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