Fixed bug #14050: CleanUp - CGL format of t3lib files - t3lib_positionmap
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_iconworks.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2010 Kasper Skårhøj (kasperYYYY@typo3.com)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Contains class for icon generation in the backend
29 *
30 * $Id$
31 * Revised for TYPO3 3.6 July/2003 by Kasper Skårhøj
32 * XHTML compliant
33 *
34 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
35 */
36 /**
37 * [CLASS/FUNCTION INDEX of SCRIPT]
38 *
39 *
40 *
41 * 85: class t3lib_iconWorks
42 * 100: function getIconImage($table,$row=array(),$backPath,$params='',$shaded=FALSE)
43 * 118: function getIcon($table,$row=array(),$shaded=FALSE)
44 * 264: function skinImg($backPath,$src,$wHattribs='',$outputMode=0)
45 *
46 * SECTION: Other functions
47 * 353: function makeIcon($iconfile,$mode, $user, $protectSection,$absFile,$iconFileName_stateTagged)
48 * 475: function imagecopyresized(&$im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h)
49 * 505: function imagecreatefrom($file)
50 * 522: function imagemake($im, $path)
51 *
52 * TOTAL FUNCTIONS: 7
53 * (This index is automatically created/updated by the extension "extdeveval")
54 *
55 */
56
57
58 /**
59 * Icon generation, backend
60 * This library has functions that returns - and if necessary creates - the icon for an element in TYPO3
61 *
62 * Expects global vars:
63 * - $BACK_PATH
64 * - PATH_typo3
65 * - $TCA, $PAGES_TYPES
66 *
67 *
68 * Notes:
69 * These functions are strongly related to the interface of TYPO3.
70 * The class is included in eg. init.php
71 * ALL functions called without making a class instance, eg. "t3lib_iconWorks::getIconImage()"
72 *
73 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
74 * @package TYPO3
75 * @subpackage t3lib
76 */
77 final class t3lib_iconWorks {
78
79 public static $fileSpriteIconNames = array(
80 'htm' => 'mimetypes-text-html',
81 'html' => 'mimetypes-text-html',
82 'css' => 'mimetypes-text-css',
83 'js' => 'mimetypes-text-js',
84 'csv' => 'mimetypes-text-csv',
85 'php' => 'mimetypes-text-php',
86 'php6' => 'mimetypes-text-php',
87 'php5' => 'mimetypes-text-php',
88 'php4' => 'mimetypes-text-php',
89 'php3' => 'mimetypes-text-php',
90 'inc' => 'mimetypes-text-php',
91 'ts' => 'mimetypes-text-ts',
92 'txt' => 'mimetypes-text-text',
93 'class' => 'mimetypes-text-text',
94 'tmpl' => 'mimetypes-text-text',
95 'jpg' => 'mimetypes-media-image',
96 'jpeg' => 'mimetypes-media-image',
97 'gif' => 'mimetypes-media-image',
98 'png' => 'mimetypes-media-image',
99 'bmp' => 'mimetypes-media-image',
100 'tif' => 'mimetypes-media-image',
101 'tga' => 'mimetypes-media-image',
102 'psd' => 'mimetypes-media-image',
103 'eps' => 'mimetypes-media-image',
104 'avi' => 'mimetypes-media-video',
105 'mpg' => 'mimetypes-media-video',
106 'mpeg' => 'mimetypes-media-video',
107 'mov' => 'mimetypes-media-video',
108 'wav' => 'mimetypes-media-audio',
109 'mp3' => 'mimetypes-media-audio',
110 'mid' => 'mimetypes-media-audio',
111 'swf' => 'mimetypes-media-flash',
112 'swa' => 'mimetypes-media-flash',
113 'exe' => 'mimetypes-executable-executable',
114 'com' => 'mimetypes-executable-executable',
115 't3x' => 'mimetypes-compressed',
116 't3d' => 'mimetypes-compressed',
117 'zip' => 'mimetypes-compressed',
118 'tgz' => 'mimetypes-compressed',
119 'gz' => 'mimetypes-compressed',
120 'pdf' => 'mimetypes-pdf',
121 'doc' => 'mimetypes-word',
122 'sxw' => 'mimetypes-word',
123 'rtf' => 'mimetypes-word',
124 'xls' => 'mimetypes-excel',
125 'sxc' => 'mimetypes-excel',
126 'ppt' => 'mimetypes-powerpoint',
127 'mount' => 'apps-filetree-mount',
128 'folder' => 'apps-filetree-folder-default',
129 'default' => 'mimetypes-other-other'
130 );
131
132 /**
133 * Returns an icon image tag, 18x16 pixels, based on input information.
134 * This function is recommended to use in your backend modules.
135 * Usage: 60
136 *
137 * @param string The table name
138 * @param array The table row ("enablefields" are at least needed for correct icon display and for pages records some more fields in addition!)
139 * @param string The backpath to the main TYPO3 directory (relative path back to PATH_typo3)
140 * @param string Additional attributes for the image tag
141 * @param boolean If set, the icon will be grayed/shaded
142 * @return string <img>-tag
143 * @see getIcon()
144 */
145 public static function getIconImage($table, $row = array(), $backPath, $params = '', $shaded = FALSE) {
146 $str = '<img' .
147 self::skinImg($backPath, self::getIcon($table, $row, $shaded), 'width="18" height="16"') .
148 (trim($params) ? ' ' . trim($params) : '');
149 if (!stristr($str, 'alt="')) {
150 $str .= ' alt=""';
151 }
152 $str .= ' />';
153 return $str;
154 }
155
156 /**
157 * Creates the icon for input table/row
158 * Returns filename for the image icon, relative to PATH_typo3
159 * Usage: 24
160 *
161 * @param string The table name
162 * @param array The table row ("enablefields" are at least needed for correct icon display and for pages records some more fields in addition!)
163 * @param boolean If set, the icon will be grayed/shaded
164 * @return string Icon filename
165 * @see getIconImage()
166 */
167 public static function getIcon($table, $row = array(), $shaded = FALSE) {
168 global $TCA, $PAGES_TYPES, $ICON_TYPES;
169
170 // Flags:
171 $doNotGenerateIcon = $GLOBALS['TYPO3_CONF_VARS']['GFX']['noIconProc']; // If set, the icon will NOT be generated with GDlib. Rather the icon will be looked for as [iconfilename]_X.[extension]
172 $doNotRenderUserGroupNumber = TRUE; // If set, then the usergroup number will NOT be printed unto the icon. NOTICE. the icon is generated only if a default icon for groups is not found... So effectively this is ineffective...
173
174 // Shadow:
175 if ($TCA[$table]['ctrl']['versioningWS']) {
176 switch ((int) $row['t3ver_state']) {
177 case 1:
178 return 'gfx/i/shadow_hide.png';
179 break;
180 case 2:
181 return 'gfx/i/shadow_delete.png';
182 break;
183 case 3:
184 return 'gfx/i/shadow_moveto_plh.png';
185 break;
186 case 4:
187 return 'gfx/i/shadow_moveto_pointer.png';
188 break;
189 }
190 }
191
192 // First, find the icon file name. This can depend on configuration in TCA, field values and more:
193 if ($table == 'pages') {
194 // @TODO: RFC #7370: doktype 2&5 are deprecated since TYPO3 4.2-beta1
195 if ($row['nav_hide'] && ($row['doktype'] == t3lib_pageSelect::DOKTYPE_DEFAULT || $row['doktype'] == t3lib_pageSelect::DOKTYPE_ADVANCED)) {
196 $row['doktype'] = t3lib_pageSelect::DOKTYPE_HIDE_IN_MENU;
197 } // Workaround to change the icon if "Hide in menu" was set
198
199 if (!$iconfile = $PAGES_TYPES[$row['doktype']]['icon']) {
200 $iconfile = $PAGES_TYPES['default']['icon'];
201 }
202 if ($row['module'] && $ICON_TYPES[$row['module']]['icon']) {
203 $iconfile = $ICON_TYPES[$row['module']]['icon'];
204 }
205 } else {
206 if (!$iconfile = $TCA[$table]['ctrl']['typeicons'][$row[$TCA[$table]['ctrl']['typeicon_column']]]) {
207 $iconfile = (($TCA[$table]['ctrl']['iconfile']) ? $TCA[$table]['ctrl']['iconfile'] : $table . '.gif');
208 }
209 }
210
211 // Setting path of iconfile if not already set. Default is "gfx/i/"
212 if (!strstr($iconfile, '/')) {
213 $iconfile = 'gfx/i/' . $iconfile;
214 }
215
216 // Setting the absolute path where the icon should be found as a file:
217 if (substr($iconfile, 0, 3) == '../') {
218 $absfile = PATH_site . substr($iconfile, 3);
219 } else {
220 $absfile = PATH_typo3 . $iconfile;
221 }
222
223 // Initializing variables, all booleans except otherwise stated:
224 $hidden = FALSE;
225 $timing = FALSE;
226 $futuretiming = FALSE;
227 $user = FALSE; // In fact an integer value...
228 $deleted = FALSE;
229 $protectSection = FALSE; // Set, if a page-record (only pages!) has the extend-to-subpages flag set.
230 $noIconFound = $row['_NO_ICON_FOUND'] ? TRUE : FALSE;
231 // + $shaded which is also boolean!
232
233 // Icon state based on "enableFields":
234 if (is_array($TCA[$table]['ctrl']['enablecolumns'])) {
235 $enCols = $TCA[$table]['ctrl']['enablecolumns'];
236 // If "hidden" is enabled:
237 if ($enCols['disabled']) {
238 if ($row[$enCols['disabled']]) {
239 $hidden = TRUE;
240 }
241 }
242 // If a "starttime" is set and higher than current time:
243 if ($enCols['starttime']) {
244 if ($GLOBALS['EXEC_TIME'] < intval($row[$enCols['starttime']])) {
245 $timing = TRUE;
246 // ...And if "endtime" is NOT set:
247 if (intval($row[$enCols['endtime']]) == 0) {
248 $futuretiming = TRUE;
249 }
250 }
251 }
252 // If an "endtime" is set:
253 if ($enCols['endtime']) {
254 if (intval($row[$enCols['endtime']]) > 0) {
255 if (intval($row[$enCols['endtime']]) < $GLOBALS['EXEC_TIME']) {
256 $timing = TRUE; // End-timing applies at this point.
257 } else {
258 $futuretiming = TRUE; // End-timing WILL apply in the future for this element.
259 }
260 }
261 }
262 // If a user-group field is set:
263 if ($enCols['fe_group']) {
264 $user = $row[$enCols['fe_group']];
265 if ($user && $doNotRenderUserGroupNumber) {
266 $user = 100;
267 } // Limit for user number rendering!
268 }
269 }
270
271 // If "deleted" flag is set (only when listing records which are also deleted!)
272 if ($col = $row[$TCA[$table]['ctrl']['delete']]) {
273 $deleted = TRUE;
274 }
275 // Detecting extendToSubpages (for pages only)
276 if ($table == 'pages' && $row['extendToSubpages'] && ($hidden || $timing || $futuretiming || $user)) {
277 $protectSection = TRUE;
278 }
279
280 // If ANY of the booleans are set it means we have to alter the icon:
281 if ($hidden || $timing || $futuretiming || $user || $deleted || $shaded || $noIconFound) {
282 $flags = '';
283 $string = '';
284 if ($deleted) {
285 $string = 'deleted';
286 $flags = 'd';
287 } elseif ($noIconFound) { // This is ONLY for creating icons with "?" on easily...
288 $string = 'no_icon_found';
289 $flags = 'x';
290 } else {
291 if ($hidden) {
292 $string .= 'hidden';
293 }
294 if ($timing) {
295 $string .= 'timing';
296 }
297 if (!$string && $futuretiming) {
298 $string = 'futuretiming';
299 }
300
301 $flags .=
302 ($hidden ? 'h' : '') .
303 ($timing ? 't' : '') .
304 ($futuretiming ? 'f' : '') .
305 ($user ? 'u' : '') .
306 ($protectSection ? 'p' : '') .
307 ($shaded ? 's' : '');
308 }
309
310 // Create tagged icon file name:
311 $iconFileName_stateTagged = preg_replace('/.([[:alnum:]]+)$/', '__' . $flags . '.\1', basename($iconfile));
312
313 // Check if tagged icon file name exists (a tagget icon means the icon base name with the flags added between body and extension of the filename, prefixed with underscore)
314 if (@is_file(dirname($absfile) . '/' . $iconFileName_stateTagged) || @is_file($GLOBALS['TBE_STYLES']['skinImgAutoCfg']['absDir'] . '/' . dirname($iconfile) . '/' . $iconFileName_stateTagged)) { // Look for [iconname]_xxxx.[ext]
315 return dirname($iconfile) . '/' . $iconFileName_stateTagged;
316 } elseif ($doNotGenerateIcon) { // If no icon generation can be done, try to look for the _X icon:
317 $iconFileName_X = preg_replace('/.([[:alnum:]]+)$/', '__x.\1', basename($iconfile));
318 if (@is_file(dirname($absfile) . '/' . $iconFileName_X)) {
319 return dirname($iconfile) . '/' . $iconFileName_X;
320 } else {
321 return 'gfx/i/no_icon_found.gif';
322 }
323 } else { // Otherwise, create the icon:
324 $theRes = self::makeIcon($GLOBALS['BACK_PATH'] . $iconfile, $string, $user, $protectSection, $absfile, $iconFileName_stateTagged);
325 return $theRes;
326 }
327 } else {
328 return $iconfile;
329 }
330 }
331
332 /**
333 * Returns the src=... for the input $src value OR any alternative found in $TBE_STYLES['skinImg']
334 * Used for skinning the TYPO3 backend with an alternative set of icons
335 * Usage: 336
336 *
337 * @param string Current backpath to PATH_typo3 folder
338 * @param string Icon file name relative to PATH_typo3 folder
339 * @param string Default width/height, defined like 'width="12" height="14"'
340 * @param integer Mode: 0 (zero) is default and returns src/width/height. 1 returns value of src+backpath, 2 returns value of w/h.
341 * @return string Returns ' src="[backPath][src]" [wHattribs]'
342 * @see skinImgFile()
343 */
344 public static function skinImg($backPath, $src, $wHattribs = '', $outputMode = 0) {
345
346 static $cachedSkinImages = array();
347
348 $imageId = md5($backPath . $src . $wHattribs . $outputMode);
349
350 if (isset($cachedSkinImages[$imageId])) {
351 return $cachedSkinImages[$imageId];
352 }
353 // Setting source key. If the icon is refered to inside an extension, we homogenize the prefix to "ext/":
354 $srcKey = preg_replace('/^(\.\.\/typo3conf\/ext|sysext|ext)\//', 'ext/', $src);
355 #if ($src!=$srcKey)debug(array($src, $srcKey));
356
357 // LOOKING for alternative icons:
358 if ($GLOBALS['TBE_STYLES']['skinImg'][$srcKey]) { // Slower or faster with is_array()? Could be used.
359 list($src, $wHattribs) = $GLOBALS['TBE_STYLES']['skinImg'][$srcKey];
360 } elseif ($GLOBALS['TBE_STYLES']['skinImgAutoCfg']) { // Otherwise, test if auto-detection is enabled:
361
362 // Search for alternative icon automatically:
363 $fExt = $GLOBALS['TBE_STYLES']['skinImgAutoCfg']['forceFileExtension'];
364 $scaleFactor = ($GLOBALS['TBE_STYLES']['skinImgAutoCfg']['scaleFactor'] ? $GLOBALS['TBE_STYLES']['skinImgAutoCfg']['scaleFactor'] : 1); // Scaling factor
365 $lookUpName = ($fExt ? preg_replace('/\.[[:alnum:]]+$/', '', $srcKey) . '.' . $fExt : $srcKey); // Set filename to look for
366
367 if ($fExt && !@is_file($GLOBALS['TBE_STYLES']['skinImgAutoCfg']['absDir'] . $lookUpName)) {
368 // fallback to original filename if icon with forced extension doesn't exists
369 $lookUpName = $srcKey;
370 }
371 // If file is found:
372 if (@is_file($GLOBALS['TBE_STYLES']['skinImgAutoCfg']['absDir'] . $lookUpName)) { // If there is a file...
373 $iInfo = @getimagesize($GLOBALS['TBE_STYLES']['skinImgAutoCfg']['absDir'] . $lookUpName); // Get width/height:
374
375 // Set $src and $wHattribs:
376 $src = $GLOBALS['TBE_STYLES']['skinImgAutoCfg']['relDir'] . $lookUpName;
377 $wHattribs = 'width="' . round($iInfo[0] * $scaleFactor) . '" height="' . round($iInfo[1] * $scaleFactor) . '"';
378 }
379
380 // In any case, set currect src / wHattrib - this way we make sure that an entry IS found next time we hit the function,
381 // regardless of whether it points to a alternative icon or just the current.
382 $GLOBALS['TBE_STYLES']['skinImg'][$srcKey] = array($src, $wHattribs); // Set default...
383 }
384
385 // DEBUG: This doubles the size of all icons - for testing/debugging:
386 // if (preg_match('/^width="([0-9]+)" height="([0-9]+)"$/', $wHattribs, $reg)) $wHattribs='width="'.($reg[1]*2).'" height="'.($reg[2]*2).'"';
387
388
389 // rendering disabled (greyed) icons using _i (inactive) as name suffix ("_d" is already used)
390 $matches = array();
391 $srcBasename = basename($src);
392 if (preg_match('/(.*)_i(\....)$/', $srcBasename, $matches)) {
393 $temp_path = dirname(PATH_thisScript) . '/';
394 if (!@is_file($temp_path . $backPath . $src)) {
395 $srcOrg = preg_replace('/_i' . preg_quote($matches[2]) . '$/', $matches[2], $src);
396 $src = self::makeIcon($backPath . $srcOrg, 'disabled', 0, FALSE, $temp_path . $backPath . $srcOrg, $srcBasename);
397 }
398 }
399
400
401 // Return icon source/wHattributes:
402 $output = '';
403 switch ($outputMode) {
404 case 0:
405 $output = ' src="' . $backPath . $src . '" ' . $wHattribs;
406 break;
407 case 1:
408 $output = $backPath . $src;
409 break;
410 case 2:
411 $output = $wHattribs;
412 break;
413 }
414
415 $cachedSkinImages[$imageId] = $output;
416 return $output;
417 }
418
419
420 /***********************************
421 *
422 * Other functions
423 *
424 ***********************************/
425
426 /**
427 * Creates the icon file for the function getIcon()
428 *
429 * @param string Original unprocessed Icon file, relative path to PATH_typo3
430 * @param string Mode string, eg. "deleted" or "futuretiming" determining how the icon will look
431 * @param integer The number of the fe_group record uid if applicable
432 * @param boolean Flag determines if the protected-section icon should be applied.
433 * @param string Absolute path to file from which to create the icon.
434 * @param string The filename that this icon should have had, basically [icon base name]_[flags].[extension] - used for part of temporary filename
435 * @return string Filename relative to PATH_typo3
436 * @access private
437 */
438 public static function makeIcon($iconfile, $mode, $user, $protectSection, $absFile, $iconFileName_stateTagged) {
439 $iconFileName = 'icon_' . t3lib_div::shortMD5($iconfile . '|' . $mode . '|-' . $user . '|' . $protectSection) . '_' . $iconFileName_stateTagged . '.' . ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png'] ? 'png' : 'gif');
440 $mainpath = '../typo3temp/' . $iconFileName;
441 $path = PATH_site . 'typo3temp/' . $iconFileName;
442
443
444 if (file_exists(PATH_typo3 . 'icons/' . $iconFileName)) { // Returns if found in typo3/icons/
445 return 'icons/' . $iconFileName;
446 } elseif (file_exists($path)) { // Returns if found in ../typo3temp/icons/
447 return $mainpath;
448 } else { // Makes icon:
449 if (file_exists($absFile)) {
450 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib']) {
451
452 // Create image pointer, if possible
453 $im = self::imagecreatefrom($absFile);
454 if ($im < 0) {
455 return $iconfile;
456 }
457
458 // Converting to gray scale, dimming the icon:
459 if (($mode == 'disabled') OR ($mode != 'futuretiming' && $mode != 'no_icon_found' && !(!$mode && $user))) {
460 for ($c = 0; $c < ImageColorsTotal($im); $c++) {
461 $cols = ImageColorsForIndex($im, $c);
462 $newcol = round(($cols['red'] + $cols['green'] + $cols['blue']) / 3);
463 $lighten = ($mode == 'disabled') ? 2.5 : 2;
464 $newcol = round(255 - ((255 - $newcol) / $lighten));
465 ImageColorSet($im, $c, $newcol, $newcol, $newcol);
466 }
467 }
468 // Applying user icon, if there are access control on the item:
469 if ($user) {
470 if ($user < 100) { // Apply user number only if lower than 100
471 $black = ImageColorAllocate($im, 0, 0, 0);
472 imagefilledrectangle($im, 0, 0, (($user > 10) ? 9 : 5), 8, $black);
473
474 $white = ImageColorAllocate($im, 255, 255, 255);
475 imagestring($im, 1, 1, 1, $user, $white);
476 }
477
478 $ol_im = self::imagecreatefrom($GLOBALS['BACK_PATH'] . 'gfx/overlay_group.gif');
479 if ($ol_im < 0) {
480 return $iconfile;
481 }
482
483 self::imagecopyresized($im, $ol_im, 0, 0, 0, 0, imagesx($ol_im), imagesy($ol_im), imagesx($ol_im), imagesy($ol_im));
484 }
485 // Applying overlay based on mode:
486 if ($mode) {
487 unset($ol_im);
488 switch ($mode) {
489 case 'deleted':
490 $ol_im = self::imagecreatefrom($GLOBALS['BACK_PATH'] . 'gfx/overlay_deleted.gif');
491 break;
492 case 'futuretiming':
493 $ol_im = self::imagecreatefrom($GLOBALS['BACK_PATH'] . 'gfx/overlay_timing.gif');
494 break;
495 case 'timing':
496 $ol_im = self::imagecreatefrom($GLOBALS['BACK_PATH'] . 'gfx/overlay_timing.gif');
497 break;
498 case 'hiddentiming':
499 $ol_im = self::imagecreatefrom($GLOBALS['BACK_PATH'] . 'gfx/overlay_hidden_timing.gif');
500 break;
501 case 'no_icon_found':
502 $ol_im = self::imagecreatefrom($GLOBALS['BACK_PATH'] . 'gfx/overlay_no_icon_found.gif');
503 break;
504 case 'disabled':
505 // is already greyed - nothing more
506 $ol_im = 0;
507 break;
508 case 'hidden':
509 default:
510 $ol_im = self::imagecreatefrom($GLOBALS['BACK_PATH'] . 'gfx/overlay_hidden.gif');
511 break;
512 }
513 if ($ol_im < 0) {
514 return $iconfile;
515 }
516 if ($ol_im) {
517 self::imagecopyresized($im, $ol_im, 0, 0, 0, 0, imagesx($ol_im), imagesy($ol_im), imagesx($ol_im), imagesy($ol_im));
518 }
519 }
520 // Protect-section icon:
521 if ($protectSection) {
522 $ol_im = self::imagecreatefrom($GLOBALS['BACK_PATH'] . 'gfx/overlay_sub5.gif');
523 if ($ol_im < 0) {
524 return $iconfile;
525 }
526 self::imagecopyresized($im, $ol_im, 0, 0, 0, 0, imagesx($ol_im), imagesy($ol_im), imagesx($ol_im), imagesy($ol_im));
527 }
528
529 // Create the image as file, destroy GD image and return:
530 @self::imagemake($im, $path);
531 t3lib_div::gif_compress($path, 'IM');
532 ImageDestroy($im);
533 return $mainpath;
534 } else {
535 return $iconfile;
536 }
537 } else {
538 return $GLOBALS['BACK_PATH'] . 'gfx/fileicons/default.gif';
539 }
540 }
541 }
542
543 /**
544 * The necessity of using this function for combining two images if GD is version 2 is that
545 * GD2 cannot manage to combine two indexed-color images without totally spoiling everything.
546 * In class.t3lib_stdgraphic this was solved by combining the images onto a first created true color image
547 * However it has turned out that this method will not work if the indexed png-files contains transparency.
548 * So I had to turn my attention to ImageMagick - my 'enemy of death'.
549 * And so it happend - ImageMagick is now used to combine my two indexed-color images with transparency. And that works.
550 * Of course it works only if ImageMagick is able to create valid png-images - which you cannot be sure of with older versions (still 5+)
551 * The only drawback is (apparently) that IM creates true-color png's. The transparency of these will not be shown by MSIE on windows at this time (although it's straight 0%/100% transparency!) and the file size may be larger.
552 *
553 * For parameters, see PHP function "imagecopyresized()"
554 *
555 * @param pointer see PHP function "imagecopyresized()"
556 * @param pointer see PHP function "imagecopyresized()"
557 * @param integer see PHP function "imagecopyresized()"
558 * @param integer see PHP function "imagecopyresized()"
559 * @param integer see PHP function "imagecopyresized()"
560 * @param integer see PHP function "imagecopyresized()"
561 * @param integer see PHP function "imagecopyresized()"
562 * @param integer see PHP function "imagecopyresized()"
563 * @param integer see PHP function "imagecopyresized()"
564 * @param integer see PHP function "imagecopyresized()"
565 * @return void
566 * @access private
567 */
568 public static function imagecopyresized(&$im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h) {
569 imagecopyresized($im, $cpImg, $Xstart, $Ystart, $cpImgCutX, $cpImgCutY, $w, $h, $w, $h);
570 }
571
572 /**
573 * Create new image pointer from input file (either gif/png, in case the wrong format it is converted by t3lib_div::read_png_gif())
574 *
575 * @param string Absolute filename of the image file from which to start the icon creation.
576 * @return mixed If success, image pointer, otherwise "-1"
577 * @access private
578 * @see t3lib_div::read_png_gif
579 */
580 public static function imagecreatefrom($file) {
581 $file = t3lib_div::read_png_gif($file, $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png']);
582 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png']) {
583 return $file ? imagecreatefrompng($file) : -1;
584 } else {
585 return $file ? imagecreatefromgif($file) : -1;
586 }
587 }
588
589 /**
590 * Write the icon in $im pointer to $path
591 *
592 * @param pointer Pointer to GDlib image resource
593 * @param string Absolute path to the filename in which to write the icon.
594 * @return void
595 * @access private
596 */
597 public static function imagemake($im, $path) {
598 if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png']) {
599 @ImagePng($im, $path);
600 } else {
601 @ImageGif($im, $path);
602 }
603 }
604
605
606 /**********************************************
607 * SPRITE ICON API
608 *
609 * The Sprite Icon API helps you to quickly get the HTML for any icon you want
610 * this is typically wrapped in a <span> tag with corresponding CSS classes that
611 * will be responsible for the
612 *
613 * There are three ways to use this API:
614 *
615 * 1) for any given TCA record
616 * $spriteIconHtml = t3lib_iconWorks::getSpriteIconForRecord('pages', $row);
617 *
618 * 2) for any given file
619 * $spriteIconHtml = t3lib_iconWorks::getSpriteIconForFile('myimage.png');
620 *
621 * 3) for any other icon you know the name
622 * $spriteIconHtml = t3lib_iconWorks::getSpriteIcon('actions-document-open');
623 *
624 **********************************************/
625
626 /**
627 * This generic method is used throughout the TYPO3 Backend to show icons in any variation which are not
628 * bound to any file type (see getSpriteIconForFile) or database record (see getSpriteIconForRecord)
629 *
630 * Generates a HTML tag with proper CSS classes. The TYPO3 skin has defined these CSS classes
631 * already to have a pre-defined background image, and the correct background-position to show
632 * the necessary icon.
633 *
634 * @param string $iconName the name of the icon to fetch
635 * @param array $options an associative array with additional options and attributes for the tag. by default, the key is the name of the attribute, and the value is the parameter string that is set. However, there are some additional special reserved keywords that can be used as keys: "html" (which is the HTML that will be inside the icon HTML tag), "tagName" (which is an alternative tagName than "span"), and "class" (additional class names that will be merged with the sprite icon CSS classes)
636 * @param array $overlays an associative array with the icon-name as key, and the options for this overlay as an array again (see the parameter $options again)
637 * @return string the full HTML tag (usually a <span>)
638 * @access public
639 */
640 public static function getSpriteIcon($iconName, array $options = array(), array $overlays = array()) {
641 $innerHtml = (isset($options['html']) ? $options['html'] : NULL);
642 $tagName = (isset($options['tagName']) ? $options['tagName'] : NULL);
643
644 // deal with the overlays
645 if (count($overlays)) {
646 foreach ($overlays as $overlayIconName => $overlayOptions) {
647 $overlayOptions['html'] = $innerHtml;
648 $overlayOptions['class'] = (isset($overlayOptions['class']) ? $overlayOptions['class'] . ' ' : '') . 't3-icon-overlay';
649 $innerHtml = self::getSpriteIcon($overlayIconName, $overlayOptions);
650 }
651 }
652
653 // check if whished icon is available
654 $iconName = (in_array($iconName, $GLOBALS['TBE_STYLES']['spriteIconApi']['iconsAvailable']) || $iconName == 'empty-empty' ? $iconName : 'status-status-icon-missing');
655
656 // create the CSS class
657 $options['class'] = self::getSpriteIconClasses($iconName) . (isset($options['class']) ? ' ' . $options['class'] : '');
658
659 unset($options['html']);
660 unset($options['tagName']);
661 return self::buildSpriteHtmlIconTag($options, $innerHtml, $tagName);
662 }
663
664
665 /**
666 * This method is used throughout the TYPO3 Backend to show icons for a file type
667 *
668 * Generates a HTML tag with proper CSS classes. The TYPO3 skin has defined these CSS classes
669 * already to have a pre-defined background image, and the correct background-position to show
670 * the necessary icon.
671 *
672 * @param string $fileExtension the name of the icon to fetch, can be a file extension, full file path or one of the special keywords "folder" or "mount"
673 * @param array $options an associative array with additional options and attributes for the tag. by default, the key is the name of the attribute, and the value is the parameter string that is set. However, there are some additional special reserved keywords that can be used as keys: "html" (which is the HTML that will be inside the icon HTML tag), "tagName" (which is an alternative tagName than "span"), and "class" (additional class names that will be merged with the sprite icon CSS classes)
674 * @return string the full HTML tag (usually a <span>)
675 * @access public
676 */
677 public static function getSpriteIconForFile($fileExtension, array $options = array()) {
678 $innerHtml = (isset($options['html']) ? $options['html'] : NULL);
679 $tagName = (isset($options['tagName']) ? $options['tagName'] : NULL);
680
681 // create the CSS class
682 $options['class'] = self::mapFileExtensionToSpriteIconClass($fileExtension) . (isset($options['class']) ? ' ' . $options['class'] : '');
683
684 unset($options['html']);
685 unset($options['tagName']);
686 return self::buildSpriteHtmlIconTag($options, $innerHtml, $tagName);
687 }
688
689
690 /**
691 * Generates the spriteicon css classes name for a given path or fileExtension
692 * usually called from getSpriteIconForFile or ExtJs Provider
693 *
694 * @param string fileExtension can be jpg, gif etc, but also be 'mount' or 'folder', but can also be a full path which will be resolved then
695 * @return string the string of the CSS class, see t3lib_iconworks::$fileSpriteIconNames
696 * @access private
697 */
698 public static function mapFileExtensionToSpriteIconClass($fileExtension) {
699 return self::getSpriteIconClasses(self::mapFileExtensionToSpriteIconName($fileExtension));
700 }
701
702 /**
703 * Generates the spriteicon name for a given path or fileExtension
704 * usually called from mapFileExtensionToSpriteIconClass and tceforms
705 *
706 * @param string fileExtension can be jpg, gif etc, but also be 'mount' or 'folder', but can also be a full path which will be resolved then
707 * @return string the string of the CSS class, see t3lib_iconworks::$fileSpriteIconNames
708 * @access private
709 */
710 public static function mapFileExtensionToSpriteIconName($fileExtension) {
711
712 // if the file is a whole file with name etc (mainly, if it has a "." or a "/"),
713 // then it is checked whether it is a valid directory
714 if (strpos($fileExtension, '.') !== FALSE || strpos($fileExtension, '/') !== FALSE) {
715
716 // check if it is a directory
717 $filePath = dirname(t3lib_div::getIndpEnv('SCRIPT_FILENAME')) . '/' . $GLOBALS['BACK_PATH'] . $fileExtension;
718 $path = t3lib_div::resolveBackPath($filePath);
719 if (is_dir($path) || substr($fileExtension, -1) === '/' || substr($fileExtension, -1) === '\\') {
720 $fileExtension = 'folder';
721 } else {
722 if (($pos = strrpos($fileExtension, '.')) !== FALSE) {
723 $fileExtension = strtolower(substr($fileExtension, $pos + 1));
724 } else {
725 $fileExtension = 'default';
726 }
727 }
728 }
729
730 // if the file extension is not valid
731 // then use the default one
732 if (!isset(self::$fileSpriteIconNames[$fileExtension])) {
733 $fileExtension = 'default';
734 }
735 $iconName = self::$fileSpriteIconNames[$fileExtension];
736
737 return $iconName;
738 }
739
740
741 /**
742 * This method is used throughout the TYPO3 Backend to show icons for a DB record
743 *
744 * Generates a HTML tag with proper CSS classes. The TYPO3 skin has defined these CSS classes
745 * already to have a pre-defined background image, and the correct background-position to show
746 * the necessary icon.
747 *
748 * @param string $table the TCA table name
749 * @param array $row the DB record of the TCA table
750 * @param array $options an associative array with additional options and attributes for the tag. by default, the key is the name of the attribute, and the value is the parameter string that is set. However, there are some additional special reserved keywords that can be used as keys: "html" (which is the HTML that will be inside the icon HTML tag), "tagName" (which is an alternative tagName than "span"), and "class" (additional class names that will be merged with the sprite icon CSS classes)
751 * @return string the full HTML tag (usually a <span>)
752 * @access public
753 */
754 public static function getSpriteIconForRecord($table, array $row, array $options = array()) {
755 $innerHtml = (isset($options['html']) ? $options['html'] : NULL);
756 $tagName = (isset($options['tagName']) ? $options['tagName'] : NULL);
757
758 // overlay this record icon with the status of the row
759 $overlaySpriteIconName = self::mapRecordOverlayToSpriteIconName($table, $row);
760 if ($overlaySpriteIconName) {
761 $overlayOptions = array(
762 'html' => $innerHtml,
763 'class' => 't3-icon-overlay'
764 );
765 $innerHtml = self::getSpriteIcon($overlaySpriteIconName, $overlayOptions);
766 }
767
768 // fetch the name for the CSS class, based on the $row
769 $options['class'] = self::mapRecordTypeToSpriteIconClass($table, $row) . (isset($options['class']) ? ' ' . $options['class'] : '');
770
771 unset($options['html']);
772 unset($options['tagName']);
773 return self::buildSpriteHtmlIconTag($options, $innerHtml, $tagName);
774 }
775
776
777 /**
778 * this helper functions looks up the column that is used for the type of
779 * the chosen TCA table. And then fetches the corresponding class
780 * based on the chosen iconsprite class in this TCA
781 * The TCA looks up
782 * - [ctrl][typeicon_column]
783 * -
784 * This method solely takes care of the type of this record, not any
785 * statuses, used for overlays.
786 * You should not use this directly besides if you need classes for ExtJS iconCls.
787 *
788 * see t3lib/stddb/tables.php for an example with the TCA table "pages"
789 *
790 * @param string $table the TCA table
791 * @param array $row the selected record
792 * @return string the CSS class for the sprite icon of that DB record
793 * @access private
794 **/
795 public static function mapRecordTypeToSpriteIconClass($table, array $row) {
796 return self::getSpriteIconClasses(self::mapRecordTypeToSpriteIconName($table, $row));
797 }
798
799 /**
800 * this helper functions looks up the column that is used for the type of
801 * the chosen TCA table. And then fetches the corresponding iconname
802 * based on the chosen iconsprite class in this TCA
803 * The TCA looks up
804 * - [ctrl][typeicon_column]
805 * -
806 * This method solely takes care of the type of this record, not any
807 * statuses, used for overlays.
808 * You should not use this directly besides if you need it in tceforms/core classes
809 *
810 * see t3lib/stddb/tables.php for an example with the TCA table "pages"
811 *
812 * @param string $table the TCA table
813 * @param array $row the selected record
814 * @return string the CSS class for the sprite icon of that DB record
815 * @access private
816 **/
817 public static function mapRecordTypeToSpriteIconName($table, array $row) {
818 $recordType = array();
819 $ref = NULL;
820 if (isset($GLOBALS['TCA'][$table]['ctrl']['typeicon_column'])) {
821 $column = $GLOBALS['TCA'][$table]['ctrl']['typeicon_column'];
822
823 if (isset($row[$column])) {
824 $recordType[1] = $row[$column];
825 } else {
826 $recordType[1] = 'default';
827 }
828
829 // workaround to give nav_hide pages a complete different icon
830 // although it's not a separate doctype
831 // and to give root-pages an own icon
832 if ($table === 'pages') {
833 if ($row['nav_hide']) {
834 $recordType[2] = $recordType[1] . '-hideinmenu';
835 }
836 if ($row['is_siteroot']) {
837 $recordType[3] = $recordType[1] . '-root';
838 }
839 if ($row['module']) {
840 $recordType[4] = 'contains-' . $row['module'];
841 }
842 }
843
844 if (is_array($GLOBALS['TCA'][$table]['ctrl']['typeicon_classes'])) {
845 foreach ($recordType AS $key => $type) {
846 if (isset($GLOBALS['TCA'][$table]['ctrl']['typeicon_classes'][$type])) {
847 $recordType[$key] = $GLOBALS['TCA'][$table]['ctrl']['typeicon_classes'][$type];
848 } else {
849 unset($recordType[$key]);
850 }
851 }
852 $recordType[0] = $GLOBALS['TCA'][$table]['ctrl']['typeicon_classes']['default'];
853 if (isset($GLOBALS['TCA'][$table]['ctrl']['typeicon_classes']['mask'])) {
854 $recordType[5] = str_replace('###TYPE###', $row[$column], $GLOBALS['TCA'][$table]['ctrl']['typeicon_classes']['mask']);
855 }
856 if (isset($GLOBALS['TCA'][$table]['ctrl']['typeicon_classes']['userFunc'])) {
857 $recordType[6] = t3lib_div::callUserFunction($GLOBALS['TCA'][$table]['ctrl']['typeicon_classes']['userFunc'], array('row' => $row), $ref);
858 }
859 } else {
860 foreach ($recordType AS $key => $type) {
861 $recordType[$key] = 'tcarecords-' . $table . '-' . $type;
862 }
863 $recordType[0] = 'tcarecords-' . $table . '-default';
864 }
865 } else {
866 if (is_array($GLOBALS['TCA'][$table]['ctrl']['typeicon_classes'])) {
867 $recordType[0] = $GLOBALS['TCA'][$table]['ctrl']['typeicon_classes']['default'];
868 } else {
869 $recordType[0] = 'tcarecords-' . $table . '-default';
870 }
871 }
872 krsort($recordType);
873 foreach ($recordType as $iconName) {
874 if (in_array($iconName, $GLOBALS['TBE_STYLES']['spriteIconApi']['iconsAvailable'])) {
875 return $iconName;
876 }
877 }
878 return 'status-status-icon-missing';
879 }
880
881
882 /**
883 * this helper functions checks if the DB record ($row) has any special status
884 * based on the TCA settings like hidden, starttime etc, and then returns a specific
885 * Sprite icon class for the overlay of this DB record
886 * This method solely takes care of the overlay of this record, not any type
887 *
888 * Please note that this only returns one overlay, one status, that is prioritized
889 * by $GLOBALS['TYPO3_CONF_VARS']['BE']['spriteIconRecordOverlayPriorities']
890 * We wanted to not have these icons blown over by tons of overlays, so this is limited
891 * to just one.
892 *
893 * see t3lib/config_default.php for the default options, you will find
894 * $GLOBALS['TYPO3_CONF_VARS']['BE']['spriteIconRecordOverlayNames'] that shows
895 * the list of CSS classes that will be used for the sprites, mapped to the statuses here
896 *
897 * @param string $table the TCA table
898 * @param array $row the selected record
899 * @return string the CSS class for the sprite icon of that DB record
900 * @access private
901 */
902 public static function mapRecordOverlayToSpriteIconName($table, array $row) {
903 $tcaCtrl = $GLOBALS['TCA'][$table]['ctrl'];
904
905 // Calculate for a given record the actual visibility at the moment
906 $status = array(
907 'hidden' => FALSE,
908 'starttime' => FALSE,
909 'endtime' => FALSE,
910 'futureendtime' => FALSE,
911 'fe_group' => FALSE,
912 'deleted' => FALSE,
913 'protectedSection' => FALSE,
914 'nav_hide' => ($row['nav_hide'] ? TRUE : FALSE),
915 'noIconFound' => ($row['_NO_ICON_FOUND'] ? TRUE : FALSE),
916 );
917
918 // Icon state based on "enableFields":
919 if (is_array($tcaCtrl['enablecolumns'])) {
920 $enCols = $tcaCtrl['enablecolumns'];
921 // If "hidden" is enabled:
922 if ($tcaCtrl['enablecolumns']['disabled'] && $row[$tcaCtrl['enablecolumns']['disabled']]) {
923 $status['hidden'] = TRUE;
924 }
925 // If a "starttime" is set and higher than current time:
926 if ($tcaCtrl['enablecolumns']['starttime'] && $GLOBALS['EXEC_TIME'] < intval($row[$tcaCtrl['enablecolumns']['starttime']])) {
927 $status['starttime'] = TRUE;
928 }
929
930 // If an "endtime" is set
931 if ($tcaCtrl['enablecolumns']['endtime']) {
932 if (intval($row[$tcaCtrl['enablecolumns']['endtime']]) > 0) {
933 if (intval($row[$tcaCtrl['enablecolumns']['endtime']]) < $GLOBALS['EXEC_TIME']) {
934 // End-timing applies at this point.
935 $status['endtime'] = TRUE;
936 } else {
937 // End-timing WILL apply in the future for this element.
938 $status['futureendtime'] = TRUE;
939 }
940 }
941 }
942 // If a user-group field is set
943 if ($tcaCtrl['enablecolumns']['fe_group'] && $row[$tcaCtrl['enablecolumns']['fe_group']]) {
944 $status['fe_group'] = TRUE;
945 }
946 }
947
948 // If "deleted" flag is set (only when listing records which are also deleted!)
949 if ($row[$tcaCtrl['delete']]) {
950 $status['deleted'] = TRUE;
951 }
952
953 // Detecting extendToSubpages (for pages only)
954 if ($table == 'pages' && $row['extendToSubpages']) {
955 $status['protectedSection'] = TRUE;
956 }
957
958
959 // now only show the status with the highest priority
960 $priorities = $GLOBALS['TBE_STYLES']['spriteIconApi']['spriteIconRecordOverlayPriorities'];
961
962 $iconName = '';
963 foreach ($priorities as $priority) {
964 if ($status[$priority]) {
965 $iconName = $GLOBALS['TBE_STYLES']['spriteIconApi']['spriteIconRecordOverlayNames'][$priority];
966 break;
967 }
968 }
969
970 return $iconName;
971 }
972
973
974 /**
975 * generic method to create the final CSS classes based on the sprite icon name
976 * with the base class and splits the name into parts
977 * is usually called by the methods that are responsible for fetching the names
978 * out of the file name, or the record type
979 *
980 * @param string $name iconname like 'actions-document-new'
981 * @return string a list of all CSS classes needed for the HTML tag
982 * @access public
983 */
984 public static function getSpriteIconClasses($iconName) {
985 $cssClasses = $baseCssClass = 't3-icon';
986 $parts = explode('-', $iconName);
987
988 if (count($parts) > 1) {
989 // will be something like "t3-icon-actions"
990 $cssClasses .= ' ' . ($baseCssClass . '-' . $parts[0]);
991 // will be something like "t3-icon-actions-document"
992 $cssClasses .= ' ' . ($baseCssClass . '-' . $parts[0] . '-' . $parts[1]);
993 // will be something like "t3-icon-document-new"
994 $cssClasses .= ' ' . ($baseCssClass . '-' . substr($iconName, strlen($parts[0]) + 1));
995 }
996 return $cssClasses;
997 }
998
999
1000 /**
1001 * low level function that generates the HTML tag for the sprite icon
1002 * is usually called by the three API classes (getSpriteIcon, getSpriteIconForFile, getSpriteIconForRecord)
1003 * it does not care about classes or anything else, but just plainly builds the HTML tag
1004 *
1005 * @param array $tagAttributes an associative array of additional tagAttributes for the HTML tag
1006 * @param string $innerHtml (optional) the content within the tag, a "&nbsp;" by default
1007 * @param string $tagName (optional) the name of the HTML element that should be used (span by default)
1008 */
1009 protected static function buildSpriteHtmlIconTag(array $tagAttributes, $innerHtml = NULL, $tagName = NULL) {
1010 $innerHtml = ($innerHtml === NULL ? '&nbsp;' : $innerHtml);
1011 $tagName = ($tagName === NULL ? 'span' : $tagName);
1012 $attributes = '';
1013 foreach ($tagAttributes as $attribute => $value) {
1014 $attributes .= ' ' . htmlspecialchars($attribute) . '="' . htmlspecialchars($value) . '"';
1015 }
1016 return '<' . $tagName . $attributes . '>' . $innerHtml . '</' . $tagName . '>';
1017 }
1018
1019 }
1020
1021 ?>