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