diff --git a/typo3/sysext/backend/Classes/Controller/BackendController.php b/typo3/sysext/backend/Classes/Controller/BackendController.php index 2d51a0066bbfead2aee5ec2c3d8b9933ecd77096..2bae24f618ef4c6809bd95f582212a4b27b24908 100644 --- a/typo3/sysext/backend/Classes/Controller/BackendController.php +++ b/typo3/sysext/backend/Classes/Controller/BackendController.php @@ -29,6 +29,7 @@ use TYPO3\CMS\Backend\Routing\RouteRedirect; use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Backend\Template\PageRendererBackendSetupTrait; use TYPO3\CMS\Backend\Toolbar\RequestAwareToolbarItemInterface; +use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface; use TYPO3\CMS\Backend\Toolbar\ToolbarItemsRegistry; use TYPO3\CMS\Backend\View\BackendViewFactory; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; @@ -210,72 +211,24 @@ class BackendController $view->assign('logoHeight', $logoHeight); $view->assign('applicationVersion', $this->typo3Version->getVersion()); $view->assign('siteName', $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']); - $view->assign('toolbar', $this->renderToolbar($request)); + $view->assign('toolbarItems', $this->getToolbarItems($request)); } /** - * Renders the items in the top toolbar. - * - * @todo: Inline this to the topbar template + * @param ServerRequestInterface $request + * @return ToolbarItemInterface[] */ - protected function renderToolbar(ServerRequestInterface $request): string + protected function getToolbarItems(ServerRequestInterface $request): array { - $toolbarItems = $this->toolbarItemsRegistry->getToolbarItems(); - $toolbar = []; - foreach ($toolbarItems as $toolbarItem) { + return array_map(static function (ToolbarItemInterface $toolbarItem) use ($request) { if ($toolbarItem instanceof RequestAwareToolbarItemInterface) { $toolbarItem->setRequest($request); } - if ($toolbarItem->checkAccess()) { - $hasDropDown = (bool)$toolbarItem->hasDropDown(); - $additionalAttributes = (array)$toolbarItem->getAdditionalAttributes(); - - $liAttributes = []; - - // Merge class: Add dropdown class if hasDropDown, add classes from additional attributes - $classes = []; - $classes[] = 'toolbar-item'; - $classes[] = 't3js-toolbar-item'; - if (isset($additionalAttributes['class'])) { - $classes[] = $additionalAttributes['class']; - unset($additionalAttributes['class']); - } - $liAttributes['class'] = implode(' ', $classes); - - // Add further attributes - foreach ($additionalAttributes as $name => $value) { - $liAttributes[(string)$name] = (string)$value; - } - - // Create a unique id from class name - $fullyQualifiedClassName = \get_class($toolbarItem); - $className = GeneralUtility::underscoredToLowerCamelCase($fullyQualifiedClassName); - $className = GeneralUtility::camelCaseToLowerCaseUnderscored($className); - $className = str_replace(['_', '\\'], '-', $className); - $liAttributes['id'] = $className; - - // Create data attribute identifier - $shortName = substr($fullyQualifiedClassName, (int)strrpos($fullyQualifiedClassName, '\\') + 1); - $dataToolbarIdentifier = GeneralUtility::camelCaseToLowerCaseUnderscored($shortName); - $dataToolbarIdentifier = str_replace('_', '-', $dataToolbarIdentifier); - $liAttributes['data-toolbar-identifier'] = $dataToolbarIdentifier; - - $toolbar[] = '<li ' . GeneralUtility::implodeAttributes($liAttributes, true) . '>'; - - if ($hasDropDown) { - $toolbar[] = '<a href="#" class="toolbar-item-link dropdown-toggle" data-bs-toggle="dropdown" data-bs-offset="0,-2">'; - $toolbar[] = $toolbarItem->getItem(); - $toolbar[] = '</a>'; - $toolbar[] = '<div class="dropdown-menu" role="menu">'; - $toolbar[] = $toolbarItem->getDropDown(); - $toolbar[] = '</div>'; - } else { - $toolbar[] = $toolbarItem->getItem(); - } - $toolbar[] = '</li>'; - } - } - return implode(LF, $toolbar); + return $toolbarItem; + }, array_filter( + $this->toolbarItemsRegistry->getToolbarItems(), + static fn (ToolbarItemInterface $toolbarItem) => $toolbarItem->checkAccess() + )); } /** diff --git a/typo3/sysext/backend/Classes/ViewHelpers/Toolbar/AttributesViewHelper.php b/typo3/sysext/backend/Classes/ViewHelpers/Toolbar/AttributesViewHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..85a24347cbabeee2454c8803992e0de98a030a0c --- /dev/null +++ b/typo3/sysext/backend/Classes/ViewHelpers/Toolbar/AttributesViewHelper.php @@ -0,0 +1,68 @@ +<?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\ViewHelpers\Toolbar; + +use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; +use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; +use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic; + +/** + * Builds an attribute string for use in rendered toolbar items + * + * @internal + */ +final class AttributesViewHelper extends AbstractViewHelper +{ + use CompileWithRenderStatic; + + public function initializeArguments(): void + { + $this->registerArgument('class', ToolbarItemInterface::class, 'Class being converted to a string for usage as id attribute', true); + } + + /** + * @param array{class?: ToolbarItemInterface} $arguments + * @param \Closure $renderChildrenClosure + * @param RenderingContextInterface $renderingContext + * @return string + */ + public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext): string + { + $additionalAttributes = [ + 'class' => 'toolbar-item t3js-toolbar-item', + ]; + + $toolbarItem = $arguments['class'] ?? null; + if ($toolbarItem instanceof ToolbarItemInterface) { + $additionalAttributes['class'] .= ' ' . ($toolbarItem->getAdditionalAttributes()['class'] ?? ''); + $additionalAttributes['id'] = self::convertClassNameToIdAttribute(\get_class($toolbarItem)); + } + + return GeneralUtility::implodeAttributes($additionalAttributes); + } + + private static function convertClassNameToIdAttribute(string $fullyQualifiedClassName): string + { + $className = GeneralUtility::underscoredToLowerCamelCase($fullyQualifiedClassName); + $className = GeneralUtility::camelCaseToLowerCaseUnderscored($className); + + return str_replace(['_', '\\'], '-', $className); + } +} diff --git a/typo3/sysext/backend/Resources/Private/Partials/Backend/Topbar.html b/typo3/sysext/backend/Resources/Private/Partials/Backend/Topbar.html index 61478378fa81c92c96c2344ae9227c7d9a7ceff5..cd6037d1357cd9f83d60932fbd918ddb4324ab9f 100644 --- a/typo3/sysext/backend/Resources/Private/Partials/Backend/Topbar.html +++ b/typo3/sysext/backend/Resources/Private/Partials/Backend/Topbar.html @@ -1,4 +1,5 @@ <html + xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers" xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true" @@ -48,7 +49,23 @@ <div class="scaffold-toolbar t3js-scaffold-toolbar" data-toolbar-identifier="toolbar"> <div class="toolbar t3js-topbar-toolbar"> <ul class="toolbar-list" data-typo3-role="typo3-module-menu"> - <f:format.raw>{toolbar}</f:format.raw> + <f:for each="{toolbarItems}" as="toolbarItem"> + <li {be:toolbar.attributes(class: toolbarItem) -> f:format.raw()}> + <f:if condition="{toolbarItem.dropdown}"> + <f:then> + <a href="#" class="toolbar-item-link dropdown-toggle" data-bs-toggle="dropdown" data-bs-offset="0,-2"> + {toolbarItem.item -> f:format.raw()} + </a> + <div class="dropdown-menu" role="menu"> + {toolbarItem.dropdown -> f:format.raw()} + </div> + </f:then> + <f:else> + {toolbarItem.item -> f:format.raw()} + </f:else> + </f:if> + </li> + </f:for> </ul> </div> </div>