[!!!][TASK] Use native trigger_error and ErrorHandler for deprecations
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Imaging / IconRegistry.php
1 <?php
2 namespace TYPO3\CMS\Core\Imaging;
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 Symfony\Component\Finder\Finder;
18 use TYPO3\CMS\Core\Cache\CacheManager;
19 use TYPO3\CMS\Core\Exception;
20 use TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider;
21 use TYPO3\CMS\Core\Imaging\IconProvider\FontawesomeIconProvider;
22 use TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider;
23 use TYPO3\CMS\Core\SingletonInterface;
24 use TYPO3\CMS\Core\Utility\GeneralUtility;
25 use TYPO3\CMS\Core\Utility\StringUtility;
26
27 /**
28 * Class IconRegistry, which makes it possible to register custom icons
29 * from within an extension.
30 */
31 class IconRegistry implements SingletonInterface
32 {
33 /**
34 * @var bool
35 */
36 protected $fullInitialized = false;
37
38 /**
39 * @var bool
40 */
41 protected $tcaInitialized = false;
42
43 /**
44 * @var bool
45 */
46 protected $flagsInitialized = false;
47
48 /**
49 * @var bool
50 */
51 protected $moduleIconsInitialized = false;
52
53 /**
54 * @var bool
55 */
56 protected $backendIconsInitialized = false;
57
58 /**
59 * Registered icons
60 *
61 * @var array
62 */
63 protected $icons = [];
64
65 /**
66 * Paths to backend icon folders for automatic registration
67 *
68 * @var string[]
69 */
70 protected $backendIconPaths = [
71 'EXT:backend/Resources/Public/Icons/',
72 'EXT:core/Resources/Public/Icons/T3Icons/',
73 'EXT:impexp/Resources/Public/Icons/',
74 'EXT:install/Resources/Public/Icons'
75 ];
76
77 /**
78 * List of allowed icon file extensions with their Provider class
79 *
80 * @var string[]
81 */
82 protected $backendIconAllowedExtensionsWithProvider = [
83 'png' => BitmapIconProvider::class,
84 'svg' => SvgIconProvider::class
85 ];
86
87 /**
88 * manually registered icons
89 * hopefully obsolete one day
90 *
91 * @var array
92 */
93 protected $staticIcons = [
94
95 /**
96 * Important Information:
97 *
98 * Icons are maintained in an external repository, if new icons are needed
99 * please request them at: https://github.com/wmdbsystems/T3.Icons/issues
100 */
101
102 // Actions
103 'actions-wizard-link' => [
104 'provider' => FontawesomeIconProvider::class,
105 'options' => [
106 'name' => 'link'
107 ]
108 ],
109 'actions-wizard-rte' => [
110 'provider' => FontawesomeIconProvider::class,
111 'options' => [
112 'name' => 'arrows-alt'
113 ]
114 ],
115
116 // Apps
117 'apps-pagetree-category-toggle-hide-checked' => [
118 'provider' => FontawesomeIconProvider::class,
119 'options' => [
120 'name' => 'check-square'
121 ]
122 ],
123
124 // Module
125 'module-web' => [
126 'provider' => FontawesomeIconProvider::class,
127 'options' => [
128 'name' => 'file-o'
129 ]
130 ],
131 'module-file' => [
132 'provider' => FontawesomeIconProvider::class,
133 'options' => [
134 'name' => 'image'
135 ]
136 ],
137 'module-tools' => [
138 'provider' => FontawesomeIconProvider::class,
139 'options' => [
140 'name' => 'rocket'
141 ]
142 ],
143 'module-system' => [
144 'provider' => FontawesomeIconProvider::class,
145 'options' => [
146 'name' => 'plug'
147 ]
148 ],
149 'module-help' => [
150 'provider' => FontawesomeIconProvider::class,
151 'options' => [
152 'name' => 'question-circle'
153 ]
154 ],
155
156 // Status
157 'status-dialog-information' => [
158 'provider' => FontawesomeIconProvider::class,
159 'options' => [
160 'name' => 'exclamation-circle'
161 ]
162 ],
163 'status-dialog-ok' => [
164 'provider' => FontawesomeIconProvider::class,
165 'options' => [
166 'name' => 'check-circle',
167 ]
168 ],
169 'status-dialog-notification' => [
170 'provider' => FontawesomeIconProvider::class,
171 'options' => [
172 'name' => 'exclamation-circle'
173 ]
174 ],
175 'status-dialog-warning' => [
176 'provider' => FontawesomeIconProvider::class,
177 'options' => [
178 'name' => 'exclamation-triangle'
179 ]
180 ],
181 'status-dialog-error' => [
182 'provider' => FontawesomeIconProvider::class,
183 'options' => [
184 'name' => 'exclamation-circle'
185 ]
186 ],
187 'status-status-checked' => [
188 'provider' => FontawesomeIconProvider::class,
189 'options' => [
190 'name' => 'check',
191 ]
192 ],
193 'status-status-current' => [
194 'provider' => FontawesomeIconProvider::class,
195 'options' => [
196 'name' => 'caret-right',
197 ]
198 ],
199 'status-status-sorting-asc' => [
200 'provider' => FontawesomeIconProvider::class,
201 'options' => [
202 'name' => 'caret-up',
203 ]
204 ],
205 'status-status-sorting-desc' => [
206 'provider' => FontawesomeIconProvider::class,
207 'options' => [
208 'name' => 'caret-down',
209 ]
210 ],
211 'status-status-sorting-light-asc' => [
212 'provider' => FontawesomeIconProvider::class,
213 'options' => [
214 'name' => 'caret-up',
215 ]
216 ],
217 'status-status-sorting-light-desc' => [
218 'provider' => FontawesomeIconProvider::class,
219 'options' => [
220 'name' => 'caret-down',
221 ]
222 ],
223 'status-status-permission-granted' => [
224 'provider' => FontawesomeIconProvider::class,
225 'options' => [
226 'name' => 'check',
227 ]
228 ],
229 'status-status-permission-denied' => [
230 'provider' => FontawesomeIconProvider::class,
231 'options' => [
232 'name' => 'times',
233 ]
234 ],
235
236 // Extensions
237 'extensions-extensionmanager-update-script' => [
238 'provider' => FontawesomeIconProvider::class,
239 'options' => [
240 'name' => 'refresh',
241 ]
242 ],
243 'extensions-scheduler-run-task' => [
244 'provider' => FontawesomeIconProvider::class,
245 'options' => [
246 'name' => 'play-circle',
247 ]
248 ],
249 'extensions-scheduler-run-task-cron' => [
250 'provider' => FontawesomeIconProvider::class,
251 'options' => [
252 'name' => 'clock-o',
253 ]
254 ],
255 'generate-ws-preview-link' => [
256 'provider' => BitmapIconProvider::class,
257 'options' => [
258 'source' => 'EXT:workspaces/Resources/Public/Images/generate-ws-preview-link.png'
259 ]
260 ],
261
262 // Empty
263 'empty-empty' => [
264 'provider' => FontawesomeIconProvider::class,
265 'options' => [
266 'name' => 'empty-empty',
267 ]
268 ],
269
270 // System Information
271 'sysinfo-php-version' => [
272 'provider' => FontawesomeIconProvider::class,
273 'options' => [
274 'name' => 'code'
275 ]
276 ],
277 'sysinfo-database' => [
278 'provider' => FontawesomeIconProvider::class,
279 'options' => [
280 'name' => 'database'
281 ]
282 ],
283 'sysinfo-application-context' => [
284 'provider' => FontawesomeIconProvider::class,
285 'options' => [
286 'name' => 'tasks'
287 ]
288 ],
289 'sysinfo-composer-mode' => [
290 'provider' => FontawesomeIconProvider::class,
291 'options' => [
292 'name' => 'music'
293 ]
294 ],
295 'sysinfo-git' => [
296 'provider' => FontawesomeIconProvider::class,
297 'options' => [
298 'name' => 'git'
299 ]
300 ],
301 'sysinfo-webserver' => [
302 'provider' => FontawesomeIconProvider::class,
303 'options' => [
304 'name' => 'server'
305 ]
306 ],
307 'sysinfo-os-linux' => [
308 'provider' => FontawesomeIconProvider::class,
309 'options' => [
310 'name' => 'linux'
311 ]
312 ],
313 'sysinfo-os-apple' => [
314 'provider' => FontawesomeIconProvider::class,
315 'options' => [
316 'name' => 'apple'
317 ]
318 ],
319 'sysinfo-os-windows' => [
320 'provider' => FontawesomeIconProvider::class,
321 'options' => [
322 'name' => 'windows'
323 ]
324 ],
325
326 // Sysnote
327 'sysnote-type-0' => [
328 'provider' => FontawesomeIconProvider::class,
329 'options' => [
330 'name' => 'sticky-note-o'
331 ]
332 ],
333 'sysnote-type-1' => [
334 'provider' => FontawesomeIconProvider::class,
335 'options' => [
336 'name' => 'cog'
337 ]
338 ],
339 'sysnote-type-2' => [
340 'provider' => FontawesomeIconProvider::class,
341 'options' => [
342 'name' => 'code'
343 ]
344 ],
345 'sysnote-type-3' => [
346 'provider' => FontawesomeIconProvider::class,
347 'options' => [
348 'name' => 'thumb-tack'
349 ]
350 ],
351 'sysnote-type-4' => [
352 'provider' => FontawesomeIconProvider::class,
353 'options' => [
354 'name' => 'check-square'
355 ]
356 ],
357
358 // Flags will be auto-registered after we have the SVG files
359 'flags-multiple' => [
360 'provider' => BitmapIconProvider::class,
361 'options' => [
362 'source' => 'EXT:core/Resources/Public/Icons/Flags/multiple.png'
363 ]
364 ],
365 'flags-catalonia' => [
366 'provider' => BitmapIconProvider::class,
367 'options' => [
368 'source' => 'EXT:core/Resources/Public/Icons/Flags/catalonia.png'
369 ]
370 ],
371 'flags-en-us-gb' => [
372 'provider' => BitmapIconProvider::class,
373 'options' => [
374 'source' => 'EXT:core/Resources/Public/Icons/Flags/en_us-gb.png'
375 ]
376 ],
377 ];
378
379 /**
380 * Mapping of file extensions to mimetypes
381 *
382 * @var string[]
383 */
384 protected $fileExtensionMapping = [
385 'htm' => 'mimetypes-text-html',
386 'html' => 'mimetypes-text-html',
387 'css' => 'mimetypes-text-css',
388 'js' => 'mimetypes-text-js',
389 'csv' => 'mimetypes-text-csv',
390 'php' => 'mimetypes-text-php',
391 'php6' => 'mimetypes-text-php',
392 'php5' => 'mimetypes-text-php',
393 'php4' => 'mimetypes-text-php',
394 'php3' => 'mimetypes-text-php',
395 'inc' => 'mimetypes-text-php',
396 'ts' => 'mimetypes-text-ts',
397 'typoscript' => 'mimetypes-text-typoscript',
398 'txt' => 'mimetypes-text-text',
399 'class' => 'mimetypes-text-text',
400 'tmpl' => 'mimetypes-text-text',
401 'jpg' => 'mimetypes-media-image',
402 'jpeg' => 'mimetypes-media-image',
403 'gif' => 'mimetypes-media-image',
404 'png' => 'mimetypes-media-image',
405 'bmp' => 'mimetypes-media-image',
406 'tif' => 'mimetypes-media-image',
407 'tiff' => 'mimetypes-media-image',
408 'tga' => 'mimetypes-media-image',
409 'psd' => 'mimetypes-media-image',
410 'eps' => 'mimetypes-media-image',
411 'ai' => 'mimetypes-media-image',
412 'svg' => 'mimetypes-media-image',
413 'pcx' => 'mimetypes-media-image',
414 'avi' => 'mimetypes-media-video',
415 'mpg' => 'mimetypes-media-video',
416 'mpeg' => 'mimetypes-media-video',
417 'mov' => 'mimetypes-media-video',
418 'vimeo' => 'mimetypes-media-video-vimeo',
419 'youtube' => 'mimetypes-media-video-youtube',
420 'wav' => 'mimetypes-media-audio',
421 'mp3' => 'mimetypes-media-audio',
422 'ogg' => 'mimetypes-media-audio',
423 'flac' => 'mimetypes-media-audio',
424 'opus' => 'mimetypes-media-audio',
425 'mid' => 'mimetypes-media-audio',
426 'swf' => 'mimetypes-media-flash',
427 'swa' => 'mimetypes-media-flash',
428 'exe' => 'mimetypes-application',
429 'com' => 'mimetypes-application',
430 't3x' => 'mimetypes-compressed',
431 't3d' => 'mimetypes-compressed',
432 'zip' => 'mimetypes-compressed',
433 'tgz' => 'mimetypes-compressed',
434 'gz' => 'mimetypes-compressed',
435 'pdf' => 'mimetypes-pdf',
436 'doc' => 'mimetypes-word',
437 'dot' => 'mimetypes-word',
438 'docm' => 'mimetypes-word',
439 'docx' => 'mimetypes-word',
440 'dotm' => 'mimetypes-word',
441 'dotx' => 'mimetypes-word',
442 'sxw' => 'mimetypes-word',
443 'rtf' => 'mimetypes-word',
444 'xls' => 'mimetypes-excel',
445 'xlsm' => 'mimetypes-excel',
446 'xlsx' => 'mimetypes-excel',
447 'xltm' => 'mimetypes-excel',
448 'xltx' => 'mimetypes-excel',
449 'sxc' => 'mimetypes-excel',
450 'pps' => 'mimetypes-powerpoint',
451 'ppsx' => 'mimetypes-powerpoint',
452 'ppt' => 'mimetypes-powerpoint',
453 'pptm' => 'mimetypes-powerpoint',
454 'pptx' => 'mimetypes-powerpoint',
455 'potm' => 'mimetypes-powerpoint',
456 'potx' => 'mimetypes-powerpoint',
457 'mount' => 'apps-filetree-mount',
458 'folder' => 'apps-filetree-folder-default',
459 'default' => 'mimetypes-other-other',
460 ];
461
462 /**
463 * Mapping of mime types to icons
464 *
465 * @var string[]
466 */
467 protected $mimeTypeMapping = [
468 'video/*' => 'mimetypes-media-video',
469 'audio/*' => 'mimetypes-media-audio',
470 'image/*' => 'mimetypes-media-image',
471 'text/*' => 'mimetypes-text-text',
472 ];
473
474 /**
475 * Array of deprecated icons, add deprecated icons to this array and remove it from registry
476 * - Index of this array contains the deprecated icon
477 * - Value of each entry may contain a possible new identifier
478 *
479 * Example:
480 * [
481 * 'deprecated-icon-identifier' => 'new-icon-identifier',
482 * 'another-deprecated-identifier' => null,
483 * ]
484 *
485 * @var array
486 */
487 protected $deprecatedIcons = [
488 'status-warning-lock' => 'warning-lock',
489 'status-warning-in-use' => 'warning-in-use',
490 'status-status-reference-hard' => 'status-reference-hard',
491 'status-status-reference-soft' => 'status-reference-soft',
492 'status-status-edit-read-only' => 'status-edit-read-only',
493 'extensions-workspaces-generatepreviewlink' => 'generate-ws-preview-link',
494 ];
495
496 /**
497 * @var string
498 */
499 protected $defaultIconIdentifier = 'default-not-found';
500
501 /**
502 * The constructor
503 */
504 public function __construct()
505 {
506 $this->initialize();
507 }
508
509 /**
510 * Initialize the registry
511 * This method can be called multiple times, depending on initialization status.
512 * In some cases e.g. TCA is not available, the method must be called multiple times.
513 */
514 protected function initialize()
515 {
516 if (!$this->backendIconsInitialized) {
517 $this->getCachedBackendIcons();
518 }
519 if (!$this->tcaInitialized && !empty($GLOBALS['TCA'])) {
520 $this->registerTCAIcons();
521 }
522 if (!$this->moduleIconsInitialized && !empty($GLOBALS['TBE_MODULES'])) {
523 $this->registerModuleIcons();
524 }
525 if (!$this->flagsInitialized) {
526 $this->registerFlags();
527 }
528 if ($this->backendIconsInitialized
529 && $this->tcaInitialized
530 && $this->moduleIconsInitialized
531 && $this->flagsInitialized) {
532 $this->fullInitialized = true;
533 }
534 }
535
536 /**
537 * Retrieve the icons from cache render them when not cached yet
538 */
539 protected function getCachedBackendIcons()
540 {
541 $cacheIdentifier = 'BackendIcons_' . sha1((TYPO3_version . PATH_site . 'BackendIcons'));
542 /** @var \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend $assetsCache */
543 $assetsCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('assets');
544 $cacheEntry = $assetsCache->get($cacheIdentifier);
545
546 if ($cacheEntry !== false) {
547 $this->icons = $cacheEntry;
548 } else {
549 $this->registerBackendIcons();
550 // all found icons should now be present, for historic reasons now merge w/ the statically declared icons
551 $this->icons = array_merge($this->icons, $this->staticIcons);
552 $assetsCache->set($cacheIdentifier, $this->icons);
553 }
554 // if there's now at least one icon registered, consider it successful
555 if (is_array($this->icons) && (count($this->icons) >= count($this->staticIcons))) {
556 $this->backendIconsInitialized = true;
557 }
558 }
559
560 /**
561 * Automatically find and register the core backend icons
562 */
563 protected function registerBackendIcons()
564 {
565 foreach ($this->backendIconPaths as $iconPath) {
566 $absoluteIconFolderPath = GeneralUtility::getFileAbsFileName($iconPath);
567 if ($absoluteIconFolderPath === '' || !is_readable($absoluteIconFolderPath)) {
568 // maybe EXT:path could not be resolved, then ignore
569 continue;
570 }
571
572 $finder = new Finder();
573 $finder
574 ->files()
575 ->in($absoluteIconFolderPath)
576 ->name('/\.(' . implode('|', array_keys($this->backendIconAllowedExtensionsWithProvider)) . ')$/');
577
578 foreach ($finder as $iconFile) {
579 $iconOptions = [
580 'source' => $iconPath . GeneralUtility::fixWindowsFilePath($iconFile->getRelativePathname())
581 ];
582 // kind of hotfix for now, needs a nicer concept later
583 if (strpos($iconFile->getFilename(), 'spinner') === 0) {
584 $iconOptions['spinning'] = true;
585 }
586
587 $this->registerIcon(
588 $iconFile->getBasename('.' . $iconFile->getExtension()),
589 $this->backendIconAllowedExtensionsWithProvider[$iconFile->getExtension()],
590 $iconOptions
591 );
592 }
593 }
594 }
595
596 /**
597 * @param string $identifier
598 * @return bool
599 */
600 public function isRegistered($identifier)
601 {
602 if (!$this->fullInitialized) {
603 $this->initialize();
604 }
605 return isset($this->icons[$identifier]);
606 }
607
608 /**
609 * @param string $identifier
610 * @return bool
611 */
612 public function isDeprecated($identifier)
613 {
614 return isset($this->deprecatedIcons[$identifier]);
615 }
616
617 /**
618 * @return string
619 */
620 public function getDefaultIconIdentifier()
621 {
622 return $this->defaultIconIdentifier;
623 }
624
625 /**
626 * Registers an icon to be available inside the Icon Factory
627 *
628 * @param string $identifier
629 * @param string $iconProviderClassName
630 * @param array $options
631 *
632 * @throws \InvalidArgumentException
633 */
634 public function registerIcon($identifier, $iconProviderClassName, array $options = [])
635 {
636 if (!in_array(IconProviderInterface::class, class_implements($iconProviderClassName), true)) {
637 throw new \InvalidArgumentException('An IconProvider must implement '
638 . IconProviderInterface::class, 1437425803);
639 }
640 $this->icons[$identifier] = [
641 'provider' => $iconProviderClassName,
642 'options' => $options
643 ];
644 }
645
646 /**
647 * Register an icon for a file extension
648 *
649 * @param string $fileExtension
650 * @param string $iconIdentifier
651 */
652 public function registerFileExtension($fileExtension, $iconIdentifier)
653 {
654 $this->fileExtensionMapping[$fileExtension] = $iconIdentifier;
655 }
656
657 /**
658 * Register an icon for a mime-type
659 *
660 * @param string $mimeType
661 * @param string $iconIdentifier
662 */
663 public function registerMimeTypeIcon($mimeType, $iconIdentifier)
664 {
665 $this->mimeTypeMapping[$mimeType] = $iconIdentifier;
666 }
667
668 /**
669 * Fetches the configuration provided by registerIcon()
670 *
671 * @param string $identifier the icon identifier
672 * @return mixed
673 * @throws Exception
674 */
675 public function getIconConfigurationByIdentifier($identifier)
676 {
677 if (!$this->fullInitialized) {
678 $this->initialize();
679 }
680 if (!$this->isRegistered($identifier)) {
681 throw new Exception('Icon with identifier "' . $identifier . '" is not registered"', 1437425804);
682 }
683 if ($this->isDeprecated($identifier)) {
684 $replacement = $this->deprecatedIcons[$identifier];
685 if (!empty($replacement)) {
686 $message = 'The icon "%s" is deprecated since TYPO3 v9 and will be removed in TYPO3 v10. Please use "%s" instead.';
687 $arguments = [$replacement];
688 } else {
689 $message = 'The icon "%s" is deprecated since TYPO3 v9 and will be removed in TYPO3 v10.';
690 $arguments = [];
691 }
692 trigger_error(vsprintf($message, $arguments), E_USER_DEPRECATED);
693 }
694 return $this->icons[$identifier];
695 }
696
697 /**
698 * @return array
699 */
700 public function getAllRegisteredIconIdentifiers()
701 {
702 if (!$this->fullInitialized) {
703 $this->initialize();
704 }
705 return array_keys($this->icons);
706 }
707
708 /**
709 * @param string $fileExtension
710 * @return string
711 */
712 public function getIconIdentifierForFileExtension($fileExtension)
713 {
714 // If the file extension is not valid use the default one
715 if (!isset($this->fileExtensionMapping[$fileExtension])) {
716 $fileExtension = 'default';
717 }
718 return $this->fileExtensionMapping[$fileExtension];
719 }
720
721 /**
722 * Get iconIdentifier for given mimeType
723 *
724 * @param string $mimeType
725 * @return string|null Returns null if no icon is registered for the mimeType
726 */
727 public function getIconIdentifierForMimeType($mimeType)
728 {
729 if (!isset($this->mimeTypeMapping[$mimeType])) {
730 return null;
731 }
732 return $this->mimeTypeMapping[$mimeType];
733 }
734
735 /**
736 * Load icons from TCA for each table and add them as "tcarecords-XX" to $this->icons
737 */
738 protected function registerTCAIcons()
739 {
740 $resultArray = [];
741
742 $tcaTables = array_keys($GLOBALS['TCA']);
743 // check every table in the TCA, if an icon is needed
744 foreach ($tcaTables as $tableName) {
745 // This method is only needed for TCA tables where typeicon_classes are not configured
746 if (is_array($GLOBALS['TCA'][$tableName])) {
747 $tcaCtrl = $GLOBALS['TCA'][$tableName]['ctrl'];
748 $iconIdentifier = 'tcarecords-' . $tableName . '-default';
749 if (isset($this->icons[$iconIdentifier])) {
750 continue;
751 }
752 if (isset($tcaCtrl['iconfile'])) {
753 $resultArray[$iconIdentifier] = $tcaCtrl['iconfile'];
754 }
755 }
756 }
757
758 foreach ($resultArray as $iconIdentifier => $iconFilePath) {
759 $iconProviderClass = $this->detectIconProvider($iconFilePath);
760 $this->icons[$iconIdentifier] = [
761 'provider' => $iconProviderClass,
762 'options' => [
763 'source' => $iconFilePath
764 ]
765 ];
766 }
767 $this->tcaInitialized = true;
768 }
769
770 /**
771 * Register module icons
772 */
773 protected function registerModuleIcons()
774 {
775 $moduleConfiguration = $GLOBALS['TBE_MODULES']['_configuration'];
776 foreach ($moduleConfiguration as $moduleKey => $singleModuleConfiguration) {
777 $iconIdentifier = !empty($singleModuleConfiguration['iconIdentifier'])
778 ? $singleModuleConfiguration['iconIdentifier']
779 : null;
780
781 if ($iconIdentifier !== null) {
782 // iconIdentifier found, icon is registered, continue
783 continue;
784 }
785
786 $iconPath = !empty($singleModuleConfiguration['icon'])
787 ? $singleModuleConfiguration['icon']
788 : null;
789 $iconProviderClass = $this->detectIconProvider($iconPath);
790 $iconIdentifier = 'module-icon-' . $moduleKey;
791
792 $this->icons[$iconIdentifier] = [
793 'provider' => $iconProviderClass,
794 'options' => [
795 'source' => $iconPath
796 ]
797 ];
798 }
799 $this->moduleIconsInitialized = true;
800 }
801
802 /**
803 * Register flags
804 */
805 protected function registerFlags()
806 {
807 $iconFolder = 'EXT:core/Resources/Public/Icons/Flags/PNG/';
808 $files = [
809 'AC', 'AD', 'AE', 'AF', 'AG', 'AI', 'AL', 'AM', 'AN', 'AO', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AW', 'AX', 'AZ',
810 'BA', 'BB', 'BD', 'BE', 'BF', 'BG', 'BH', 'BI', 'BJ', 'BL', 'BM', 'BN', 'BO', 'BQ', 'BR', 'BS', 'BT', 'BV', 'BW', 'BY', 'BZ',
811 'CA', 'CC', 'CD', 'CF', 'CG', 'CH', 'CI', 'CK', 'CL', 'CM', 'CN', 'CO', 'CP', 'CR', 'CS', 'CU', 'CV', 'CW', 'CX', 'CY', 'CZ',
812 'DE', 'DG', 'DJ', 'DK', 'DM', 'DO', 'DZ',
813 'EA', 'EC', 'EE', 'EG', 'EH', 'ER', 'ES', 'ET', 'EU',
814 'FI', 'FJ', 'FK', 'FM', 'FO', 'FR',
815 'GA', 'GB-ENG', 'GB-NIR', 'GB-SCT', 'GB-WLS', 'GB', 'GD', 'GE', 'GF', 'GG', 'GH', 'GI', 'GL', 'GM', 'GN', 'GP', 'GQ', 'GR', 'GS', 'GT', 'GU', 'GW', 'GY',
816 'HK', 'HM', 'HN', 'HR', 'HT', 'HU',
817 'IC', 'ID', 'IE', 'IL', 'IM', 'IN', 'IO', 'IQ', 'IR', 'IS', 'IT',
818 'JE', 'JM', 'JO', 'JP',
819 'KE', 'KG', 'KH', 'KI', 'KM', 'KN', 'KP', 'KR', 'KW', 'KY', 'KZ',
820 'LA', 'LB', 'LC', 'LI', 'LK', 'LR', 'LS', 'LT', 'LU', 'LV', 'LY',
821 'MA', 'MC', 'MD', 'ME', 'MF', 'MG', 'MH', 'MK', 'ML', 'MM', 'MN', 'MO', 'MP', 'MQ', 'MR', 'MS', 'MT', 'MU', 'MV', 'MW', 'MX', 'MY', 'MZ',
822 'NA', 'NC', 'NE', 'NF', 'NG', 'NI', 'NL', 'NO', 'NP', 'NR', 'NU', 'NZ',
823 'OM',
824 'PA', 'PE', 'PF', 'PG', 'PH', 'PK', 'PL', 'PM', 'PN', 'PR', 'PS', 'PT', 'PW', 'PY',
825 'QA', 'QC',
826 'RE', 'RO', 'RS', 'RU', 'RW',
827 'SA', 'SB', 'SC', 'SD', 'SE', 'SG', 'SH', 'SI', 'SJ', 'SK', 'SL', 'SM', 'SN', 'SO', 'SR', 'SS', 'ST', 'SV', 'SX', 'SY', 'SZ',
828 'TA', 'TC', 'TD', 'TF', 'TG', 'TH', 'TJ', 'TK', 'TL', 'TM', 'TN', 'TO', 'TR', 'TT', 'TV', 'TW', 'TZ',
829 'UA', 'UG', 'UM', 'US', 'UY', 'UZ',
830 'VA', 'VC', 'VE', 'VG', 'VI', 'VN', 'VU',
831 'WF', 'WS',
832 'XK',
833 'YE', 'YT',
834 'ZA', 'ZM', 'ZW'
835 ];
836 foreach ($files as $file) {
837 $identifier = strtolower($file);
838 $this->icons['flags-' . $identifier] = [
839 'provider' => BitmapIconProvider::class,
840 'options' => [
841 'source' => $iconFolder . $file . '.png'
842 ]
843 ];
844 }
845 $this->flagsInitialized = true;
846 }
847
848 /**
849 * Detect the IconProvider of an icon
850 *
851 * @param string $iconReference
852 * @return string
853 */
854 public function detectIconProvider($iconReference)
855 {
856 if (StringUtility::endsWith(strtolower($iconReference), 'svg')) {
857 return SvgIconProvider::class;
858 }
859 return BitmapIconProvider::class;
860 }
861 }