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