Commit 5fad4f42 authored by Benni Mack's avatar Benni Mack Committed by Andreas Fernandez
Browse files

[FEATURE] Register Icons via Service Container

Custom icons from extensions can now be registered
via EXT:my_extension/Configuration/Icons.php.

These files are now loaded and parsed during build-time,
and stored in the core cache.

Resolves: #94692
Releases: master
Change-Id: I9f919510b8913103288e56e824c8a0148e045ad6
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/70178

Tested-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Reviewed-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
parent 34c57726
<?php
// Register icons not being part of TYPO3.Icons repository
return [
'status-edit-read-only' => [
'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider::class,
'source' => 'EXT:backend/Resources/Public/Icons/status-edit-read-only.png'
],
'warning-in-use' => [
'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider::class,
'source' => 'EXT:backend/Resources/Public/Icons/warning-in-use.png'
],
'warning-lock' => [
'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider::class,
'source' => 'EXT:backend/Resources/Public/Icons/warning-lock.png'
],
];
......@@ -33,24 +33,6 @@ $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['backend']['previewRendererResolver'] = \
"@import 'EXT:backend/Configuration/TsConfig/Page/Mod/Wizards/NewContentElement.tsconfig'"
);
// Register icons not being part of TYPO3.Icons repository
$iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\IconRegistry::class);
$iconRegistry->registerIcon(
'status-edit-read-only',
\TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider::class,
['source' => 'EXT:backend/Resources/Public/Icons/status-edit-read-only.png']
);
$iconRegistry->registerIcon(
'warning-in-use',
\TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider::class,
['source' => 'EXT:backend/Resources/Public/Icons/warning-in-use.png']
);
$iconRegistry->registerIcon(
'warning-lock',
\TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider::class,
['source' => 'EXT:backend/Resources/Public/Icons/warning-lock.png']
);
// Register BackendLayoutDataProvider for PageTs
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['BackendLayoutDataProvider']['pagets'] = \TYPO3\CMS\Backend\Provider\PageTsBackendLayoutDataProvider::class;
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauthgroup.php']['backendUserLogin']['sendEmailOnLogin'] = \TYPO3\CMS\Backend\Security\EmailLoginNotification::class . '->emailAtLogin';
......
......@@ -51,6 +51,7 @@ abstract class AbstractServiceProvider implements ServiceProviderInterface
return [
'middlewares' => [ static::class, 'configureMiddlewares' ],
'backend.routes' => [ static::class, 'configureBackendRoutes' ],
'icons' => [ static::class, 'configureIcons' ],
];
}
......@@ -105,6 +106,19 @@ abstract class AbstractServiceProvider implements ServiceProviderInterface
return $routes;
}
public static function configureIcons(ContainerInterface $container, ArrayObject $icons, string $path = null): ArrayObject
{
$path = $path ?? static::getPackagePath();
$iconsFileNameForPackage = $path . 'Configuration/Icons.php';
if (file_exists($iconsFileNameForPackage)) {
$definedIconsInPackage = require $iconsFileNameForPackage;
if (is_array($definedIconsInPackage)) {
$icons->exchangeArray(array_merge($icons->getArrayCopy(), $definedIconsInPackage));
}
}
return $icons;
}
/**
* Create an instance of a class. Supports auto injection of the logger.
*
......
......@@ -24,6 +24,8 @@ use Symfony\Component\Console\Command\HelpCommand;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface as SymfonyEventDispatcherInterface;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\DependencyInjection\ContainerBuilder;
use TYPO3\CMS\Core\Imaging\IconRegistry;
use TYPO3\CMS\Core\Information\Typo3Version;
use TYPO3\CMS\Core\Package\AbstractServiceProvider;
use TYPO3\SymfonyPsrEventDispatcherAdapter\EventDispatcherAdapter as SymfonyEventDispatcher;
......@@ -80,6 +82,7 @@ class ServiceProvider extends AbstractServiceProvider
TimeTracker\TimeTracker::class => [ static::class, 'getTimeTracker' ],
TypoScript\Parser\ConstantConfigurationParser::class => [ static::class, 'getTypoScriptConstantConfigurationParser' ],
TypoScript\TypoScriptService::class => [ static::class, 'getTypoScriptService' ],
'icons' => [ static::class, 'getIcons' ],
'middlewares' => [ static::class, 'getMiddlewares' ],
];
}
......@@ -88,6 +91,7 @@ class ServiceProvider extends AbstractServiceProvider
{
return [
Console\CommandRegistry::class => [ static::class, 'configureCommands' ],
Imaging\IconRegistry::class => [ static::class, 'configureIconRegistry' ],
EventDispatcherInterface::class => [ static::class, 'provideFallbackEventDispatcher' ],
EventDispatcher\ListenerProvider::class => [ static::class, 'extendEventListenerProvider' ],
] + parent::getExtensions();
......@@ -225,6 +229,37 @@ class ServiceProvider extends AbstractServiceProvider
]);
}
public static function configureIconRegistry(ContainerInterface $container, IconRegistry $iconRegistry): IconRegistry
{
$cache = $container->get('cache.core');
$cacheIdentifier = 'Icons_' . sha1((string)(new Typo3Version()) . Environment::getProjectPath());
$iconsFromPackages = $cache->require($cacheIdentifier);
if ($iconsFromPackages === false) {
$iconsFromPackages = $container->get('icons')->getArrayCopy();
$cache->set($cacheIdentifier, 'return ' . var_export($iconsFromPackages, true) . ';');
}
foreach ($iconsFromPackages as $icon => $options) {
$provider = $options['provider'] ?? null;
unset($options['provider']);
$options ??= [];
if ($provider === null && ($options['source'] ?? false)) {
$provider = $iconRegistry->detectIconProvider($options['source']);
}
if ($provider === null) {
continue;
}
$iconRegistry->registerIcon($icon, $provider, $options);
}
return $iconRegistry;
}
public static function getIcons(ContainerInterface $container): ArrayObject
{
return new ArrayObject();
}
public static function getFontawesomeIconProvider(ContainerInterface $container): Imaging\IconProvider\FontawesomeIconProvider
{
return self::new($container, Imaging\IconProvider\FontawesomeIconProvider::class, [
......
.. include:: ../../Includes.txt
=========================================================
Feature: #94692 - Registering Icons via Service Container
=========================================================
See :issue:`94692`
Description
===========
Extensions can now register their custom icons via
a configuration file placed in `Configuration/Icons.php` of their
extension directory, e.g. `typo3conf/ext/my_extension/Configuration/Icons.php`.
Each file needs to return a flat PHP configuration array, with
custom options used for the IconRegistry to register a new icon.
Example:
.. code-block:: php
<?php
return [
'myicon' => [
'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class,
'source' => 'EXT:my_extension/Resources/Public/Icons/myicon.svg'
]
];
Impact
======
Using the new approach improves the loading speed of every request
as the registration can be handled at once and cached
during warmup of the core caches.
In addition, extension authors' `ext_localconf.php` files are
drastically reduced, as extension authors have a better overview
and a better separation of concerns when registering custom
functionality.
.. index:: PHP-API, ext:core
\ No newline at end of file
<?php
return [
'status-reference-hard' => [
'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider::class,
'source' => 'EXT:impexp/Resources/Public/Icons/status-reference-hard.png'
],
'status-reference-soft' => [
'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider::class,
'source' => 'EXT:impexp/Resources/Public/Icons/status-reference-soft.png'
]
];
......@@ -2,18 +2,5 @@
defined('TYPO3') or die();
// Register icons not being part of TYPO3.Icons repository
$iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\IconRegistry::class);
$iconRegistry->registerIcon(
'status-reference-hard',
\TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider::class,
['source' => 'EXT:impexp/Resources/Public/Icons/status-reference-hard.png']
);
$iconRegistry->registerIcon(
'status-reference-soft',
\TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider::class,
['source' => 'EXT:impexp/Resources/Public/Icons/status-reference-soft.png']
);
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/backend.php']['constructPostProcess'][] = \TYPO3\CMS\Impexp\Hook\BackendControllerHook::class . '->addJavaScript';
$GLOBALS['TYPO3_CONF_VARS']['BE']['ContextMenu']['ItemProviders'][1486418735] = \TYPO3\CMS\Impexp\ContextMenu\ItemProvider::class;
......@@ -92,6 +92,7 @@ class ServiceProvider extends AbstractServiceProvider
{
return [
'backend.routes' => [ static::class, 'configureBackendRoutes' ],
'icons' => [ static::class, 'configureIcons' ],
CommandRegistry::class => [ static::class, 'configureCommands' ],
];
}
......
<?php
return [
'module-install-environment' => [
'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class,
'source' => 'EXT:install/Resources/Public/Icons/module-install-environment.svg'
],
'module-install-maintenance' => [
'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class,
'source' => 'EXT:install/Resources/Public/Icons/module-install-maintenance.svg'
],
'module-install-settings' => [
'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class,
'source' => 'EXT:install/Resources/Public/Icons/module-install-settings.svg'
],
'module-install-upgrade' => [
'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class,
'source' => 'EXT:install/Resources/Public/Icons/module-install-upgrade.svg'
],
];
......@@ -24,22 +24,6 @@ $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['backendUserL
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['sysLogChannel']
= \TYPO3\CMS\Install\Updates\SysLogChannel::class;
$iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\IconRegistry::class);
$icons = [
'module-install-environment' => 'EXT:install/Resources/Public/Icons/module-install-environment.svg',
'module-install-maintenance' => 'EXT:install/Resources/Public/Icons/module-install-maintenance.svg',
'module-install-settings' => 'EXT:install/Resources/Public/Icons/module-install-settings.svg',
'module-install-upgrade' => 'EXT:install/Resources/Public/Icons/module-install-upgrade.svg',
];
foreach ($icons as $iconIdentifier => $source) {
$iconRegistry->registerIcon(
$iconIdentifier,
\TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class,
['source' => $source]
);
}
// Register report module additions
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['reports']['tx_reports']['status']['providers']['typo3'][] = \TYPO3\CMS\Install\Report\InstallStatusReport::class;
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['reports']['tx_reports']['status']['providers']['security'][] = \TYPO3\CMS\Install\Report\SecurityStatusReport::class;
......
<?php
return [
'mimetypes-x-sys_redirect' => [
'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class,
'source' => 'EXT:redirects/Resources/Public/Icons/mimetypes-x-sys_redirect.svg'
]
];
......@@ -14,13 +14,6 @@ $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['tcaDatabaseRe
],
];
\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\IconRegistry::class)
->registerIcon(
'mimetypes-x-sys_redirect',
\TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class,
['source' => 'EXT:redirects/Resources/Public/Icons/mimetypes-x-sys_redirect.svg']
);
// Add validation call for form field source_host and source_path
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][\TYPO3\CMS\Redirects\Evaluation\SourceHost::class] = '';
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment