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