Commit f52d6c60 authored by Daniel Windloff's avatar Daniel Windloff Committed by Andreas Fernandez
Browse files

[!!!][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'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 ad6da374
......@@ -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
*
......
<?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;
}
}
......@@ -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'));
};
......@@ -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
......@@ -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,
......
......@@ -1382,7 +1382,6 @@ return [
'flexformForceCDATA' => 0,
'versionNumberInFilename' => false,
'debug' => false,
'toolbarItems' => [], // Array: Registered toolbar items classes
'HTTP' => [
'Response' => [
'Headers' => [
......
.. 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
.. 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
......@@ -537,4 +537,9 @@ return [
'Deprecation-95343-LegacyHookForNewContentElementWizard.rst',
],
],
'$GLOBALS[\'TYPO3_CONF_VARS\'][\'BE\'][\'toolbarItems\']' => [
'restFiles' => [
'Breaking-96041-ToolbarItemsRegisterByTag.rst',
],
],
];
......@@ -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) {
......
......@@ -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());
}
......
......@@ -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';
......@@ -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;
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