TYPO3 CMS  TYPO3_6-2
IconUtility.php
Go to the documentation of this file.
1 <?php
3 
19 
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 
113  static protected $spriteIconCache = array();
114 
128  static public function getIconImage($table, $row = array(), $backPath, $params = '', $shaded = FALSE) {
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 
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'])) {
158  return 'gfx/i/shadow_hide.png';
159  break;
161  return 'gfx/i/shadow_delete.png';
162  break;
164  return 'gfx/i/shadow_moveto_plh.png';
165  break;
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 
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  ***********************************/
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 
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 
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 
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)) {
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  **********************************************/
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 
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 
659  static public function mapFileExtensionToSpriteIconClass($fileExtension) {
660  return self::getSpriteIconClasses(self::mapFileExtensionToSpriteIconName($fileExtension));
661  }
662 
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 
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 
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()->isBrowsable() ||
790  !$resource->getStorage()->checkFolderActionPermission('add', $resource)
791  ) {
792  $overlays['status-overlay-locked'] = array();
793  }
794  }
795 
796 
797 
798  // File
799  } else {
800  $iconName = self::mapFileExtensionToSpriteIconName($resource->getExtension());
801 
802  if ($resource instanceof \TYPO3\CMS\Core\Resource\File && $resource->isMissing()) {
803  $overlays['status-overlay-missing'] = array();
804  }
805  }
806 
807  // Hook: allow some other process to influence the choice of icon and overlays
808  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_iconworks.php']['overrideResourceIcon'])) {
809  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_iconworks.php']['overrideResourceIcon'] as $classRef) {
810  $hookObject = GeneralUtility::getUserObj($classRef);
811  if (!$hookObject instanceof IconUtilityOverrideResourceIconHookInterface) {
812  throw new \UnexpectedValueException('$hookObject must implement interface TYPO3\\CMS\\Backend\\Utility\\IconUtilityOverrideResourceIconHookInterface', 1393574895);
813  }
814  $hookObject->overrideResourceIcon($resource, $iconName, $options, $overlays);
815  }
816  }
817 
818  unset($options['mount-root']);
819  unset($options['folder-open']);
820  return self::getSpriteIcon($iconName, $options, $overlays);
821  }
822 
841  static public function mapRecordTypeToSpriteIconClass($table, array $row) {
842  return self::getSpriteIconClasses(self::mapRecordTypeToSpriteIconName($table, $row));
843  }
844 
863  static public function mapRecordTypeToSpriteIconName($table, array $row) {
864  $recordType = array();
865  $ref = NULL;
866  if (isset($GLOBALS['TCA'][$table]['ctrl']['typeicon_column'])) {
867  $column = $GLOBALS['TCA'][$table]['ctrl']['typeicon_column'];
868  if (isset($row[$column])) {
869  $recordType[1] = $row[$column];
870  } else {
871  $recordType[1] = 'default';
872  }
873  // Workaround to give nav_hide pages a complete different icon
874  // Although it's not a separate doctype
875  // and to give root-pages an own icon
876  if ($table === 'pages') {
877  if ($row['nav_hide']) {
878  $recordType[2] = $recordType[1] . '-hideinmenu';
879  }
880  if ($row['is_siteroot']) {
881  $recordType[3] = $recordType[1] . '-root';
882  }
883  if ($row['module']) {
884  $recordType[4] = 'contains-' . $row['module'];
885  }
886  }
887  if (is_array($GLOBALS['TCA'][$table]['ctrl']['typeicon_classes'])) {
888  foreach ($recordType as $key => $type) {
889  if (isset($GLOBALS['TCA'][$table]['ctrl']['typeicon_classes'][$type])) {
890  $recordType[$key] = $GLOBALS['TCA'][$table]['ctrl']['typeicon_classes'][$type];
891  } else {
892  unset($recordType[$key]);
893  }
894  }
895  $recordType[0] = $GLOBALS['TCA'][$table]['ctrl']['typeicon_classes']['default'];
896  if (isset($GLOBALS['TCA'][$table]['ctrl']['typeicon_classes']['mask'])) {
897  $recordType[5] = str_replace('###TYPE###', $row[$column], $GLOBALS['TCA'][$table]['ctrl']['typeicon_classes']['mask']);
898  }
899  if (isset($GLOBALS['TCA'][$table]['ctrl']['typeicon_classes']['userFunc'])) {
900  $parameters = array('row' => $row);
901  $recordType[6] = GeneralUtility::callUserFunction($GLOBALS['TCA'][$table]['ctrl']['typeicon_classes']['userFunc'], $parameters, $ref);
902  }
903  } else {
904  foreach ($recordType as &$type) {
905  $type = 'tcarecords-' . $table . '-' . $type;
906  }
907  unset($type);
908  $recordType[0] = 'tcarecords-' . $table . '-default';
909  }
910  } else {
911  if (is_array($GLOBALS['TCA'][$table]['ctrl']['typeicon_classes'])) {
912  $recordType[0] = $GLOBALS['TCA'][$table]['ctrl']['typeicon_classes']['default'];
913  } else {
914  $recordType[0] = 'tcarecords-' . $table . '-default';
915  }
916  }
917  krsort($recordType);
918  if (is_array($GLOBALS['TBE_STYLES']['spriteIconApi']['iconsAvailable'])) {
919  foreach ($recordType as $iconName) {
920  if (in_array($iconName, $GLOBALS['TBE_STYLES']['spriteIconApi']['iconsAvailable'])) {
921  return $iconName;
922  }
923  }
924  }
925  return 'status-status-icon-missing';
926  }
927 
948  static public function mapRecordOverlayToSpriteIconName($table, array $row) {
949  $tcaCtrl = $GLOBALS['TCA'][$table]['ctrl'];
950  // Calculate for a given record the actual visibility at the moment
951  $status = array(
952  'hidden' => FALSE,
953  'starttime' => FALSE,
954  'endtime' => FALSE,
955  'futureendtime' => FALSE,
956  'fe_group' => FALSE,
957  'deleted' => FALSE,
958  'protectedSection' => FALSE,
959  'nav_hide' => $row['nav_hide'] ? TRUE : FALSE,
960  'noIconFound' => $row['_NO_ICON_FOUND'] ? TRUE : FALSE
961  );
962  // Icon state based on "enableFields":
963  if (is_array($tcaCtrl['enablecolumns'])) {
964  $enCols = $tcaCtrl['enablecolumns'];
965  // If "hidden" is enabled:
966  if ($tcaCtrl['enablecolumns']['disabled'] && $row[$tcaCtrl['enablecolumns']['disabled']]) {
967  $status['hidden'] = TRUE;
968  }
969  // If a "starttime" is set and higher than current time:
970  if ($tcaCtrl['enablecolumns']['starttime'] && $GLOBALS['EXEC_TIME'] < (int)$row[$tcaCtrl['enablecolumns']['starttime']]) {
971  $status['starttime'] = TRUE;
972  }
973  // If an "endtime" is set
974  if ($tcaCtrl['enablecolumns']['endtime']) {
975  if ((int)$row[$tcaCtrl['enablecolumns']['endtime']] > 0) {
976  if ((int)$row[$tcaCtrl['enablecolumns']['endtime']] < $GLOBALS['EXEC_TIME']) {
977  // End-timing applies at this point.
978  $status['endtime'] = TRUE;
979  } else {
980  // End-timing WILL apply in the future for this element.
981  $status['futureendtime'] = TRUE;
982  }
983  }
984  }
985  // If a user-group field is set
986  if ($tcaCtrl['enablecolumns']['fe_group'] && $row[$tcaCtrl['enablecolumns']['fe_group']]) {
987  $status['fe_group'] = TRUE;
988  }
989  }
990  // If "deleted" flag is set (only when listing records which are also deleted!)
991  if ($row[$tcaCtrl['delete']]) {
992  $status['deleted'] = TRUE;
993  }
994  // Detecting extendToSubpages (for pages only)
995  if ($table == 'pages' && $row['extendToSubpages']) {
996  $status['protectedSection'] = TRUE;
997  }
998  // Hook: allow some other process to influence the choice of icon overlay
999  // The method called receives the table name, the current row and the current status array as parameters
1000  // The status array should be passed as a reference and in order to be modified within the hook
1001  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_iconworks.php']['overrideIconOverlay'])) {
1002  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_iconworks.php']['overrideIconOverlay'] as $classRef) {
1003  $hookObject = GeneralUtility::getUserObj($classRef);
1004  if (method_exists($hookObject, 'overrideIconOverlay')) {
1005  $hookObject->overrideIconOverlay($table, $row, $status);
1006  }
1007  }
1008  }
1009  // Now only show the status with the highest priority
1010  $priorities = $GLOBALS['TBE_STYLES']['spriteIconApi']['spriteIconRecordOverlayPriorities'];
1011  $iconName = '';
1012  if (is_array($priorities)) {
1013  foreach ($priorities as $priority) {
1014  if ($status[$priority]) {
1015  $iconName = $GLOBALS['TBE_STYLES']['spriteIconApi']['spriteIconRecordOverlayNames'][$priority];
1016  break;
1017  }
1018  }
1019  }
1020  return $iconName;
1021  }
1022 
1032  static public function getSpriteIconClasses($iconName) {
1033  $cssClasses = ($baseCssClass = 't3-icon');
1034  $parts = explode('-', $iconName);
1035  if (count($parts) > 1) {
1036  // Will be something like "t3-icon-actions"
1037  $cssClasses .= ' ' . ($baseCssClass . '-' . $parts[0]);
1038  // Will be something like "t3-icon-actions-document"
1039  $cssClasses .= ' ' . ($baseCssClass . '-' . $parts[0] . '-' . $parts[1]);
1040  // Will be something like "t3-icon-document-new"
1041  $cssClasses .= ' ' . ($baseCssClass . '-' . substr($iconName, (strlen($parts[0]) + 1)));
1042  }
1043  return $cssClasses;
1044  }
1045 
1056  static protected function buildSpriteHtmlIconTag(array $tagAttributes, $innerHtml = NULL, $tagName = NULL) {
1057  $innerHtml = $innerHtml === NULL ? '&nbsp;' : $innerHtml;
1058  $tagName = $tagName === NULL ? 'span' : $tagName;
1059  $attributes = '';
1060  foreach ($tagAttributes as $attribute => $value) {
1061  $attributes .= ' ' . htmlspecialchars($attribute) . '="' . htmlspecialchars($value) . '"';
1062  }
1063  return '<' . $tagName . $attributes . '>' . $innerHtml . '</' . $tagName . '>';
1064  }
1065 
1066 }
static buildSpriteHtmlIconTag(array $tagAttributes, $innerHtml=NULL, $tagName=NULL)
static skinImg($backPath, $src, $wHattribs='', $outputMode=0)
$parameters
Definition: FileDumpEID.php:15
static getSpriteIconForResource(\TYPO3\CMS\Core\Resource\ResourceInterface $resource, array $options=array(), array $overlays=array())
static mapRecordTypeToSpriteIconName($table, array $row)
static mapFileExtensionToSpriteIconName($fileExtension)
static getUserObj($classRef, $checkPrefix='', $silent=FALSE)
static mapRecordOverlayToSpriteIconName($table, array $row)
static fixPermissions($path, $recursive=FALSE)
static mapRecordTypeToSpriteIconClass($table, array $row)
static callUserFunction($funcName, &$params, &$ref, $checkPrefix='', $errorMode=0)
static read_png_gif($theFile, $output_png=FALSE)
static getSpriteIconForRecord($table, array $row, array $options=array())
static getIconImage($table, $row=array(), $backPath, $params='', $shaded=FALSE)
static mapFileExtensionToSpriteIconClass($fileExtension)
static getIcon($table, $row=array(), $shaded=FALSE)
static imagecopyresized(&$destinationImage, $sourceImage, $destinationX, $destinationY, $sourceX, $sourceY, $destinationWidth, $destinationHeight, $sourceWidth, $sourceHeight)
static gif_compress($theFile, $type)
static getSpriteIcon($iconName, array $options=array(), array $overlays=array())
static makeIcon($iconfile, $mode, $user, $protectSection, $absFile, $iconFileName_stateTagged)
static getSpriteIconForFile($fileExtension, array $options=array())
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]