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