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