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