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