ec1d6ef4c23238adc493932b52a7eb9f14fd620b
[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 $deprecationMessage = vsprintf($message, $arguments);
693 GeneralUtility::deprecationLog($deprecationMessage);
694 }
695 return $this->icons[$identifier];
696 }
697
698 /**
699 * @return array
700 */
701 public function getAllRegisteredIconIdentifiers()
702 {
703 if (!$this->fullInitialized) {
704 $this->initialize();
705 }
706 return array_keys($this->icons);
707 }
708
709 /**
710 * @param string $fileExtension
711 * @return string
712 */
713 public function getIconIdentifierForFileExtension($fileExtension)
714 {
715 // If the file extension is not valid use the default one
716 if (!isset($this->fileExtensionMapping[$fileExtension])) {
717 $fileExtension = 'default';
718 }
719 return $this->fileExtensionMapping[$fileExtension];
720 }
721
722 /**
723 * Get iconIdentifier for given mimeType
724 *
725 * @param string $mimeType
726 * @return string|null Returns null if no icon is registered for the mimeType
727 */
728 public function getIconIdentifierForMimeType($mimeType)
729 {
730 if (!isset($this->mimeTypeMapping[$mimeType])) {
731 return null;
732 }
733 return $this->mimeTypeMapping[$mimeType];
734 }
735
736 /**
737 * Load icons from TCA for each table and add them as "tcarecords-XX" to $this->icons
738 */
739 protected function registerTCAIcons()
740 {
741 $resultArray = [];
742
743 $tcaTables = array_keys($GLOBALS['TCA']);
744 // check every table in the TCA, if an icon is needed
745 foreach ($tcaTables as $tableName) {
746 // This method is only needed for TCA tables where typeicon_classes are not configured
747 if (is_array($GLOBALS['TCA'][$tableName])) {
748 $tcaCtrl = $GLOBALS['TCA'][$tableName]['ctrl'];
749 $iconIdentifier = 'tcarecords-' . $tableName . '-default';
750 if (isset($this->icons[$iconIdentifier])) {
751 continue;
752 }
753 if (isset($tcaCtrl['iconfile'])) {
754 $resultArray[$iconIdentifier] = $tcaCtrl['iconfile'];
755 }
756 }
757 }
758
759 foreach ($resultArray as $iconIdentifier => $iconFilePath) {
760 $iconProviderClass = $this->detectIconProvider($iconFilePath);
761 $this->icons[$iconIdentifier] = [
762 'provider' => $iconProviderClass,
763 'options' => [
764 'source' => $iconFilePath
765 ]
766 ];
767 }
768 $this->tcaInitialized = true;
769 }
770
771 /**
772 * Register module icons
773 */
774 protected function registerModuleIcons()
775 {
776 $moduleConfiguration = $GLOBALS['TBE_MODULES']['_configuration'];
777 foreach ($moduleConfiguration as $moduleKey => $singleModuleConfiguration) {
778 $iconIdentifier = !empty($singleModuleConfiguration['iconIdentifier'])
779 ? $singleModuleConfiguration['iconIdentifier']
780 : null;
781
782 if ($iconIdentifier !== null) {
783 // iconIdentifier found, icon is registered, continue
784 continue;
785 }
786
787 $iconPath = !empty($singleModuleConfiguration['icon'])
788 ? $singleModuleConfiguration['icon']
789 : null;
790 $iconProviderClass = $this->detectIconProvider($iconPath);
791 $iconIdentifier = 'module-icon-' . $moduleKey;
792
793 $this->icons[$iconIdentifier] = [
794 'provider' => $iconProviderClass,
795 'options' => [
796 'source' => $iconPath
797 ]
798 ];
799 }
800 $this->moduleIconsInitialized = true;
801 }
802
803 /**
804 * Register flags
805 */
806 protected function registerFlags()
807 {
808 $iconFolder = 'EXT:core/Resources/Public/Icons/Flags/PNG/';
809 $files = [
810 'AC', 'AD', 'AE', 'AF', 'AG', 'AI', 'AL', 'AM', 'AN', 'AO', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AW', 'AX', 'AZ',
811 'BA', 'BB', 'BD', 'BE', 'BF', 'BG', 'BH', 'BI', 'BJ', 'BL', 'BM', 'BN', 'BO', 'BQ', 'BR', 'BS', 'BT', 'BV', 'BW', 'BY', 'BZ',
812 'CA', 'CC', 'CD', 'CF', 'CG', 'CH', 'CI', 'CK', 'CL', 'CM', 'CN', 'CO', 'CP', 'CR', 'CS', 'CU', 'CV', 'CW', 'CX', 'CY', 'CZ',
813 'DE', 'DG', 'DJ', 'DK', 'DM', 'DO', 'DZ',
814 'EA', 'EC', 'EE', 'EG', 'EH', 'ER', 'ES', 'ET', 'EU',
815 'FI', 'FJ', 'FK', 'FM', 'FO', 'FR',
816 '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',
817 'HK', 'HM', 'HN', 'HR', 'HT', 'HU',
818 'IC', 'ID', 'IE', 'IL', 'IM', 'IN', 'IO', 'IQ', 'IR', 'IS', 'IT',
819 'JE', 'JM', 'JO', 'JP',
820 'KE', 'KG', 'KH', 'KI', 'KM', 'KN', 'KP', 'KR', 'KW', 'KY', 'KZ',
821 'LA', 'LB', 'LC', 'LI', 'LK', 'LR', 'LS', 'LT', 'LU', 'LV', 'LY',
822 'MA', 'MC', 'MD', 'ME', 'MF', 'MG', 'MH', 'MK', 'ML', 'MM', 'MN', 'MO', 'MP', 'MQ', 'MR', 'MS', 'MT', 'MU', 'MV', 'MW', 'MX', 'MY', 'MZ',
823 'NA', 'NC', 'NE', 'NF', 'NG', 'NI', 'NL', 'NO', 'NP', 'NR', 'NU', 'NZ',
824 'OM',
825 'PA', 'PE', 'PF', 'PG', 'PH', 'PK', 'PL', 'PM', 'PN', 'PR', 'PS', 'PT', 'PW', 'PY',
826 'QA', 'QC',
827 'RE', 'RO', 'RS', 'RU', 'RW',
828 'SA', 'SB', 'SC', 'SD', 'SE', 'SG', 'SH', 'SI', 'SJ', 'SK', 'SL', 'SM', 'SN', 'SO', 'SR', 'SS', 'ST', 'SV', 'SX', 'SY', 'SZ',
829 'TA', 'TC', 'TD', 'TF', 'TG', 'TH', 'TJ', 'TK', 'TL', 'TM', 'TN', 'TO', 'TR', 'TT', 'TV', 'TW', 'TZ',
830 'UA', 'UG', 'UM', 'US', 'UY', 'UZ',
831 'VA', 'VC', 'VE', 'VG', 'VI', 'VN', 'VU',
832 'WF', 'WS',
833 'XK',
834 'YE', 'YT',
835 'ZA', 'ZM', 'ZW'
836 ];
837 foreach ($files as $file) {
838 $identifier = strtolower($file);
839 $this->icons['flags-' . $identifier] = [
840 'provider' => BitmapIconProvider::class,
841 'options' => [
842 'source' => $iconFolder . $file . '.png'
843 ]
844 ];
845 }
846 $this->flagsInitialized = true;
847 }
848
849 /**
850 * Detect the IconProvider of an icon
851 *
852 * @param string $iconReference
853 * @return string
854 */
855 public function detectIconProvider($iconReference)
856 {
857 if (StringUtility::endsWith(strtolower($iconReference), 'svg')) {
858 return SvgIconProvider::class;
859 }
860 return BitmapIconProvider::class;
861 }
862 }