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