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