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