From f52d6c60ff938496e04db38343abdb0cf0737ca2 Mon Sep 17 00:00:00 2001 From: Daniel Windloff <daniel.jc.windloff@googlemail.com> Date: Sat, 20 Nov 2021 11:15:34 +0100 Subject: [PATCH] [!!!][FEATURE] Automatically register toolbar items as container services Toolbar items are now automatically tagged and registered, based on the implemented `ToolbarItemInterface`, using the autoconfiguration feature from the DI container. The registration via `$GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems']` has been removed. Resolves: #96041 Related: #62928 Releases: master Change-Id: Ic3d84752f30444d5a6be67ecbfe39e525c68e9ac Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/72241 Tested-by: Oliver Bartsch <bo@cedev.de> Tested-by: core-ci <typo3@b13.com> Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de> Reviewed-by: Oliver Bartsch <bo@cedev.de> Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de> --- .../Classes/Controller/BackendController.php | 42 ++------------ .../Classes/Toolbar/ToolbarItemsRegistry.php | 58 +++++++++++++++++++ .../sysext/backend/Configuration/Services.php | 2 + .../backend/Configuration/Services.yaml | 4 ++ typo3/sysext/backend/ext_localconf.php | 13 ----- .../Configuration/DefaultConfiguration.php | 1 - ...eaking-96041-ToolbarItemsRegisterByTag.rst | 45 ++++++++++++++ ...6041-ImproveBackendToolbarRegistration.rst | 32 ++++++++++ .../Php/ArrayDimensionMatcher.php | 5 ++ .../Classes/Service/OpenDocumentService.php | 2 + .../Unit/Service/OpenDocumentServiceTest.php | 1 + typo3/sysext/opendocs/ext_localconf.php | 1 - typo3/sysext/workspaces/ext_localconf.php | 3 - 13 files changed, 155 insertions(+), 54 deletions(-) create mode 100644 typo3/sysext/backend/Classes/Toolbar/ToolbarItemsRegistry.php create mode 100644 typo3/sysext/core/Documentation/Changelog/12.0/Breaking-96041-ToolbarItemsRegisterByTag.rst create mode 100644 typo3/sysext/core/Documentation/Changelog/12.0/Feature-96041-ImproveBackendToolbarRegistration.rst diff --git a/typo3/sysext/backend/Classes/Controller/BackendController.php b/typo3/sysext/backend/Classes/Controller/BackendController.php index 508351f1f54a..e9305acc3cb3 100644 --- a/typo3/sysext/backend/Classes/Controller/BackendController.php +++ b/typo3/sysext/backend/Classes/Controller/BackendController.php @@ -24,6 +24,7 @@ use TYPO3\CMS\Backend\Routing\RouteRedirect; use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Backend\Template\ModuleTemplateFactory; use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface; +use TYPO3\CMS\Backend\Toolbar\ToolbarItemsRegistry; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; use TYPO3\CMS\Core\Configuration\ExtensionConfiguration; use TYPO3\CMS\Core\Http\HtmlResponse; @@ -71,6 +72,7 @@ class BackendController protected UriBuilder $uriBuilder; protected ModuleLoader $moduleLoader; protected ModuleTemplateFactory $moduleTemplateFactory; + protected ToolbarItemsRegistry $toolbarItemsRegistry; /** * @var \SplObjectStorage @@ -84,7 +86,8 @@ class BackendController PageRenderer $pageRenderer, ModuleLoader $moduleLoader, BackendModuleRepository $backendModuleRepository, - ModuleTemplateFactory $moduleTemplateFactory + ModuleTemplateFactory $moduleTemplateFactory, + ToolbarItemsRegistry $toolbarItemsRegistry ) { $javaScriptRenderer = $pageRenderer->getJavaScriptRenderer(); $this->getLanguageService()->includeLLFile('EXT:core/Resources/Private/Language/locallang_misc.xlf'); @@ -94,6 +97,7 @@ class BackendController $this->typo3Version = $typo3Version; $this->pageRenderer = $pageRenderer; $this->moduleLoader = $moduleLoader; + $this->toolbarItemsRegistry = $toolbarItemsRegistry; $this->moduleLoader->observeWorkspaces = true; $this->moduleLoader->load($GLOBALS['TBE_MODULES']); $this->moduleTemplateFactory = $moduleTemplateFactory; @@ -142,46 +146,12 @@ class BackendController $this->pageRenderer->addInlineSetting('FileCommit', 'moduleUrl', (string)$this->uriBuilder->buildUriFromRoute('tce_file')); $this->pageRenderer->addInlineSetting('Clipboard', 'moduleUrl', (string)$this->uriBuilder->buildUriFromRoute('clipboard_process')); - $this->initializeToolbarItems(); + $this->toolbarItems = $this->toolbarItemsRegistry->getToolbarItems(); $this->executeHook('constructPostProcess'); $this->moduleStorage = $this->backendModuleRepository->loadAllowedModules(['user', 'help']); } - /** - * Initialize toolbar item objects - * - * @throws \RuntimeException - */ - protected function initializeToolbarItems() - { - $toolbarItemInstances = []; - foreach ($GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'] ?? [] as $className) { - $toolbarItemInstance = GeneralUtility::makeInstance($className); - if (!$toolbarItemInstance instanceof ToolbarItemInterface) { - throw new \RuntimeException( - 'class ' . $className . ' is registered as toolbar item but does not implement' - . ToolbarItemInterface::class, - 1415958218 - ); - } - $index = (int)$toolbarItemInstance->getIndex(); - if ($index < 0 || $index > 100) { - throw new \RuntimeException( - 'getIndex() must return an integer between 0 and 100', - 1415968498 - ); - } - // Find next free position in array - while (array_key_exists($index, $toolbarItemInstances)) { - $index++; - } - $toolbarItemInstances[$index] = $toolbarItemInstance; - } - ksort($toolbarItemInstances); - $this->toolbarItems = $toolbarItemInstances; - } - /** * Main function generating the BE scaffolding * diff --git a/typo3/sysext/backend/Classes/Toolbar/ToolbarItemsRegistry.php b/typo3/sysext/backend/Classes/Toolbar/ToolbarItemsRegistry.php new file mode 100644 index 000000000000..a9dddf7ba8a1 --- /dev/null +++ b/typo3/sysext/backend/Classes/Toolbar/ToolbarItemsRegistry.php @@ -0,0 +1,58 @@ +<?php + +declare(strict_types=1); + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +namespace TYPO3\CMS\Backend\Toolbar; + +/** + * Registry class for toolbar items + * @internal + */ +class ToolbarItemsRegistry +{ + protected array $toolbarItems = []; + + public function __construct(iterable $toolbarItems) + { + foreach ($toolbarItems as $toolbarItem) { + if ($toolbarItem instanceof ToolbarItemInterface) { + $index = (int)$toolbarItem->getIndex(); + if ($index < 0 || $index > 100) { + throw new \RuntimeException( + 'getIndex() must return an integer between 0 and 100', + 1415968498 + ); + } + // Find next free position in array + while (isset($this->toolbarItems[$index])) { + $index++; + } + $this->toolbarItems[$index] = $toolbarItem; + } + } + ksort($this->toolbarItems); + } + + /** + * Get all registered toolbarItems + * + * @return ToolbarItemInterface[] + */ + public function getToolbarItems(): array + { + return $this->toolbarItems; + } +} diff --git a/typo3/sysext/backend/Configuration/Services.php b/typo3/sysext/backend/Configuration/Services.php index acee5159f4eb..45e326262e5a 100644 --- a/typo3/sysext/backend/Configuration/Services.php +++ b/typo3/sysext/backend/Configuration/Services.php @@ -5,8 +5,10 @@ namespace TYPO3\CMS\Backend; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; +use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface; use TYPO3\CMS\Core\DependencyInjection\PublicServicePass; return static function (ContainerConfigurator $container, ContainerBuilder $containerBuilder) { + $containerBuilder->registerForAutoconfiguration(ToolbarItemInterface::class)->addTag('backend.toolbar.item'); $containerBuilder->addCompilerPass(new PublicServicePass('backend.controller')); }; diff --git a/typo3/sysext/backend/Configuration/Services.yaml b/typo3/sysext/backend/Configuration/Services.yaml index 4fbbb8a4cbd3..97e3e4e7f410 100644 --- a/typo3/sysext/backend/Configuration/Services.yaml +++ b/typo3/sysext/backend/Configuration/Services.yaml @@ -159,3 +159,7 @@ services: tags: - name: event.listener identifier: 'backend-empty-colpos' + # Toolbar registry + TYPO3\CMS\Backend\Toolbar\ToolbarItemsRegistry: + arguments: + - !tagged_iterator backend.toolbar.item diff --git a/typo3/sysext/backend/ext_localconf.php b/typo3/sysext/backend/ext_localconf.php index 0725ff6de5d4..189ebf77bc47 100644 --- a/typo3/sysext/backend/ext_localconf.php +++ b/typo3/sysext/backend/ext_localconf.php @@ -3,12 +3,6 @@ declare(strict_types=1); use TYPO3\CMS\Backend\Backend\Avatar\DefaultAvatarProvider; -use TYPO3\CMS\Backend\Backend\ToolbarItems\ClearCacheToolbarItem; -use TYPO3\CMS\Backend\Backend\ToolbarItems\HelpToolbarItem; -use TYPO3\CMS\Backend\Backend\ToolbarItems\LiveSearchToolbarItem; -use TYPO3\CMS\Backend\Backend\ToolbarItems\ShortcutToolbarItem; -use TYPO3\CMS\Backend\Backend\ToolbarItems\SystemInformationToolbarItem; -use TYPO3\CMS\Backend\Backend\ToolbarItems\UserToolbarItem; use TYPO3\CMS\Backend\LoginProvider\UsernamePasswordLoginProvider; use TYPO3\CMS\Backend\Preview\StandardPreviewRendererResolver; use TYPO3\CMS\Backend\Provider\PageTsBackendLayoutDataProvider; @@ -18,13 +12,6 @@ use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; defined('TYPO3') or die(); -$GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][1435433106] = ClearCacheToolbarItem::class; -$GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][1435433107] = HelpToolbarItem::class; -$GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][1435433108] = LiveSearchToolbarItem::class; -$GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][1435433109] = ShortcutToolbarItem::class; -$GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][1435433110] = SystemInformationToolbarItem::class; -$GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][1435433111] = UserToolbarItem::class; - $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['backend']['loginProviders'][1433416747] = [ 'provider' => UsernamePasswordLoginProvider::class, 'sorting' => 50, diff --git a/typo3/sysext/core/Configuration/DefaultConfiguration.php b/typo3/sysext/core/Configuration/DefaultConfiguration.php index 0f2fe8848b27..506933625003 100644 --- a/typo3/sysext/core/Configuration/DefaultConfiguration.php +++ b/typo3/sysext/core/Configuration/DefaultConfiguration.php @@ -1382,7 +1382,6 @@ return [ 'flexformForceCDATA' => 0, 'versionNumberInFilename' => false, 'debug' => false, - 'toolbarItems' => [], // Array: Registered toolbar items classes 'HTTP' => [ 'Response' => [ 'Headers' => [ diff --git a/typo3/sysext/core/Documentation/Changelog/12.0/Breaking-96041-ToolbarItemsRegisterByTag.rst b/typo3/sysext/core/Documentation/Changelog/12.0/Breaking-96041-ToolbarItemsRegisterByTag.rst new file mode 100644 index 000000000000..dd9e2fa69286 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/12.0/Breaking-96041-ToolbarItemsRegisterByTag.rst @@ -0,0 +1,45 @@ +.. include:: ../../Includes.txt + +================================================= +Breaking: #96041 - Toolbar items: Register by tag +================================================= + +See :issue:`96041` + +Description +=========== + +Toolbar items implementing :php:`\TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface` are now automatically +registered by adding the tag :yaml:`backend.toolbar.item`, if :yaml:`autoconfigure` +is enabled in :file:`Services.yaml`. + + +Impact +====== + +The registration via :php:`$GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems']` isn't evaluated anymore. + + +Affected Installations +====================== + +Every extension, that adds toolbar items via :php:`$GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems']` +in its :file:`ext_localconf.php` file. + + +Migration +========= + +Remove :php:`$GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems']` from your :file:`ext_localconf.php` file. +If :yaml:`autoconfigure` is not enabled in your :file:`Configuration/Services.(yaml|php)`, add the tag :yaml:`backend.toolbar.item` to your toolbar item class. + + +Example: + +.. code-block:: yaml + + VENDOR\Extension\ToolbarItem\YourAdditionalToolbarItem: + tags: + - name: backend.toolbar.item + +.. index:: Backend, LocalConfiguration, PHP-API, FullyScanned, ext:backend diff --git a/typo3/sysext/core/Documentation/Changelog/12.0/Feature-96041-ImproveBackendToolbarRegistration.rst b/typo3/sysext/core/Documentation/Changelog/12.0/Feature-96041-ImproveBackendToolbarRegistration.rst new file mode 100644 index 000000000000..36e8290512e6 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/12.0/Feature-96041-ImproveBackendToolbarRegistration.rst @@ -0,0 +1,32 @@ +.. include:: ../../Includes.txt + +====================================================== +Feature: #96041 - Improve Backend toolbar registration +====================================================== + +See :issue:`96041` + +Description +=========== + +The toolbar in the TYPO3 backend is well known by users as it provides +e.g. the personal bookmarks or a common used feature for administrators: +the "flush caches" action. + +It's furthermore also possible for extension authors to add their own +toolbar items. The registration therefore had to be done in the +:php:`LocalConfiguration.php` file. + +Since the introduction of the symfony service container in TYPO3 v10, +it's possible to autoconfigure services. This feature is now also used +for the toolbar items. Therefore, the previous registration step is +now superfluous. All toolbar items are now automatically tagged and +registered based on the implemented :php:`ToolbarItemInterface`. + +Impact +====== + +Custom toolbar items are now automatically registered, based on +the implemented interface, through the service configuration. + +.. index:: Backend, PHP-API, ext:backend diff --git a/typo3/sysext/install/Configuration/ExtensionScanner/Php/ArrayDimensionMatcher.php b/typo3/sysext/install/Configuration/ExtensionScanner/Php/ArrayDimensionMatcher.php index 6046a6ccf60d..94c4d805db63 100644 --- a/typo3/sysext/install/Configuration/ExtensionScanner/Php/ArrayDimensionMatcher.php +++ b/typo3/sysext/install/Configuration/ExtensionScanner/Php/ArrayDimensionMatcher.php @@ -537,4 +537,9 @@ return [ 'Deprecation-95343-LegacyHookForNewContentElementWizard.rst', ], ], + '$GLOBALS[\'TYPO3_CONF_VARS\'][\'BE\'][\'toolbarItems\']' => [ + 'restFiles' => [ + 'Breaking-96041-ToolbarItemsRegisterByTag.rst', + ], + ], ]; diff --git a/typo3/sysext/opendocs/Classes/Service/OpenDocumentService.php b/typo3/sysext/opendocs/Classes/Service/OpenDocumentService.php index fdc4adb31c6f..1ad7876bbfff 100644 --- a/typo3/sysext/opendocs/Classes/Service/OpenDocumentService.php +++ b/typo3/sysext/opendocs/Classes/Service/OpenDocumentService.php @@ -47,6 +47,8 @@ class OpenDocumentService public function getOpenDocuments(): array { $openDocuments = []; + // @TODO remove if it is mandatory in AbstractUserAuthentication + $this->backendUser->start(); $sessionOpenDocuments = $this->backendUser->getModuleData('FormEngine', 'ses'); if ($sessionOpenDocuments !== null) { diff --git a/typo3/sysext/opendocs/Tests/Unit/Service/OpenDocumentServiceTest.php b/typo3/sysext/opendocs/Tests/Unit/Service/OpenDocumentServiceTest.php index 3cd63d6a0f13..d0873bdce6a0 100644 --- a/typo3/sysext/opendocs/Tests/Unit/Service/OpenDocumentServiceTest.php +++ b/typo3/sysext/opendocs/Tests/Unit/Service/OpenDocumentServiceTest.php @@ -44,6 +44,7 @@ class OpenDocumentServiceTest extends UnitTestCase { parent::setUp(); $this->backendUser = $this->prophesize(BackendUserAuthentication::class); + $this->backendUser->start()->willReturn(); $this->subject = new OpenDocumentService($this->backendUser->reveal()); } diff --git a/typo3/sysext/opendocs/ext_localconf.php b/typo3/sysext/opendocs/ext_localconf.php index 41f733fee719..56871b8594ed 100644 --- a/typo3/sysext/opendocs/ext_localconf.php +++ b/typo3/sysext/opendocs/ext_localconf.php @@ -6,6 +6,5 @@ use TYPO3\CMS\Opendocs\Backend\ToolbarItems\OpendocsToolbarItem; defined('TYPO3') or die(); -$GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][1435433112] = OpendocsToolbarItem::class; // Register update signal to update the number of open documents $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['updateSignalHook']['OpendocsController::updateNumber'] = OpendocsToolbarItem::class . '->updateNumberOfOpenDocsHook'; diff --git a/typo3/sysext/workspaces/ext_localconf.php b/typo3/sysext/workspaces/ext_localconf.php index 4b0b3cf6b134..ad3e25ee25bc 100644 --- a/typo3/sysext/workspaces/ext_localconf.php +++ b/typo3/sysext/workspaces/ext_localconf.php @@ -3,7 +3,6 @@ declare(strict_types=1); use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; -use TYPO3\CMS\Workspaces\Backend\ToolbarItems\WorkspaceSelectorToolbarItem; use TYPO3\CMS\Workspaces\Hook\BackendUtilityHook; use TYPO3\CMS\Workspaces\Hook\DataHandlerHook; @@ -30,5 +29,3 @@ if (!is_array($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations 'groups' => ['all'], ]; } - -$GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][1435433114] = WorkspaceSelectorToolbarItem::class; -- GitLab