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