[CLEANUP] Streamline backend toolbar items 09/51909/8
authorBenni Mack <benni@typo3.org>
Tue, 28 Feb 2017 20:13:38 +0000 (21:13 +0100)
committerFrank Naegler <frank.naegler@typo3.org>
Thu, 30 Mar 2017 08:13:08 +0000 (10:13 +0200)
- Move everything to Fluid (also icon generation and labels)
- Remove a lot of get* shorthand protected methods
- Add PHP comments and remove PHP comments where applicable

Resolves: #80554
Releases: master
Change-Id: I9c417a02b2ac41fee95b815ee626ff44523c96f5
Reviewed-on: https://review.typo3.org/51909
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Daniel Goerz <ervaude@gmail.com>
Tested-by: Daniel Goerz <ervaude@gmail.com>
Reviewed-by: Frank Naegler <frank.naegler@typo3.org>
Tested-by: Frank Naegler <frank.naegler@typo3.org>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
28 files changed:
typo3/sysext/backend/Classes/Backend/ToolbarItems/ClearCacheToolbarItem.php
typo3/sysext/backend/Classes/Backend/ToolbarItems/HelpToolbarItem.php
typo3/sysext/backend/Classes/Backend/ToolbarItems/LiveSearchToolbarItem.php
typo3/sysext/backend/Classes/Backend/ToolbarItems/ShortcutToolbarItem.php
typo3/sysext/backend/Classes/Backend/ToolbarItems/SystemInformationToolbarItem.php
typo3/sysext/backend/Classes/Backend/ToolbarItems/UserToolbarItem.php
typo3/sysext/backend/Resources/Private/Templates/ToolbarItems/ClearCacheToolbarItem.html
typo3/sysext/backend/Resources/Private/Templates/ToolbarItems/ClearCacheToolbarItemDropDown.html
typo3/sysext/backend/Resources/Private/Templates/ToolbarItems/ClearCacheToolbarItemSingle.html
typo3/sysext/backend/Resources/Private/Templates/ToolbarItems/HelpToolbarItem.html
typo3/sysext/backend/Resources/Private/Templates/ToolbarItems/HelpToolbarItemDropDown.html
typo3/sysext/backend/Resources/Private/Templates/ToolbarItems/LiveSearchToolbarItem.html [new file with mode: 0644]
typo3/sysext/backend/Resources/Private/Templates/ToolbarItems/SystemInformationDropDown.html [new file with mode: 0644]
typo3/sysext/backend/Resources/Private/Templates/ToolbarItems/SystemInformationToolbarItem.html [new file with mode: 0644]
typo3/sysext/backend/Resources/Private/Templates/ToolbarItems/UserToolbarItem.html
typo3/sysext/backend/Resources/Private/Templates/ToolbarItems/UserToolbarItemDropDown.html
typo3/sysext/backend/Resources/Private/Templates/ToolbarMenu/SystemInformation.html [deleted file]
typo3/sysext/opendocs/Classes/Backend/ToolbarItems/OpendocsToolbarItem.php
typo3/sysext/opendocs/Resources/Private/Templates/DropDown.html [deleted file]
typo3/sysext/opendocs/Resources/Private/Templates/ToolbarItem.html [deleted file]
typo3/sysext/opendocs/Resources/Private/Templates/ToolbarItems/DropDown.html [new file with mode: 0644]
typo3/sysext/opendocs/Resources/Private/Templates/ToolbarItems/ToolbarItem.html [new file with mode: 0644]
typo3/sysext/sys_action/Classes/Backend/ToolbarItems/ActionToolbarItem.php
typo3/sysext/sys_action/Resources/Private/Templates/ToolbarItems/DropDown.html [new file with mode: 0644]
typo3/sysext/sys_action/Resources/Private/Templates/ToolbarItems/ToolbarItem.html [new file with mode: 0644]
typo3/sysext/workspaces/Classes/Backend/ToolbarItems/WorkspaceSelectorToolbarItem.php
typo3/sysext/workspaces/Resources/Private/Templates/ToolbarItems/DropDown.html [new file with mode: 0644]
typo3/sysext/workspaces/Resources/Private/Templates/ToolbarItems/ToolbarItem.html [new file with mode: 0644]

index a45efb0..a036b89 100644 (file)
@@ -17,14 +17,16 @@ namespace TYPO3\CMS\Backend\Backend\ToolbarItems;
 use TYPO3\CMS\Backend\Toolbar\ClearCacheActionsHookInterface;
 use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
-use TYPO3\CMS\Core\Imaging\Icon;
-use TYPO3\CMS\Core\Imaging\IconFactory;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\Page\PageRenderer;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Fluid\View\StandaloneView;
 
 /**
  * Render cache clearing toolbar item
+ * Adds a dropdown if there are more than one item to clear (usually for admins to render the flush all caches)
+ *
+ * The dropdown items can be extended via a hook named "cacheActions".
  */
 class ClearCacheToolbarItem implements ToolbarItemInterface
 {
@@ -39,31 +41,21 @@ class ClearCacheToolbarItem implements ToolbarItemInterface
     protected $optionValues = [];
 
     /**
-     * @var IconFactory
-     */
-    protected $iconFactory;
-
-    /**
-     * Constructor
-     *
      * @throws \UnexpectedValueException
      */
     public function __construct()
     {
-        $backendUser = $this->getBackendUser();
-        $languageService = $this->getLanguageService();
-        $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
-
         $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Toolbar/ClearCacheMenu');
+        $backendUser = $this->getBackendUser();
 
         // Clear all page-related caches
         if ($backendUser->isAdmin() || $backendUser->getTSConfigVal('options.clearCache.pages')) {
             $this->cacheActions[] = [
                 'id' => 'pages',
-                'title' => htmlspecialchars($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:flushPageCachesTitle')),
-                'description' => htmlspecialchars($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:flushPageCachesDescription')),
+                'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:flushPageCachesTitle',
+                'description' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:flushPageCachesDescription',
                 'href' => BackendUtility::getModuleUrl('tce_db', ['cacheCmd' => 'pages']),
-                'icon' => $this->iconFactory->getIcon('actions-system-cache-clear-impact-low', Icon::SIZE_SMALL)->render()
+                'iconIdentifier' => 'actions-system-cache-clear-impact-low'
             ];
             $this->optionValues[] = 'pages';
         }
@@ -74,10 +66,10 @@ class ClearCacheToolbarItem implements ToolbarItemInterface
         if ($backendUser->getTSConfigVal('options.clearCache.all') || ($backendUser->isAdmin() && $backendUser->getTSConfigVal('options.clearCache.all') !== '0')) {
             $this->cacheActions[] = [
                 'id' => 'all',
-                'title' => htmlspecialchars($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:flushAllCachesTitle2')),
-                'description' => htmlspecialchars($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:flushAllCachesDescription2')),
+                'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:flushAllCachesTitle2',
+                'description' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:flushAllCachesDescription2',
                 'href' => BackendUtility::getModuleUrl('tce_db', ['cacheCmd' => 'all']),
-                'icon' => $this->iconFactory->getIcon('actions-system-cache-clear-impact-high', Icon::SIZE_SMALL)->render()
+                'iconIdentifier' => 'actions-system-cache-clear-impact-high'
             ];
             $this->optionValues[] = 'all';
         }
@@ -105,41 +97,33 @@ class ClearCacheToolbarItem implements ToolbarItemInterface
         if ($backendUser->isAdmin()) {
             return true;
         }
-        if (is_array($this->optionValues)) {
-            foreach ($this->optionValues as $value) {
-                if ($backendUser->getTSConfigVal('options.clearCache.' . $value)) {
-                    return true;
-                }
+        foreach ($this->optionValues as $value) {
+            if ($backendUser->getTSConfigVal('options.clearCache.' . $value)) {
+                return true;
             }
         }
         return false;
     }
 
     /**
-     * Render clear cache icon
+     * Render clear cache icon, based on the option if there is more than one icon or just one.
      *
      * @return string Icon HTML
      */
     public function getItem()
     {
         if ($this->hasDropDown()) {
-            $templateReference = 'ClearCacheToolbarItem.html';
-            $icon = $this->iconFactory->getIcon('apps-toolbar-menu-cache', Icon::SIZE_SMALL)->render('inline');
-            $variables = [
-                'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:rm.clearCache_clearCache',
-                'icon' => $icon
-            ];
+            return $this->getFluidTemplateObject('ClearCacheToolbarItem.html')->render();
         } else {
-            $templateReference = 'ClearCacheToolbarItemSingle.html';
+            $view = $this->getFluidTemplateObject('ClearCacheToolbarItemSingle.html');
             $cacheAction = end($this->cacheActions);
-            $variables['link'] = $cacheAction['href'];
-            $variables['title'] = $cacheAction['title'];
-            $variables['icon'] = $cacheAction['icon'];
+            $view->assignMultiple([
+                'link'  => $cacheAction['href'],
+                'title' => $cacheAction['title'],
+                'iconIdentifier'  => $cacheAction['iconIdentifier'],
+            ]);
+            return $view->render();
         }
-        $view = $this->getFluidTemplateObject($templateReference);
-        $view->assignMultiple($variables);
-
-        return $view->render();
     }
 
     /**
@@ -150,12 +134,7 @@ class ClearCacheToolbarItem implements ToolbarItemInterface
     public function getDropDown()
     {
         $view = $this->getFluidTemplateObject('ClearCacheToolbarItemDropDown.html');
-        $view->assignMultiple([
-                'title' =>  'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:rm.clearCache_clearCache',
-                'cacheActions' => $this->cacheActions,
-            ]
-        );
-
+        $view->assign('cacheActions', $this->cacheActions);
         return $view->render();
     }
 
@@ -170,7 +149,7 @@ class ClearCacheToolbarItem implements ToolbarItemInterface
     }
 
     /**
-     * This item has a drop down
+     * This item has a drop down if there is more than one cache action available for the current Backend user.
      *
      * @return bool
      */
@@ -192,7 +171,7 @@ class ClearCacheToolbarItem implements ToolbarItemInterface
     /**
      * Returns the current BE user.
      *
-     * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
+     * @return BackendUserAuthentication
      */
     protected function getBackendUser()
     {
@@ -200,8 +179,6 @@ class ClearCacheToolbarItem implements ToolbarItemInterface
     }
 
     /**
-     * Returns current PageRenderer
-     *
      * @return PageRenderer
      */
     protected function getPageRenderer()
@@ -210,31 +187,19 @@ class ClearCacheToolbarItem implements ToolbarItemInterface
     }
 
     /**
-     * Returns LanguageService
-     *
-     * @return \TYPO3\CMS\Lang\LanguageService
-     */
-    protected function getLanguageService()
-    {
-        return $GLOBALS['LANG'];
-    }
-
-    /**
      * Returns a new standalone view, shorthand function
      *
      * @param string $filename Which templateFile should be used.
-     *
      * @return StandaloneView
      */
-    protected function getFluidTemplateObject(string $filename):StandaloneView
+    protected function getFluidTemplateObject(string $filename): StandaloneView
     {
-        /** @var StandaloneView $view */
         $view = GeneralUtility::makeInstance(StandaloneView::class);
-        $view->setLayoutRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Layouts')]);
-        $view->setPartialRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Partials/ToolbarItems')]);
-        $view->setTemplateRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates/ToolbarItems')]);
+        $view->setLayoutRootPaths(['EXT:backend/Resources/Private/Layouts']);
+        $view->setPartialRootPaths(['EXT:backend/Resources/Private/Partials/ToolbarItems']);
+        $view->setTemplateRootPaths(['EXT:backend/Resources/Private/Templates/ToolbarItems']);
 
-        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates/ToolbarItems/' . $filename));
+        $view->setTemplate($filename);
 
         $view->getRequest()->setControllerExtensionName('Backend');
         return $view;
index 3b55abf..f3399c5 100644 (file)
@@ -16,8 +16,6 @@ namespace TYPO3\CMS\Backend\Backend\ToolbarItems;
 
 use TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository;
 use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
-use TYPO3\CMS\Core\Imaging\Icon;
-use TYPO3\CMS\Core\Imaging\IconFactory;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Fluid\View\StandaloneView;
 
@@ -32,23 +30,15 @@ class HelpToolbarItem implements ToolbarItemInterface
     protected $helpModuleMenu = null;
 
     /**
-     * @var IconFactory
-     */
-    protected $iconFactory;
-
-    /**
      * Constructor
      */
     public function __construct()
     {
-        /** @var BackendModuleRepository $backendModuleRepository */
         $backendModuleRepository = GeneralUtility::makeInstance(BackendModuleRepository::class);
-        /** @var \TYPO3\CMS\Backend\Domain\Model\Module\BackendModule $helpModuleMenu */
         $helpModuleMenu = $backendModuleRepository->findByModuleName('help');
         if ($helpModuleMenu && $helpModuleMenu->getChildren()->count() > 0) {
             $this->helpModuleMenu = $helpModuleMenu;
         }
-        $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
     }
 
     /**
@@ -58,27 +48,17 @@ class HelpToolbarItem implements ToolbarItemInterface
      */
     public function checkAccess()
     {
-        $result = (bool)$this->helpModuleMenu;
-        return $result;
+        return (bool)$this->helpModuleMenu;
     }
 
     /**
      * Render help icon
      *
-     * @return string Help
+     * @return string toolbar item for the help icon
      */
     public function getItem()
     {
-        $icon = $this->iconFactory->getIcon('apps-toolbar-menu-help', Icon::SIZE_SMALL)->render('inline');
-
-        $view = $this->getFluidTemplateObject('HelpToolbarItem.html');
-        $view->assignMultiple([
-                'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.help',
-                'icon' => $icon
-            ]
-        );
-
-        return $view->render();
+        return $this->getFluidTemplateObject('HelpToolbarItem.html')->render();
     }
 
     /**
@@ -89,12 +69,7 @@ class HelpToolbarItem implements ToolbarItemInterface
     public function getDropDown()
     {
         $view = $this->getFluidTemplateObject('HelpToolbarItemDropDown.html');
-        $view->assignMultiple([
-                'title' =>  'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:rm.clearCache_clearCache',
-                'modules' => $this->helpModuleMenu->getChildren()
-            ]
-        );
-
+        $view->assign('modules', $this->helpModuleMenu->getChildren());
         return $view->render();
     }
 
@@ -129,31 +104,18 @@ class HelpToolbarItem implements ToolbarItemInterface
     }
 
     /**
-     * Returns LanguageService
-     *
-     * @return \TYPO3\CMS\Lang\LanguageService
-     */
-    protected function getLanguageService()
-    {
-        return $GLOBALS['LANG'];
-    }
-
-    /**
      * Returns a new standalone view, shorthand function
      *
      * @param string $filename Which templateFile should be used.
-     *
      * @return StandaloneView
      */
-    protected function getFluidTemplateObject(string $filename):StandaloneView
+    protected function getFluidTemplateObject(string $filename): StandaloneView
     {
-        /** @var StandaloneView $view */
         $view = GeneralUtility::makeInstance(StandaloneView::class);
-        $view->setLayoutRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Layouts')]);
-        $view->setPartialRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Partials/ToolbarItems')]);
-        $view->setTemplateRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates/ToolbarItems')]);
-
-        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates/ToolbarItems/' . $filename));
+        $view->setLayoutRootPaths(['EXT:backend/Resources/Private/Layouts']);
+        $view->setPartialRootPaths(['EXT:backend/Resources/Private/Partials/ToolbarItems']);
+        $view->setTemplateRootPaths(['EXT:backend/Resources/Private/Templates/ToolbarItems']);
+        $view->setTemplate($filename);
 
         $view->getRequest()->setControllerExtensionName('Backend');
         return $view;
index 0236af8..3391899 100644 (file)
@@ -16,44 +16,33 @@ namespace TYPO3\CMS\Backend\Backend\ToolbarItems;
 
 use TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository;
 use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
-use TYPO3\CMS\Core\Imaging\Icon;
-use TYPO3\CMS\Core\Imaging\IconFactory;
 use TYPO3\CMS\Core\Page\PageRenderer;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Lang\LanguageService;
+use TYPO3\CMS\Fluid\View\StandaloneView;
 
 /**
- * Adds backend live search to the toolbar
+ * Adds backend live search to the toolbar by adding JavaScript and adding an input search field
  */
 class LiveSearchToolbarItem implements ToolbarItemInterface
 {
     /**
-     * @var IconFactory
-     */
-    protected $iconFactory;
-
-    /**
-     * Constructor
+     * Loads the needed JavaScript file, ands includes it to the page renderer
      */
     public function __construct()
     {
         $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/LiveSearch');
-        $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
     }
 
     /**
      * Checks whether the user has access to this toolbar item,
-     * only allowed when the list module is available
+     * only allowed when the list module is available.
+     * Live search is heavily dependent on the list module and only available when that module is.
      *
      * @return bool TRUE if user has access, FALSE if not
      */
     public function checkAccess()
     {
-        /** @var BackendModuleRepository $backendModuleRepository */
         $backendModuleRepository = GeneralUtility::makeInstance(BackendModuleRepository::class);
-        /** @var \TYPO3\CMS\Backend\Domain\Model\Module\BackendModule $listModule */
-
-        // Live search is heavily dependent on the list module and only available when that module is.
         $listModule = $backendModuleRepository->findByModuleName('web_list');
         return $listModule !== null && $listModule !== false;
     }
@@ -65,20 +54,7 @@ class LiveSearchToolbarItem implements ToolbarItemInterface
      */
     public function getItem()
     {
-        return '
-                       <form class="t3js-topbar-navigation-search toolbar-item-search-form live-search-wrapper" role="search">
-                               <div class="form-group">
-                    <div class="form-control-holder">
-                        <div class="form-control-icon">
-                            ' . $this->iconFactory->getIcon('apps-toolbar-menu-search', Icon::SIZE_SMALL)->render('inline') . '
-                        </div>
-                                           <input type="text" class="form-control toolbar-item-search-field t3js-topbar-navigation-search-field" placeholder="' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.search')) . '" id="live-search-box" autocomplete="off">
-                    </div>
-                               </div>
-                       </form>
-            <a href="#" class="dropdown-toggle t3js-toolbar-search-dropdowntoggle" data-toggle="dropdown" aria-expanded="false"></a>
-                       <div class="dropdown-menu" role="menu"></div>
-               ';
+        return $this->getFluidTemplateObject('LiveSearchToolbarItem.html')->render();
     }
 
     /**
@@ -132,12 +108,21 @@ class LiveSearchToolbarItem implements ToolbarItemInterface
     }
 
     /**
-     * Returns LanguageService
+     * Returns a new standalone view, shorthand function
      *
-     * @return LanguageService
+     * @param string $filename Which templateFile should be used.
+     * @return StandaloneView
      */
-    protected function getLanguageService()
+    protected function getFluidTemplateObject(string $filename): StandaloneView
     {
-        return $GLOBALS['LANG'];
+        $view = GeneralUtility::makeInstance(StandaloneView::class);
+        $view->setLayoutRootPaths(['EXT:backend/Resources/Private/Layouts']);
+        $view->setPartialRootPaths(['EXT:backend/Resources/Private/Partials/ToolbarItems']);
+        $view->setTemplateRootPaths(['EXT:backend/Resources/Private/Templates/ToolbarItems']);
+
+        $view->setTemplate($filename);
+
+        $view->getRequest()->setControllerExtensionName('Backend');
+        return $view;
     }
 }
index 5b258e9..652334a 100644 (file)
@@ -952,15 +952,14 @@ class ShortcutToolbarItem implements ToolbarItemInterface
      * @throws \InvalidArgumentException
      * @internal param string $templateFile
      */
-    protected function getFluidTemplateObject(string $templateFilename)
+    protected function getFluidTemplateObject(string $templateFilename): StandaloneView
     {
-        /** @var StandaloneView $view */
         $view = GeneralUtility::makeInstance(StandaloneView::class);
-        $view->setLayoutRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Layouts')]);
-        $view->setPartialRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Partials')]);
-        $view->setTemplateRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates')]);
+        $view->setLayoutRootPaths(['EXT:backend/Resources/Private/Layouts']);
+        $view->setPartialRootPaths(['EXT:backend/Resources/Private/Partials']);
+        $view->setTemplateRootPaths(['EXT:backend/Resources/Private/Templates/ShortcutToolbarItem']);
 
-        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates/ShortcutToolbarItem/' . $templateFilename));
+        $view->setTemplate($templateFilename);
 
         $view->getRequest()->setControllerExtensionName('Backend');
         return $view;
index 60cdbf6..e991b57 100644 (file)
@@ -20,12 +20,10 @@ use TYPO3\CMS\Backend\Toolbar\Enumeration\InformationStatus;
 use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Core\Core\Bootstrap;
+use TYPO3\CMS\Core\Core\SystemEnvironmentBuilder;
 use TYPO3\CMS\Core\Database\ConnectionPool;
-use TYPO3\CMS\Core\Imaging\Icon;
-use TYPO3\CMS\Core\Imaging\IconFactory;
 use TYPO3\CMS\Core\Page\PageRenderer;
 use TYPO3\CMS\Core\Utility\CommandUtility;
-use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\StringUtility;
 use TYPO3\CMS\Core\Utility\VersionNumberUtility;
@@ -37,16 +35,6 @@ use TYPO3\CMS\Fluid\View\StandaloneView;
 class SystemInformationToolbarItem implements ToolbarItemInterface
 {
     /**
-     * @var StandaloneView
-     */
-    protected $standaloneView = null;
-
-    /**
-     * Template file for the dropdown menu
-     */
-    const TOOLBAR_MENU_TEMPLATE = 'SystemInformation.html';
-
-    /**
      * Number displayed as badge on the dropdown trigger
      *
      * @var int
@@ -83,11 +71,6 @@ class SystemInformationToolbarItem implements ToolbarItemInterface
     protected $signalSlotDispatcher = null;
 
     /**
-     * @var IconFactory
-     */
-    protected $iconFactory;
-
-    /**
      * @var int
      */
     protected $maximumCountInBadge = 99;
@@ -97,18 +80,7 @@ class SystemInformationToolbarItem implements ToolbarItemInterface
      */
     public function __construct()
     {
-        if (!$this->checkAccess()) {
-            return;
-        }
-        $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
-
-        $extPath = ExtensionManagementUtility::extPath('backend');
-        /* @var $view StandaloneView */
-        $this->standaloneView = GeneralUtility::makeInstance(StandaloneView::class);
-        $this->standaloneView->setTemplatePathAndFilename($extPath . 'Resources/Private/Templates/ToolbarMenu/' . static::TOOLBAR_MENU_TEMPLATE);
-
         $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Toolbar/SystemInformationMenu');
-
         $this->highestSeverity = InformationStatus::cast(InformationStatus::STATUS_INFO);
     }
 
@@ -142,10 +114,8 @@ class SystemInformationToolbarItem implements ToolbarItemInterface
     public function renderMenuAction(ServerRequestInterface $request, ResponseInterface $response)
     {
         $this->collectInformation();
-
         $response->getBody()->write($this->getDropDown());
-        $response = $response->withHeader('Content-Type', 'text/html; charset=utf-8');
-        return $response;
+        return $response->withHeader('Content-Type', 'text/html; charset=utf-8');
     }
 
     /**
@@ -154,9 +124,9 @@ class SystemInformationToolbarItem implements ToolbarItemInterface
     protected function getPhpVersion()
     {
         $this->systemInformation[] = [
-            'title' => htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.sysinfo.phpversion')),
+            'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.sysinfo.phpversion',
             'value' => PHP_VERSION,
-            'icon' => $this->iconFactory->getIcon('sysinfo-php-version', Icon::SIZE_SMALL)->render()
+            'iconIdentifier' => 'sysinfo-php-version'
         ];
     }
 
@@ -167,13 +137,12 @@ class SystemInformationToolbarItem implements ToolbarItemInterface
     {
         foreach (GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionNames() as $connectionName) {
             $this->systemInformation[] = [
-                'title' => $this->getLanguageService()
-                    ->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.sysinfo.database')
-                    . ' (' . htmlspecialchars($connectionName) . ')',
+                'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.sysinfo.database',
+                'titleAddition' => $connectionName,
                 'value' => GeneralUtility::makeInstance(ConnectionPool::class)
                     ->getConnectionByName($connectionName)
                     ->getServerVersion(),
-                'icon' => $this->iconFactory->getIcon('sysinfo-database', Icon::SIZE_SMALL)->render()
+                'iconIdentifier' => 'sysinfo-database'
             ];
         }
     }
@@ -185,10 +154,10 @@ class SystemInformationToolbarItem implements ToolbarItemInterface
     {
         $applicationContext = GeneralUtility::getApplicationContext();
         $this->systemInformation[] = [
-            'title' => htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.sysinfo.applicationcontext')),
-            'value' => (string)$applicationContext,
+            'title'  => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.sysinfo.applicationcontext',
+            'value'  => (string)$applicationContext,
             'status' => $applicationContext->isProduction() ? InformationStatus::STATUS_OK : InformationStatus::STATUS_WARNING,
-            'icon' => $this->iconFactory->getIcon('sysinfo-application-context', Icon::SIZE_SMALL)->render()
+            'iconIdentifier' => 'sysinfo-application-context'
         ];
     }
 
@@ -201,11 +170,10 @@ class SystemInformationToolbarItem implements ToolbarItemInterface
             return;
         }
 
-        $languageService = $this->getLanguageService();
         $this->systemInformation[] = [
-            'title' => htmlspecialchars($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.sysinfo.composerMode')),
-            'value' => htmlspecialchars($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.enabled')),
-            'icon' => $this->iconFactory->getIcon('sysinfo-composer-mode', Icon::SIZE_SMALL)->render()
+            'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.sysinfo.composerMode',
+            'value' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.enabled',
+            'iconIdentifier' => 'sysinfo-composer-mode'
         ];
     }
 
@@ -214,7 +182,7 @@ class SystemInformationToolbarItem implements ToolbarItemInterface
      */
     protected function getGitRevision()
     {
-        if (!StringUtility::endsWith(TYPO3_version, '-dev') || \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::isFunctionDisabled('exec')) {
+        if (!StringUtility::endsWith(TYPO3_version, '-dev') || SystemEnvironmentBuilder::isFunctionDisabled('exec')) {
             return;
         }
         // check if git exists
@@ -228,9 +196,9 @@ class SystemInformationToolbarItem implements ToolbarItemInterface
         $branch = trim(CommandUtility::exec('git rev-parse --abbrev-ref HEAD'));
         if (!empty($revision) && !empty($branch)) {
             $this->systemInformation[] = [
-                'title' => htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.sysinfo.gitrevision')),
+                'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.sysinfo.gitrevision',
                 'value' => sprintf('%s [%s]', $revision, $branch),
-                'icon' => $this->iconFactory->getIcon('sysinfo-git', Icon::SIZE_SMALL)->render()
+                'iconIdentifier' => 'sysinfo-git'
             ];
         }
     }
@@ -252,9 +220,9 @@ class SystemInformationToolbarItem implements ToolbarItemInterface
                 $icon = 'windows';
         }
         $this->systemInformation[] = [
-            'title' => htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.sysinfo.operatingsystem')),
+            'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.sysinfo.operatingsystem',
             'value' => $kernelName . ' ' . php_uname('r'),
-            'icon' => $this->iconFactory->getIcon('sysinfo-os-' . $icon, Icon::SIZE_SMALL)->render()
+            'iconIdentifier' => 'sysinfo-os-' . $icon
         ];
     }
 
@@ -264,9 +232,9 @@ class SystemInformationToolbarItem implements ToolbarItemInterface
     protected function getWebServer()
     {
         $this->systemInformation[] = [
-            'title' => htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.sysinfo.webserver')),
-            'value' => htmlspecialchars($_SERVER['SERVER_SOFTWARE']),
-            'icon' => $this->iconFactory->getIcon('sysinfo-webserver', Icon::SIZE_SMALL)->render()
+            'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.sysinfo.webserver',
+            'value' => $_SERVER['SERVER_SOFTWARE'],
+            'iconIdentifier' => 'sysinfo-webserver'
         ];
     }
 
@@ -276,9 +244,9 @@ class SystemInformationToolbarItem implements ToolbarItemInterface
     protected function getTypo3Version()
     {
         $this->systemInformation[] = [
-            'title' => htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.sysinfo.typo3-version')),
-            'value' => htmlspecialchars(VersionNumberUtility::getCurrentTypo3Version()),
-            'icon' => $this->iconFactory->getIcon('sysinfo-typo3-version', Icon::SIZE_SMALL)->render()
+            'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.sysinfo.typo3-version',
+            'value' => VersionNumberUtility::getCurrentTypo3Version(),
+            'iconIdentifier' => 'sysinfo-typo3-version'
         ];
     }
 
@@ -362,13 +330,7 @@ class SystemInformationToolbarItem implements ToolbarItemInterface
      */
     public function getItem()
     {
-        $title = htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.sysinfo'));
-        $icon = $this->iconFactory->getIcon('actions-system-list-open', Icon::SIZE_SMALL)->render('inline');
-        return '
-            <span class="toolbar-item-icon" title="' . $title . '">' . $icon . '</span>
-            <span class="toolbar-item-title">' . $title . '</span>
-            <span class="toolbar-item-badge t3js-systeminformation-counter badge"></span>
-            ';
+        return $this->getFluidTemplateObject('SystemInformationToolbarItem.html')->render();
     }
 
     /**
@@ -382,16 +344,15 @@ class SystemInformationToolbarItem implements ToolbarItemInterface
             return '';
         }
 
-        $request = $this->standaloneView->getRequest();
-        $request->setControllerExtensionName('backend');
-        $this->standaloneView->assignMultiple([
+        $view = $this->getFluidTemplateObject('SystemInformationDropDown.html');
+        $view->assignMultiple([
             'installToolUrl' => BackendUtility::getModuleUrl('system_extinstall'),
             'messages' => $this->systemMessages,
             'count' => $this->totalCount > $this->maximumCountInBadge ? $this->maximumCountInBadge . '+' : $this->totalCount,
             'severityBadgeClass' => $this->severityBadgeClass,
             'systemInformation' => $this->systemInformation
         ]);
-        return $this->standaloneView->render();
+        return $view->render();
     }
 
     /**
@@ -445,16 +406,6 @@ class SystemInformationToolbarItem implements ToolbarItemInterface
     }
 
     /**
-     * Returns LanguageService
-     *
-     * @return \TYPO3\CMS\Lang\LanguageService
-     */
-    protected function getLanguageService()
-    {
-        return $GLOBALS['LANG'];
-    }
-
-    /**
      * Get the SignalSlot dispatcher
      *
      * @return \TYPO3\CMS\Extbase\SignalSlot\Dispatcher
@@ -467,4 +418,23 @@ class SystemInformationToolbarItem implements ToolbarItemInterface
         }
         return $this->signalSlotDispatcher;
     }
+
+    /**
+     * Returns a new standalone view, shorthand function
+     *
+     * @param string $filename Which templateFile should be used.
+     * @return StandaloneView
+     */
+    protected function getFluidTemplateObject(string $filename): StandaloneView
+    {
+        $view = GeneralUtility::makeInstance(StandaloneView::class);
+        $view->setLayoutRootPaths(['EXT:backend/Resources/Private/Layouts']);
+        $view->setPartialRootPaths(['EXT:backend/Resources/Private/Partials/ToolbarItems']);
+        $view->setTemplateRootPaths(['EXT:backend/Resources/Private/Templates/ToolbarItems']);
+
+        $view->setTemplate($filename);
+
+        $view->getRequest()->setControllerExtensionName('Backend');
+        return $view;
+    }
 }
index 86fbf99..4783beb 100644 (file)
@@ -14,12 +14,9 @@ namespace TYPO3\CMS\Backend\Backend\ToolbarItems;
  * The TYPO3 project - inspiring people to share!
  */
 
-use TYPO3\CMS\Backend\Backend\Avatar\Avatar;
 use TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository;
 use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
-use TYPO3\CMS\Core\Imaging\Icon;
-use TYPO3\CMS\Core\Imaging\IconFactory;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Fluid\View\StandaloneView;
 
@@ -29,19 +26,6 @@ use TYPO3\CMS\Fluid\View\StandaloneView;
 class UserToolbarItem implements ToolbarItemInterface
 {
     /**
-     * @var IconFactory
-     */
-    protected $iconFactory;
-
-    /**
-     * Constructor
-     */
-    public function __construct()
-    {
-        $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
-    }
-
-    /**
      * Item is always enabled
      *
      * @return bool TRUE
@@ -52,30 +36,18 @@ class UserToolbarItem implements ToolbarItemInterface
     }
 
     /**
-     * Render username
+     * Render username and an icon
      *
      * @return string HTML
      */
     public function getItem()
     {
         $backendUser = $this->getBackendUser();
-
-        /** @var Avatar $avatar */
-        $avatar =  GeneralUtility::makeInstance(Avatar::class);
-        $icon = $avatar->render();
-
-        $realName = $backendUser->user['realName'];
-        $username = $backendUser->user['username'];
-
         $view = $this->getFluidTemplateObject('UserToolbarItem.html');
         $view->assignMultiple([
-                'username' => $username,
-                'realName' => $realName,
-                'switchUserMode' => $backendUser->user['ses_backuserid'],
-                'icon' => $icon
-            ]
-        );
-
+            'currentUser' => $backendUser->user,
+            'switchUserMode' => $backendUser->user['ses_backuserid'],
+        ]);
         return $view->render();
     }
 
@@ -86,24 +58,14 @@ class UserToolbarItem implements ToolbarItemInterface
      */
     public function getDropDown()
     {
-        $backendUser = $this->getBackendUser();
-
         /** @var BackendModuleRepository $backendModuleRepository */
         $backendModuleRepository = GeneralUtility::makeInstance(BackendModuleRepository::class);
-        /** @var \TYPO3\CMS\Backend\Domain\Model\Module\BackendModule $userModuleMenu */
-        $userModuleMenu = $backendModuleRepository->findByModuleName('user');
-
-        $icon = $this->iconFactory->getIcon('actions-logout', Icon::SIZE_SMALL)->render('inline');
-
         $view = $this->getFluidTemplateObject('UserToolbarItemDropDown.html');
         $view->assignMultiple([
-                'modules' => $userModuleMenu->getChildren(),
-                'logoutUrl' => BackendUtility::getModuleUrl('logout'),
-                'switchUserMode' => $backendUser->user['ses_backuserid'],
-                'icon' => $icon
-            ]
-        );
-
+            'modules' => $backendModuleRepository->findByModuleName('user')->getChildren(),
+            'logoutUrl' => BackendUtility::getModuleUrl('logout'),
+            'switchUserMode' => $this->getBackendUser()->user['ses_backuserid'],
+        ]);
         return $view->render();
     }
 
@@ -114,8 +76,9 @@ class UserToolbarItem implements ToolbarItemInterface
      */
     public function getAdditionalAttributes()
     {
-        $result = [];
-        $result['class'] = 'toolbar-item-user';
+        $result = [
+            'class' => 'toolbar-item-user'
+        ];
         if ($this->getBackendUser()->user['ses_backuserid']) {
             $result['class'] .= ' su-user';
         }
@@ -153,16 +116,6 @@ class UserToolbarItem implements ToolbarItemInterface
     }
 
     /**
-     * Returns LanguageService
-     *
-     * @return \TYPO3\CMS\Lang\LanguageService
-     */
-    protected function getLanguageService()
-    {
-        return $GLOBALS['LANG'];
-    }
-
-    /**
      * Returns a new standalone view, shorthand function
      *
      * @param string $filename Which templateFile should be used.
@@ -171,13 +124,12 @@ class UserToolbarItem implements ToolbarItemInterface
      */
     protected function getFluidTemplateObject(string $filename):StandaloneView
     {
-        /** @var StandaloneView $view */
         $view = GeneralUtility::makeInstance(StandaloneView::class);
-        $view->setLayoutRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Layouts')]);
-        $view->setPartialRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Partials/ToolbarItems')]);
-        $view->setTemplateRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates/ToolbarItems')]);
+        $view->setLayoutRootPaths(['EXT:backend/Resources/Private/Layouts']);
+        $view->setPartialRootPaths(['EXT:backend/Resources/Private/Partials/ToolbarItems']);
+        $view->setTemplateRootPaths(['EXT:backend/Resources/Private/Templates/ToolbarItems']);
 
-        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates/ToolbarItems/' . $filename));
+        $view->setTemplate($filename);
 
         $view->getRequest()->setControllerExtensionName('Backend');
         return $view;
index 48941d8..860c4f2 100644 (file)
@@ -1 +1,6 @@
-<f:render partial="ToolbarItem" arguments="{title: title, icon: icon}"/>
\ No newline at end of file
+<html xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true">
+<f:render partial="ToolbarItem" arguments="{
+       title: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:rm.clearCache_clearCache',
+       icon: '{core:icon(identifier: \'apps-toolbar-menu-cache\', size: \'small\', alternativeMarkupIdentifier: \'inline\')}'
+}" />
+</html>
index 4af3caa..90aac59 100644 (file)
@@ -1,19 +1,24 @@
+<html xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true">
 <h3 class="dropdown-headline">
-    {f:translate(key: title) -> f:format.raw()}
+       <f:translate key="LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:rm.clearCache_clearCache" />
 </h3>
 <hr>
 <div class="dropdown-table">
-    <f:for each="{cacheActions}" as="cacheAction">
-        <div class="dropdown-table-row">
-            <f:link.typolink parameter="{cacheAction.href}" class="toolbar-cache-flush-action">
-                <div class="dropdown-table-column dropdown-table-column-top dropdown-table-icon">
-                    {cacheAction.icon -> f:format.raw()}
-                </div>
-                <div class="dropdown-table-column dropdown-table-column-top dropdown-table-text">
-                    {cacheAction.title}
-                    <br><small class="text-muted">{f:if(condition: cacheAction.description,then: cacheAction.description,else: cacheAction.title) -> f:format.htmlspecialchars()} </small>
-                </div>
-            </f:link.typolink>
-        </div>
-    </f:for>
+       <f:for each="{cacheActions}" as="cacheAction">
+               <div class="dropdown-table-row">
+                       <a href="{cacheAction.href}" class="toolbar-cache-flush-action">
+                               <div class="dropdown-table-column dropdown-table-column-top dropdown-table-icon">
+                                       <core:icon identifier="{cacheAction.iconIdentifier}" size="small" />
+                               </div>
+                               <div class="dropdown-table-column dropdown-table-column-top dropdown-table-text">
+                                       <f:translate key="{cacheAction.title}" />
+                                       <br>
+                                       <small class="text-muted">{f:translate(key: '{f:if(condition: cacheAction.description, then: cacheAction.description, else:
+                                               cacheAction.title)}')}
+                                       </small>
+                               </div>
+                       </a>
+               </div>
+       </f:for>
 </div>
+</html>
index 8d4ca8d..cbbc039 100644 (file)
@@ -1,4 +1,5 @@
-<f:link.typolink parameter="{link}" class="toolbar-cache-flush-action toolbar-item-link" title="{title}">
-    <f:render partial="ToolbarItem" arguments="{title: title, icon: icon}"/>
-</f:link.typolink>
-
+<html xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true">
+<a href="{link}" class="toolbar-cache-flush-action toolbar-item-link" title="{title}">
+       <f:render partial="ToolbarItem" arguments="{title: title, icon: '{core:icon(identifier: iconIdentifier, size: \'small\')'}"/>
+</a>
+</html>
index 48941d8..09988f4 100644 (file)
@@ -1 +1,6 @@
-<f:render partial="ToolbarItem" arguments="{title: title, icon: icon}"/>
\ No newline at end of file
+<html xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true">
+<f:render partial="ToolbarItem" arguments="{
+       title: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.help',
+       icon: '{core:icon(identifier: \'apps-toolbar-menu-help\', size: \'small\', alternativeMarkupIdentifier: \'inline\')}'
+}" />
+</html>
index 9ba9da0..e911628 100644 (file)
@@ -1,23 +1,25 @@
+<html xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true">
 <h3 class="dropdown-headline">
-    {f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.help') -> f:format.raw()}
+       {f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.help') -> f:format.raw()}
 </h3>
 <hr>
 <div class="dropdown-table">
-    <f:for each="{modules}" as="module">
-        <div class="dropdown-table-row"
-             id="{module.name -> f:format.htmlspecialchars()}"
-             data-modulename="{module.name -> f:format.htmlspecialchars()}"
-             data-navigationcomponentid="{module.navigationFrameScript -> f:format.htmlspecialchars()}"
-             data-navigationframescript="{module.navigationFrameScript -> f:format.htmlspecialchars()}"
-             data-navigationframescriptparameters="{module.navigationFrameScriptParameters -> f:format.htmlspecialchars()}">
-            <div class="dropdown-table-column dropdown-table-icon">
-                {module.icon -> f:format.raw()}
-            </div>
-            <div class="dropdown-table-column dropdown-table-title">
-                <f:link.typolink parameter="{module.link}" title="{module.description -> f:format.htmlspecialchars()}" class="modlink">
-                    {module.title}
-                </f:link.typolink>
-            </div>
-        </div>
-    </f:for>
+       <f:for each="{modules}" as="module">
+               <div class="dropdown-table-row"
+                                id="{module.name -> f:format.htmlspecialchars()}"
+                                data-modulename="{module.name -> f:format.htmlspecialchars()}"
+                                data-navigationcomponentid="{module.navigationFrameScript -> f:format.htmlspecialchars()}"
+                                data-navigationframescript="{module.navigationFrameScript -> f:format.htmlspecialchars()}"
+                                data-navigationframescriptparameters="{module.navigationFrameScriptParameters -> f:format.htmlspecialchars()}">
+                       <div class="dropdown-table-column dropdown-table-icon">
+                               {module.icon -> f:format.raw()}
+                       </div>
+                       <div class="dropdown-table-column dropdown-table-title">
+                               <a href="{module.link}" title="{module.description -> f:format.htmlspecialchars()}">
+                                       {module.title}
+                               </a>
+                       </div>
+               </div>
+       </f:for>
 </div>
+</html>
diff --git a/typo3/sysext/backend/Resources/Private/Templates/ToolbarItems/LiveSearchToolbarItem.html b/typo3/sysext/backend/Resources/Private/Templates/ToolbarItems/LiveSearchToolbarItem.html
new file mode 100644 (file)
index 0000000..e4ebf20
--- /dev/null
@@ -0,0 +1,16 @@
+<html xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true">
+<form class="t3js-topbar-navigation-search toolbar-item-search-form live-search-wrapper" role="search">
+       <div class="form-group">
+               <div class="form-control-holder">
+                       <div class="form-control-icon">
+                               <core:icon identifier="apps-toolbar-menu-search" size="small" alternativeMarkupIdentifier="inline"/>
+                       </div>
+                       <input type="text" class="form-control toolbar-item-search-field t3js-topbar-navigation-search-field"
+                                                placeholder="{f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.search') -> f:format.htmlspecialchars()}"
+                                                id="live-search-box" autocomplete="off">
+               </div>
+       </div>
+</form>
+<a href="#" class="dropdown-toggle t3js-toolbar-search-dropdowntoggle" data-toggle="dropdown" aria-expanded="false"></a>
+<div class="dropdown-menu" role="menu"></div>
+</html>
diff --git a/typo3/sysext/backend/Resources/Private/Templates/ToolbarItems/SystemInformationDropDown.html b/typo3/sysext/backend/Resources/Private/Templates/ToolbarItems/SystemInformationDropDown.html
new file mode 100644 (file)
index 0000000..1bb6c26
--- /dev/null
@@ -0,0 +1,69 @@
+<html xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true">
+<span class="systeminformationtoolbaritem-container t3js-systeminformation-container" data-count="{count}"
+                       data-severityclass="{severityBadgeClass}"></span>
+
+<h3 class="dropdown-headline">
+       <f:translate key="systemmessage.header"/>
+</h3>
+<p class="dropdown-text typo3-module-menu-item submodule mod-system_extinstall" data-modulename="system_extinstall">
+       <f:format.raw>
+               <f:translate key="systemmessage.intro" arguments="{0: '{installToolUrl}'}"/>
+       </f:format.raw>
+</p>
+
+<f:if condition="{systemInformation}">
+       <hr>
+       <div class="dropdown-table">
+               <f:for each="{systemInformation}" as="info">
+                       <div class="dropdown-table-row">
+                               <div class="dropdown-table-column dropdown-table-icon">
+                                       <f:if condition="{info.iconIdentifier}">
+                                               <f:then>
+                                                       <core:icon identifier="{info.iconIdentifier}" size="small"/>
+                                               </f:then>
+                                               <f:else>{info.icon -> f:format.raw()}</f:else>
+                                       </f:if>
+                               </div>
+                               <div class="dropdown-table-column dropdown-table-title">
+                                       <f:translate key="{info.title}" default="{info.title}"/>
+                                       <f:if condition="{info.titleAddition}"> ({info.titleAddition -> f:format.htmlspecialchars()})</f:if>
+                               </div>
+                               <div
+                                       class="dropdown-table-column dropdown-table-value {f:if(condition: info.status, then: 'text-{info.status}')}">
+                                       {info.value}
+                               </div>
+                       </div>
+               </f:for>
+       </div>
+</f:if>
+
+<hr>
+
+<f:if condition="{messages -> f:count()} > 0">
+       <f:then>
+               <f:for each="{messages}" as="message">
+                       <f:if condition="{message.module}">
+                               <f:then>
+                                       <p id="systeminformation_{message.module}"
+                                                class="dropdown-text t3js-systeminformation-module typo3-module-menu-item submodule mod-{message.module}"
+                                                data-modulename="{message.module}">
+                                               <span class="text-{message.status}"><f:format.raw>{message.text}</f:format.raw></span>
+                                       </p>
+                               </f:then>
+                               <f:else>
+                                       <p class="dropdown-text text-{message.status}">
+                                               <f:format.raw>{message.text}</f:format.raw>
+                                       </p>
+                               </f:else>
+                       </f:if>
+               </f:for>
+       </f:then>
+       <f:else>
+               <p class="dropdown-text text-success">
+                       <f:format.nl2br>
+                               <f:translate key="systemmessage.allgood"/>
+                       </f:format.nl2br>
+               </p>
+       </f:else>
+</f:if>
+</html>
diff --git a/typo3/sysext/backend/Resources/Private/Templates/ToolbarItems/SystemInformationToolbarItem.html b/typo3/sysext/backend/Resources/Private/Templates/ToolbarItems/SystemInformationToolbarItem.html
new file mode 100644 (file)
index 0000000..12dc106
--- /dev/null
@@ -0,0 +1,7 @@
+<html xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true">
+<f:render partial="ToolbarItem" arguments="{
+       title: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.sysinfo',
+       icon: '{core:icon(identifier: \'actions-system-list-open\', size: \'small\', alternativeMarkupIdentifier: \'inline\')}'
+}" />
+<span class="toolbar-item-badge t3js-systeminformation-counter badge"></span>
+</html>
index 357b282..d5177f7 100644 (file)
@@ -1,14 +1,18 @@
-<span class="toolbar-item-avatar">{icon -> f:format.raw()}</span>
+<html xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers" data-namespace-typo3-fluid="true">
+
+<span class="toolbar-item-avatar"><be:avatar backendUser="{currentUser.uid}"/></span>
 <f:if condition="{switchUserMode}">
-    <f:then>
-        <span class="toolbar-item-name" title="{f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_misc.xlf:switchtouser')} {username}">
-            {f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_misc.xlf:switchtousershort') -> f:format.raw()}
-            {f:if(condition: '{realName}', then: '{realname} ({username})', else: '{username}')}
-        </span>
-    </f:then>
-    <f:else>
-        <span class="toolbar-item-name" title="{username}">
-            {f:if(condition: '{realName}', then: '{realName}', else: '{username}')}
-        </span>
-    </f:else>
+       <f:then>
+               <span class="toolbar-item-name"
+                                       title="{f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_misc.xlf:switchtouser')} {currentUser.username}">
+                       {f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_misc.xlf:switchtousershort') -> f:format.raw()}
+                       {f:if(condition: '{currentUser.realName}', then: '{currentUser.realName} ({currentUser.username})', else: '{currentUser.username}')}
+               </span>
+       </f:then>
+       <f:else>
+               <span class="toolbar-item-name" title="{username}">
+                       {f:if(condition: '{currentUser.realName}', then: '{currentUser.realName}', else: '{currentUser.username}')}
+               </span>
+       </f:else>
 </f:if>
+</html>
index c34ad07..475be8c 100644 (file)
@@ -1,36 +1,38 @@
+<html xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true">
 <h3 class="dropdown-headline">
-    {f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.user')}
+       {f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.user')}
 </h3>
 <hr>
 <f:if condition="{modules}">
-    <div class="dropdown-table">
-        <f:for each="{modules}" as="module">
-            <div class="dropdown-table-row"
-                id="{module.name -> f:format.htmlspecialchars()}"
-                data-modulename="{module.name -> f:format.htmlspecialchars()}"
-                data-navigationcomponentid="{module.navigationComponentId -> f:format.htmlspecialchars()}"
-                data-navigationframescript="{module.navigationFrameScript -> f:format.htmlspecialchars()}"
-                data-navigationframescriptparameters="{module.navigationFrameScriptParameters -> f:format.htmlspecialchars()}"
-            >
-                <div class="dropdown-table-column dropdown-table-icon">{module.icon -> f:format.raw()}</div>
-                <div class="dropdown-table-column dropdown-table-title">
-                    <f:link.typolink parameter="{module.link}" title="{module.description}" class="modlink">
-                        {module.title}
-                    </f:link.typolink>
-                </div>
-            </div>
-        </f:for>
-    </div>
-    <hr>
+       <div class="dropdown-table">
+               <f:for each="{modules}" as="module">
+                       <div class="dropdown-table-row"
+                                        id="{module.name -> f:format.htmlspecialchars()}"
+                                        data-modulename="{module.name -> f:format.htmlspecialchars()}"
+                                        data-navigationcomponentid="{module.navigationComponentId -> f:format.htmlspecialchars()}"
+                                        data-navigationframescript="{module.navigationFrameScript -> f:format.htmlspecialchars()}"
+                                        data-navigationframescriptparameters="{module.navigationFrameScriptParameters -> f:format.htmlspecialchars()}"
+                       >
+                               <div class="dropdown-table-column dropdown-table-icon">{module.icon -> f:format.raw()}</div>
+                               <div class="dropdown-table-column dropdown-table-title">
+                                       <a href="{module.link}" title="{module.description}">
+                                               {module.title}
+                                       </a>
+                               </div>
+                       </div>
+               </f:for>
+       </div>
+       <hr>
 </f:if>
-<f:link.typolink parameter="{logoutUrl}" class="btn btn-danger pull-left" target="_top">
-    {icon -> f:format.raw()}
-    <f:if condition="{switchUserMode}">
-        <f:then>
-            {f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:buttons.exit') -> f:format.raw()}
-        </f:then>
-        <f:else>
-            {f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:buttons.logout') -> f:format.raw()}
-        </f:else>
-    </f:if>
-</f:link.typolink>
+<a href="{logoutUrl}" class="btn btn-danger pull-left" target="_top">
+       <core:icon identifier="actions-logout" size="small" alternativeMarkupIdentifier="inline"/>
+       <f:if condition="{switchUserMode}">
+               <f:then>
+                       {f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:buttons.exit') -> f:format.raw()}
+               </f:then>
+               <f:else>
+                       {f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:buttons.logout') -> f:format.raw()}
+               </f:else>
+       </f:if>
+</a>
+</html>
diff --git a/typo3/sysext/backend/Resources/Private/Templates/ToolbarMenu/SystemInformation.html b/typo3/sysext/backend/Resources/Private/Templates/ToolbarMenu/SystemInformation.html
deleted file mode 100644 (file)
index fd481b4..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-<span class="systeminformationtoolbaritem-container t3js-systeminformation-container" data-count="{count}" data-severityclass="{severityBadgeClass}"></span>
-
-<h3 class="dropdown-headline">
-       <f:translate key="systemmessage.header" />
-</h3>
-<p class="dropdown-text typo3-module-menu-item submodule mod-system_extinstall" data-modulename="system_extinstall">
-       <f:format.raw><f:translate key="systemmessage.intro" arguments="{0: '{installToolUrl}'}" /></f:format.raw>
-</p>
-
-<f:if condition="{systemInformation}">
-       <hr>
-       <div class="dropdown-table">
-               <f:for each="{systemInformation}" as="info">
-                       <div class="dropdown-table-row">
-                               <div class="dropdown-table-column dropdown-table-icon"><f:format.raw>{info.icon}</f:format.raw></div>
-                               <div class="dropdown-table-column dropdown-table-title">{info.title}</div>
-                               <div class="dropdown-table-column dropdown-table-value {f:if(condition: info.status, then: 'text-{info.status}')}">{info.value}</div>
-                       </div>
-               </f:for>
-       </div>
-</f:if>
-
-<hr>
-
-<f:if condition="{messages -> f:count()} > 0">
-       <f:then>
-               <f:for each="{messages}" as="message">
-                       <f:if condition="{message.module}">
-                               <f:then>
-                                       <p id="systeminformation_{message.module}" class="dropdown-text t3js-systeminformation-module typo3-module-menu-item submodule mod-{message.module}" data-modulename="{message.module}">
-                                               <span class="text-{message.status}"><f:format.raw>{message.text}</f:format.raw></span>
-                                       </p>
-                               </f:then>
-                               <f:else>
-                                       <p class="dropdown-text text-{message.status}">
-                                               <f:format.raw>{message.text}</f:format.raw>
-                                       </p>
-                               </f:else>
-                       </f:if>
-               </f:for>
-       </f:then>
-       <f:else>
-               <p class="dropdown-text text-success"><f:format.nl2br><f:translate key="systemmessage.allgood" /></f:format.nl2br></p>
-       </f:else>
-</f:if>
index 0aea761..b3e8a09 100644 (file)
@@ -18,11 +18,14 @@ use Psr\Http\Message\ResponseInterface;
 use Psr\Http\Message\ServerRequestInterface;
 use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Fluid\View\StandaloneView;
 
 /**
- * Alist of all open documents
+ * Main functionality to render a list of all open documents in the top bar of the TYPO3 Backend
+ *
+ * This class also contains hooks and AJAX calls related to the toolbar item dynamic updating processing
  */
 class OpendocsToolbarItem implements ToolbarItemInterface
 {
@@ -52,7 +55,7 @@ class OpendocsToolbarItem implements ToolbarItemInterface
     public function checkAccess()
     {
         $conf = $this->getBackendUser()->getTSConfig('backendToolbarItem.tx_opendocs.disabled');
-        return $conf['value'] != 1;
+        return (int)$conf['value'] !== 1;
     }
 
     /**
@@ -69,41 +72,30 @@ class OpendocsToolbarItem implements ToolbarItemInterface
     }
 
     /**
-     * Render toolbar icon
+     * Render toolbar icon via Fluid
      *
      * @return string HTML
      */
     public function getItem()
     {
-        // Rendering of the output via fluid
-        $view = GeneralUtility::makeInstance(StandaloneView::class);
-        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName(
-            'EXT:opendocs/Resources/Private/Templates/ToolbarItem.html'
-        ));
+        $view = $this->getFluidTemplateObject('ToolbarItem.html');
         $view->assign('numDocs', count($this->openDocs));
         return $view->render();
     }
 
     /**
-     * Render drop down
+     * Render drop down via Fluid
      *
      * @return string HTML
      */
     public function getDropDown()
     {
-        $assigns = [];
-        $openDocuments = $this->openDocs;
-        $recentDocuments = $this->recentDocs;
-        $assigns['openDocuments'] = $this->getMenuEntries($openDocuments);
-        // If there are "recent documents" in the list, add them
-        $assigns['recentDocuments'] = $this->getMenuEntries($recentDocuments);
-
-        // Rendering of the output via fluid
-        $view = GeneralUtility::makeInstance(StandaloneView::class);
-        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName(
-            'EXT:opendocs/Resources/Private/Templates/DropDown.html'
-        ));
-        $view->assignMultiple($assigns);
+        $view = $this->getFluidTemplateObject('DropDown.html');
+        $view->assignMultiple([
+            'openDocuments' => $this->getMenuEntries($this->openDocs),
+            // If there are "recent documents" in the list, add them
+            'recentDocuments' => $this->getMenuEntries($this->recentDocs)
+        ]);
         return $view->render();
     }
 
@@ -113,12 +105,12 @@ class OpendocsToolbarItem implements ToolbarItemInterface
      * @param array $documents
      * @return array
      */
-    protected function getMenuEntries(array $documents) : array
+    protected function getMenuEntries(array $documents): array
     {
         $entries = [];
-        foreach ($documents as $md5sum => $recentDocument) {
-            $menuEntry = $this->getMenuEntry($recentDocument, $md5sum);
-            if ($menuEntry !== '') {
+        foreach ($documents as $md5sum => $document) {
+            $menuEntry = $this->getMenuEntry($document, $md5sum);
+            if (is_array($menuEntry)) {
                 $entries[] = $menuEntry;
             }
         }
@@ -130,7 +122,7 @@ class OpendocsToolbarItem implements ToolbarItemInterface
      *
      * @param array $document
      * @param string $md5sum
-     * @return array The data of a recent or closed document
+     * @return array The data of a recent or closed document, or null if no record was found (e.g. deleted)
      */
     protected function getMenuEntry($document, $md5sum)
     {
@@ -139,7 +131,7 @@ class OpendocsToolbarItem implements ToolbarItemInterface
         $record = BackendUtility::getRecordWSOL($table, $uid);
         if (!is_array($record)) {
             // Record seems to be deleted
-            return '';
+            return null;
         }
         $result = [];
         $result['table'] = $table;
@@ -181,14 +173,12 @@ class OpendocsToolbarItem implements ToolbarItemInterface
      ***    HOOKS    ***
      *******************/
     /**
-     * Called as a hook in \TYPO3\CMS\Backend\Utility\BackendUtility::setUpdateSignal, calls a JS function to change
+     * Called as a hook in \TYPO3\CMS\Backend\Utility\BackendUtility::getUpdateSignalCode, calls a JS function to change
      * the number of opened documents
      *
      * @param array $params
-     * @param unknown_type $ref
-     * @return string list item HTML attributes
      */
-    public function updateNumberOfOpenDocsHook(&$params, $ref)
+    public function updateNumberOfOpenDocsHook(&$params)
     {
         $params['JScode'] = '
                        if (top && top.TYPO3.OpendocsMenu) {
@@ -209,9 +199,9 @@ class OpendocsToolbarItem implements ToolbarItemInterface
      */
     public function closeDocument(ServerRequestInterface $request, ResponseInterface $response)
     {
-        $backendUser = $this->getBackendUser();
         $md5sum = isset($request->getParsedBody()['md5sum']) ? $request->getParsedBody()['md5sum'] : $request->getQueryParams()['md5sum'];
         if ($md5sum && isset($this->openDocs[$md5sum])) {
+            $backendUser = $this->getBackendUser();
             // Add the document to be closed to the recent documents
             $this->recentDocs = array_merge([$md5sum => $this->openDocs[$md5sum]], $this->recentDocs);
             // Allow a maximum of 8 recent documents
@@ -253,10 +243,32 @@ class OpendocsToolbarItem implements ToolbarItemInterface
     /**
      * Returns the current BE user.
      *
-     * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
+     * @return BackendUserAuthentication
      */
     protected function getBackendUser()
     {
         return $GLOBALS['BE_USER'];
     }
+
+    /**
+     * Returns a new standalone view, shorthand function
+     *
+     * @param string $filename Which templateFile should be used.
+     * @return StandaloneView
+     */
+    protected function getFluidTemplateObject(string $filename): StandaloneView
+    {
+        $view = GeneralUtility::makeInstance(StandaloneView::class);
+        $view->setLayoutRootPaths(['EXT:opendocs/Resources/Private/Layouts']);
+        $view->setPartialRootPaths([
+            'EXT:backend/Resources/Private/Partials/ToolbarItems',
+            'EXT:opendocs/Resources/Private/Partials/ToolbarItems'
+        ]);
+        $view->setTemplateRootPaths(['EXT:opendocs/Resources/Private/Templates/ToolbarItems']);
+
+        $view->setTemplate($filename);
+
+        $view->getRequest()->setControllerExtensionName('Opendocs');
+        return $view;
+    }
 }
diff --git a/typo3/sysext/opendocs/Resources/Private/Templates/DropDown.html b/typo3/sysext/opendocs/Resources/Private/Templates/DropDown.html
deleted file mode 100644 (file)
index 722ae74..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-<f:be.pageRenderer includeRequireJsModules="{0:'TYPO3/CMS/Opendocs/Toolbar/OpendocsMenu'}" />
-
-<h3 class="dropdown-headline">
-    {f:translate(key: 'toolbaritem', extensionName: 'opendocs')}
-</h3>
-<hr>
-
-<f:if condition="{noDocs}">
-    <f:then>
-        <p><f:translate key="no_docs" extensionName="opendocs"/></p>
-    </f:then>
-    <f:else>
-        <f:if condition="{openDocuments}">
-            <h3 class="dropdown-headline">
-                <f:translate key="open_docs" extensionName="opendocs"/>
-            </h3>
-            <div class="dropdown-table">
-                <f:for each="{openDocuments}" as="openDocument">
-                    <div class="dropdown-table-row t3js-topbar-opendocs-item">
-                        <div class="dropdown-table-column dropdown-table-icon">
-                            <core:iconForRecord table="{openDocument.table}" row="{openDocument.record}" />
-                        </div>
-                        <div class="dropdown-table-column dropdown-table-title">
-                            <a class="dropdown-table-title-ellipsis" href="#" onclick="{openDocument.onClickCode}" target="contentIframe">
-                                {openDocument.label}
-                            </a>
-                        </div>
-                        <div class="dropdown-table-column dropdown-table-actions">
-                            <a href="#" class="dropdown-table-actions-btn dropdown-table-actions-btn-close t3js-topbar-opendocs-close" data-opendocsidentifier="{openDocument.md5sum}" title="{f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:rm.closeDoc')}">
-                                <core:icon identifier="actions-close" alternativeMarkupIdentifier="inline" />
-                            </a>
-                        </div>
-                    </div>
-                </f:for>
-            </div>
-            <hr>
-        </f:if>
-        <f:if condition="{recentDocuments}">
-            <h3 class="dropdown-headline">
-                <f:translate key="recent_docs" extensionName="opendocs"/>
-            </h3>
-            <div class="dropdown-table">
-                <f:for each="{recentDocuments}" as="recentDocument">
-                    <div class="dropdown-table-row t3js-topbar-recentdoc">
-                        <div class="dropdown-table-column dropdown-table-icon">
-                            <core:iconForRecord table="{recentDocument.table}" row="{recentDocument.record}" />
-                        </div>
-                        <div class="dropdown-table-column dropdown-table-title">
-                            <a class="dropdown-table-title-ellipsis" href="#" onclick="{recentDocument.onClickCode}" target="contentIframe">
-                                {recentDocument.label}
-                            </a>
-                        </div>
-                    </div>
-                </f:for>
-            </div>
-        </f:if>
-    </f:else>
-</f:if>
diff --git a/typo3/sysext/opendocs/Resources/Private/Templates/ToolbarItem.html b/typo3/sysext/opendocs/Resources/Private/Templates/ToolbarItem.html
deleted file mode 100644 (file)
index f646406..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<span class="toolbar-item-icon" title="{f:translate(key: 'toolbaritem', extensionName: 'opendocs')}">
-    <core:icon identifier="apps-toolbar-menu-opendocs" alternativeMarkupIdentifier="inline" />
-</span>
-<span class="toolbar-item-title">{f:translate(key: 'toolbaritem', extensionName: 'opendocs')}</span>
-<span class="toolbar-item-badge badge" id="tx-opendocs-counter">{numDocs}</span>
diff --git a/typo3/sysext/opendocs/Resources/Private/Templates/ToolbarItems/DropDown.html b/typo3/sysext/opendocs/Resources/Private/Templates/ToolbarItems/DropDown.html
new file mode 100644 (file)
index 0000000..bc5e22f
--- /dev/null
@@ -0,0 +1,66 @@
+<html xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true">
+<f:be.pageRenderer includeRequireJsModules="{0:'TYPO3/CMS/Opendocs/Toolbar/OpendocsMenu'}"/>
+
+<h3 class="dropdown-headline">
+       {f:translate(key: 'toolbaritem', extensionName: 'opendocs')}
+</h3>
+<hr>
+
+<f:if condition="{noDocs}">
+       <f:then>
+               <p>
+                       <f:translate key="no_docs" extensionName="opendocs"/>
+               </p>
+       </f:then>
+       <f:else>
+               <f:if condition="{openDocuments}">
+                       <h3 class="dropdown-headline">
+                               <f:translate key="open_docs" extensionName="opendocs"/>
+                       </h3>
+                       <div class="dropdown-table">
+                               <f:for each="{openDocuments}" as="openDocument">
+                                       <div class="dropdown-table-row t3js-topbar-opendocs-item">
+                                               <div class="dropdown-table-column dropdown-table-icon">
+                                                       <core:iconForRecord table="{openDocument.table}" row="{openDocument.record}"/>
+                                               </div>
+                                               <div class="dropdown-table-column dropdown-table-title">
+                                                       <a class="dropdown-table-title-ellipsis" href="#" onclick="{openDocument.onClickCode}"
+                                                                target="contentIframe">
+                                                               {openDocument.label}
+                                                       </a>
+                                               </div>
+                                               <div class="dropdown-table-column dropdown-table-actions">
+                                                       <a href="#" class="dropdown-table-actions-btn dropdown-table-actions-btn-close t3js-topbar-opendocs-close"
+                                                                data-opendocsidentifier="{openDocument.md5sum}"
+                                                                title="{f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:rm.closeDoc')}">
+                                                               <core:icon identifier="actions-close" alternativeMarkupIdentifier="inline"/>
+                                                       </a>
+                                               </div>
+                                       </div>
+                               </f:for>
+                       </div>
+                       <hr>
+               </f:if>
+               <f:if condition="{recentDocuments}">
+                       <h3 class="dropdown-headline">
+                               <f:translate key="recent_docs" extensionName="opendocs"/>
+                       </h3>
+                       <div class="dropdown-table">
+                               <f:for each="{recentDocuments}" as="recentDocument">
+                                       <div class="dropdown-table-row t3js-topbar-recentdoc">
+                                               <div class="dropdown-table-column dropdown-table-icon">
+                                                       <core:iconForRecord table="{recentDocument.table}" row="{recentDocument.record}"/>
+                                               </div>
+                                               <div class="dropdown-table-column dropdown-table-title">
+                                                       <a class="dropdown-table-title-ellipsis" href="#" onclick="{recentDocument.onClickCode}"
+                                                                target="contentIframe">
+                                                               {recentDocument.label}
+                                                       </a>
+                                               </div>
+                                       </div>
+                               </f:for>
+                       </div>
+               </f:if>
+       </f:else>
+</f:if>
+</html>
diff --git a/typo3/sysext/opendocs/Resources/Private/Templates/ToolbarItems/ToolbarItem.html b/typo3/sysext/opendocs/Resources/Private/Templates/ToolbarItems/ToolbarItem.html
new file mode 100644 (file)
index 0000000..db78029
--- /dev/null
@@ -0,0 +1,7 @@
+<html xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true">
+<span class="toolbar-item-icon" title="{f:translate(key: 'toolbaritem', extensionName: 'opendocs')}">
+       <core:icon identifier="apps-toolbar-menu-opendocs" alternativeMarkupIdentifier="inline"/>
+</span>
+<span class="toolbar-item-title">{f:translate(key: 'toolbaritem', extensionName: 'opendocs')}</span>
+<span class="toolbar-item-badge badge" id="tx-opendocs-counter">{numDocs}</span>
+</html>
index e340cb9..5134cdd 100644 (file)
@@ -20,9 +20,8 @@ use TYPO3\CMS\Core\Database\Connection;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
 use TYPO3\CMS\Core\Database\Query\Restriction\RootLevelRestriction;
-use TYPO3\CMS\Core\Imaging\Icon;
-use TYPO3\CMS\Core\Imaging\IconFactory;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Fluid\View\StandaloneView;
 use TYPO3\CMS\SysAction\ActionTask;
 
 /**
@@ -31,38 +30,18 @@ use TYPO3\CMS\SysAction\ActionTask;
 class ActionToolbarItem implements ToolbarItemInterface
 {
     /**
-     * @var array List of action entries
+     * @var array
      */
-    protected $actionEntries = [];
+    protected $availableActions = [];
 
     /**
-     * @var IconFactory
-     */
-    protected $iconFactory;
-
-    /**
-     * Constructor
-     */
-    public function __construct()
-    {
-        $this->getLanguageService()->includeLLFile('EXT:sys_action/Resources/Private/Language/locallang.xlf');
-        $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
-        $this->initializeActionEntries();
-    }
-
-    /**
-     * Render toolbar icon
+     * Render toolbar icon via Fluid
      *
      * @return string HTML
      */
     public function getItem()
     {
-        $title = htmlspecialchars($this->getLanguageService()->getLL('action_toolbaritem'));
-        $icon = $this->iconFactory->getIcon('apps-toolbar-menu-actions', Icon::SIZE_SMALL)->render('inline');
-        return '
-            <span class="toolbar-item-icon" title="' . $title . '">' . $icon . '</span>
-            <span class="toolbar-item-title">' . $title . '</span>
-        ';
+        return $this->getFluidTemplateObject('ToolbarItem.html')->render();
     }
 
     /**
@@ -72,31 +51,17 @@ class ActionToolbarItem implements ToolbarItemInterface
      */
     public function getDropDown()
     {
-        $actionMenu = [];
-        $actionMenu[] = '<h3 class="dropdown-headline">' . htmlspecialchars($this->getLanguageService()->getLL('sys_action')) . '</h3>';
-        $actionMenu[] = '<hr>';
-        $actionMenu[] = '<div class="dropdown-table">';
-        foreach ($this->actionEntries as $linkConf) {
-            $actionMenu[] = '<div class="dropdown-table-row">';
-            $actionMenu[] = '<div class="dropdown-table-column dropdown-table-icon">';
-            $actionMenu[] = $linkConf[2];
-            $actionMenu[] = '</div>';
-            $actionMenu[] = '<div class="dropdown-table-column dropdown-table-title">';
-            $actionMenu[] = '<a class="t3js-topbar-link" href="' . htmlspecialchars($linkConf[1]) . '" target="list_frame">';
-            $actionMenu[] = htmlspecialchars($linkConf[0]);
-            $actionMenu[] = '</a>';
-            $actionMenu[] = '</div>';
-            $actionMenu[] = '</div>';
-        }
-        $actionMenu[] = '</div>';
-        return implode(LF, $actionMenu);
+        $view = $this->getFluidTemplateObject('DropDown.html');
+        $view->assign('actions', $this->availableActions);
+        return $view->render();
     }
 
     /**
-     * Gets the entries for the action menu
+     * Stores the entries for the action menu in $this->availableActions
      */
-    protected function initializeActionEntries()
+    protected function setAvailableActions()
     {
+        $actionEntries = [];
         $backendUser = $this->getBackendUser();
 
         $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_action');
@@ -115,7 +80,6 @@ class ActionToolbarItem implements ToolbarItemInterface
             $queryBuilder->orderBy('sys_action.' . $GLOBALS['TCA']['sys_action']['ctrl']['sortby']);
         }
 
-        $actions = [];
         if (!$backendUser->isAdmin()) {
             $groupList = $backendUser->groupList ?: '0';
 
@@ -152,18 +116,16 @@ class ActionToolbarItem implements ToolbarItemInterface
 
         $result = $queryBuilder->execute();
         while ($actionRow = $result->fetch()) {
-            $actions[] = [
-                $actionRow['title'],
-                sprintf(
-                    '%s&SET[mode]=tasks&SET[function]=sys_action.%s&show=%u',
-                    BackendUtility::getModuleUrl('user_task'),
-                    ActionTask::class, // @todo: class name string is hand over as url parameter?!
-                    $actionRow['uid']
-                ),
-                $this->iconFactory->getIconForRecord('sys_action', $actionRow, Icon::SIZE_SMALL)->render()
-            ];
+            $actionRow['link'] = sprintf(
+                '%s&SET[mode]=tasks&SET[function]=sys_action.%s&show=%u',
+                BackendUtility::getModuleUrl('user_task'),
+                ActionTask::class, // @todo: class name string is hand over as url parameter?!
+                $actionRow['uid']
+            );
+            $actionEntries[] = $actionRow;
         }
-        $this->actionEntries = $actions;
+
+        $this->availableActions = $actionEntries;
     }
 
     /**
@@ -189,15 +151,12 @@ class ActionToolbarItem implements ToolbarItemInterface
     /**
      * This toolbar is rendered if there are action entries, no further user restriction
      *
-     * @return bool TRUE
+     * @return bool
      */
     public function checkAccess()
     {
-        $result = false;
-        if (!empty($this->actionEntries)) {
-            $result = true;
-        }
-        return $result;
+        $this->setAvailableActions();
+        return !empty($this->availableActions);
     }
 
     /**
@@ -221,12 +180,23 @@ class ActionToolbarItem implements ToolbarItemInterface
     }
 
     /**
-     * Returns LanguageService
+     * Returns a new standalone view, shorthand function
      *
-     * @return \TYPO3\CMS\Lang\LanguageService
+     * @param string $filename Which templateFile should be used.
+     * @return StandaloneView
      */
-    protected function getLanguageService()
+    protected function getFluidTemplateObject(string $filename): StandaloneView
     {
-        return $GLOBALS['LANG'];
+        $view = GeneralUtility::makeInstance(StandaloneView::class);
+        $view->setLayoutRootPaths(['EXT:sys_action/Resources/Private/Layouts']);
+        $view->setPartialRootPaths([
+            'EXT:backend/Resources/Private/Partials/ToolbarItems',
+            'EXT:sys_action/Resources/Private/Partials'
+        ]);
+        $view->setTemplateRootPaths(['EXT:sys_action/Resources/Private/Templates/ToolbarItems']);
+        $view->setTemplate($filename);
+
+        $view->getRequest()->setControllerExtensionName('SysAction');
+        return $view;
     }
 }
diff --git a/typo3/sysext/sys_action/Resources/Private/Templates/ToolbarItems/DropDown.html b/typo3/sysext/sys_action/Resources/Private/Templates/ToolbarItems/DropDown.html
new file mode 100644 (file)
index 0000000..6defe2b
--- /dev/null
@@ -0,0 +1,22 @@
+<html xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true">
+<h3 class="dropdown-headline">
+       <f:translate key="sys_action"/>
+</h3>
+<hr>
+<div class="dropdown-table">
+       <f:for each="{actions}" as="action">
+               <div class="dropdown-table-row">
+                       <div class="dropdown-table-column dropdown-table-icon">
+                               <a href="{action.link -> f:format.htmlspecialchars()}" class="t3js-topbar-link" target="list_frame">
+                                       <core:iconForRecord table="sys_action" row="{action}" size="small"/>
+                               </a>
+                       </div>
+                       <div class="dropdown-table-column dropdown-table-title">
+                               <a href="{action.link -> f:format.htmlspecialchars()}" class="t3js-topbar-link" target="list_frame">
+                                       {action.title -> f:format.htmlspecialchars()}
+                               </a>
+                       </div>
+               </div>
+       </f:for>
+</div>
+</html>
diff --git a/typo3/sysext/sys_action/Resources/Private/Templates/ToolbarItems/ToolbarItem.html b/typo3/sysext/sys_action/Resources/Private/Templates/ToolbarItems/ToolbarItem.html
new file mode 100644 (file)
index 0000000..9a735e2
--- /dev/null
@@ -0,0 +1,6 @@
+<html xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true">
+<f:render partial="ToolbarItem" arguments="{
+       title: 'LLL:EXT:sys_action/Resources/Private/Language/locallang.xlf:action_toolbaritem',
+       icon: '{core:icon(identifier: \'apps-toolbar-menu-actions\', size: \'small\', alternativeMarkupIdentifier: \'inline\')}'
+}" />
+</html>
index e08f4d2..a8ab6eb 100644 (file)
@@ -15,10 +15,10 @@ namespace TYPO3\CMS\Workspaces\Backend\ToolbarItems;
  */
 
 use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
-use TYPO3\CMS\Core\Imaging\Icon;
-use TYPO3\CMS\Core\Imaging\IconFactory;
+use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Core\Page\PageRenderer;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Fluid\View\StandaloneView;
 use TYPO3\CMS\Workspaces\Service\WorkspaceService;
 
 /**
@@ -32,20 +32,13 @@ class WorkspaceSelectorToolbarItem implements ToolbarItemInterface
     protected $availableWorkspaces;
 
     /**
-     * @var IconFactory
-     */
-    protected $iconFactory;
-
-    /**
      * Constructor
      */
     public function __construct()
     {
-        /** @var \TYPO3\CMS\Workspaces\Service\WorkspaceService $wsService */
-        $wsService = GeneralUtility::makeInstance(WorkspaceService::class);
-        $this->availableWorkspaces = $wsService->getAvailableWorkspaces();
+        $this->availableWorkspaces = GeneralUtility::makeInstance(WorkspaceService::class)
+            ->getAvailableWorkspaces();
 
-        $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
         $pageRenderer = $this->getPageRenderer();
         $pageRenderer->addInlineLanguageLabel('Workspaces.workspaceTitle', WorkspaceService::getWorkspaceTitle($this->getBackendUser()->workspace));
         $pageRenderer->loadRequireJsModule('TYPO3/CMS/Workspaces/Toolbar/WorkspacesMenu');
@@ -71,12 +64,7 @@ class WorkspaceSelectorToolbarItem implements ToolbarItemInterface
         if (empty($this->availableWorkspaces)) {
             return '';
         }
-        $title = htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.workspace'));
-        $icon = $this->iconFactory->getIcon('apps-toolbar-menu-workspace', Icon::SIZE_SMALL)->render('inline');
-        return '
-            <span class="toolbar-item-icon" title="' . $title . '">' . $icon . '</span>
-            <span class="toolbar-item-title">' . $title . '</span>
-            ';
+        return $this->getFluidTemplateObject('ToolbarItem.html')->render();
     }
 
     /**
@@ -86,77 +74,34 @@ class WorkspaceSelectorToolbarItem implements ToolbarItemInterface
      */
     public function getDropDown()
     {
+        $topItem = null;
+        $additionalItems = [];
         $backendUser = $this->getBackendUser();
-        $languageService = $this->getLanguageService();
-
-        $index = 0;
+        $view = $this->getFluidTemplateObject('DropDown.html');
         $activeWorkspace = (int)$backendUser->workspace;
-        $stateCheckedIcon = $this->iconFactory->getIcon('status-status-checked', Icon::SIZE_SMALL)->render();
-        $stateUncheckedIcon = '<span title="' . htmlspecialchars($languageService->getLL('bookmark_inactive')) . '">' . $this->iconFactory->getIcon('empty-empty', Icon::SIZE_SMALL)->render() . '</span>';
-        $workspaceSections = [
-            'top' => [],
-            'items' => [],
-        ];
-
         foreach ($this->availableWorkspaces as $workspaceId => $label) {
             $workspaceId = (int)$workspaceId;
-            $iconState = ($workspaceId === $activeWorkspace ? $stateCheckedIcon : $stateUncheckedIcon);
-            $classValue = ($workspaceId === $activeWorkspace ? 'selected' : '');
-            $sectionName = ($index++ === 0 ? 'top' : 'items');
-            $workspaceSections[$sectionName][] = '
-                <div class="dropdown-table-row t3js-workspace-item ' . $classValue . '">
-                    <div class="dropdown-table-column dropdown-table-icon">
-                        ' . $iconState . '
-                    </div>
-                    <div class="dropdown-table-column">
-                        <a href="' . htmlspecialchars(\TYPO3\CMS\Backend\Utility\BackendUtility::getModuleUrl('main', ['changeWorkspace' => $workspaceId])) . '" data-workspaceid="' . $workspaceId . '" class="t3js-workspaces-switchlink">
-                            ' . htmlspecialchars($label) . '
-                        </a>
-                    </div>
-                </div>
-            ';
-        }
-
-        if (!empty($workspaceSections['top'])) {
-            // Add the "Go to workspace module" link
-            // if there is at least one icon on top and if the access rights are there
-            if ($backendUser->check('modules', 'web_WorkspacesWorkspaces')) {
-                $workspaceSections['top'][] = '
-                    <div class="dropdown-table-row">
-                        <div class="dropdown-table-column dropdown-table-icon">
-                            ' . $stateUncheckedIcon . '
-                        </div>
-                        <div class="dropdown-table-column">
-                            <a href="#" target="list_frame" data-module="web_WorkspacesWorkspaces" class="t3js-workspaces-modulelink">
-                                ' . htmlspecialchars($languageService->getLL('bookmark_workspace')) . '
-                            </a>
-                        </div>
-                    </div>
-                ';
+            $item = [
+                'isActive'    => $workspaceId === $activeWorkspace,
+                'label'       => $label,
+                'link'        => BackendUtility::getModuleUrl('main', ['changeWorkspace' => $workspaceId]),
+                'workspaceId' => $workspaceId
+            ];
+            if ($topItem === null) {
+                $topItem = $item;
+            } else {
+                $additionalItems[] = $item;
             }
-        } else {
-            // no items on top (= no workspace to work in)
-            $workspaceSections['top'][] = '
-                <div class="dropdown-table-row">
-                    <div class="dropdown-table-column dropdown-table-icon">
-                        ' . $stateUncheckedIcon . '
-                    </div>
-                    <div class="dropdown-table-column">
-                        ' . htmlspecialchars($languageService->getLL('bookmark_noWSfound')) . '
-                    </div>
-                </div>
-            ';
         }
 
-        $workspaceMenu = [
-            '<h3 class="dropdown-headline">' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.workspace')) . '</h3>',
-            '<hr>',
-            '<div class="dropdown-table">' . implode(LF, $workspaceSections['top']) . '</div>',
-            (!empty($workspaceSections['items']) ? '<hr>' : ''),
-            '<div class="dropdown-table">' . implode(LF, $workspaceSections['items']) . '</div>',
-        ];
-
-        return implode(LF, $workspaceMenu);
+        // Add the "Go to workspace module" link
+        // if there is at least one icon on top and if the access rights are there
+        if ($topItem !== null && $backendUser->check('modules', 'web_WorkspacesWorkspaces')) {
+            $view->assign('showLinkToModule', true);
+        }
+        $view->assign('topItem', $topItem);
+        $view->assign('additionalItems', $additionalItems);
+        return $view->render();
     }
 
     /**
@@ -210,12 +155,24 @@ class WorkspaceSelectorToolbarItem implements ToolbarItemInterface
     }
 
     /**
-     * Returns LanguageService
+     * Returns a new standalone view, shorthand function
      *
-     * @return \TYPO3\CMS\Lang\LanguageService
+     * @param string $filename Which templateFile should be used.
+     * @return StandaloneView
      */
-    protected function getLanguageService()
+    protected function getFluidTemplateObject(string $filename): StandaloneView
     {
-        return $GLOBALS['LANG'];
+        $view = GeneralUtility::makeInstance(StandaloneView::class);
+        $view->setLayoutRootPaths(['EXT:workspaces/Resources/Private/Layouts']);
+        $view->setPartialRootPaths([
+            'EXT:backend/Resources/Private/Partials/ToolbarItems',
+            'EXT:workspaces/Resources/Private/Partials/ToolbarItems'
+        ]);
+        $view->setTemplateRootPaths(['EXT:workspaces/Resources/Private/Templates/ToolbarItems']);
+
+        $view->setTemplate($filename);
+
+        $view->getRequest()->setControllerExtensionName('Workspaces');
+        return $view;
     }
 }
diff --git a/typo3/sysext/workspaces/Resources/Private/Templates/ToolbarItems/DropDown.html b/typo3/sysext/workspaces/Resources/Private/Templates/ToolbarItems/DropDown.html
new file mode 100644 (file)
index 0000000..fe5f526
--- /dev/null
@@ -0,0 +1,71 @@
+<html xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true">
+<h3 class="dropdown-headline">
+       <f:translate key="LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.workspace" />
+</h3>
+
+<hr>
+
+<div class="dropdown-table">
+       <f:if condition="{topItem}">
+               <f:then>
+                       <f:render section="workspaceItem" arguments="{item: topItem}" />
+                       <f:if condition="{showLinkToModule}">
+                               <div class="dropdown-table-row">
+                                       <div class="dropdown-table-column dropdown-table-icon">
+                                               <f:render section="uncheckedIcon" />
+                                       </div>
+                                       <div class="dropdown-table-column">
+                                               <a href="#" target="list_frame" data-module="web_WorkspacesWorkspaces" class="t3js-workspaces-modulelink">
+                                                       <f:translate key="LLL:EXT:lang/Resources/Private/Language/locallang_misc.xlf:bookmark_workspace" />
+                                               </a>
+                                       </div>
+                               </div>
+                       </f:if>
+               </f:then>
+               <f:else>
+                       <f:comment>no items on top (= no workspace to work in)</f:comment>
+                       <div class="dropdown-table-row">
+                               <div class="dropdown-table-column dropdown-table-icon">
+                                       <f:render section="uncheckedIcon" />
+                               </div>
+                               <div class="dropdown-table-column">
+                                       <f:translate key="LLL:EXT:lang/Resources/Private/Language/locallang_misc.xlf:bookmark_noWSfound" />
+                               </div>
+                       </div>
+               </f:else>
+       </f:if>
+</div>
+
+<f:if condition="{additionalItems}">
+
+       <hr>
+
+       <div class="dropdown-table">
+               <f:for each="{additionalItems}" as="item">
+                       <f:render section="workspaceItem" arguments="{item: item}" />
+               </f:for>
+       </div>
+</f:if>
+
+<f:section name="workspaceItem">
+       <div class="dropdown-table-row t3js-workspace-item{f:if(condition: item.isActive, then: ' selected')}">
+               <div class="dropdown-table-column dropdown-table-icon">
+                       <f:if condition="{item.isActive}">
+                               <f:then><core:icon identifier="status-status-checked" size="small" /></f:then>
+                               <f:else><f:render section="uncheckedIcon" /></f:else>
+                       </f:if>
+               </div>
+               <div class="dropdown-table-column">
+                       <a href="{item.link}" data-workspaceid="{item.workspaceId}" class="t3js-workspaces-switchlink">
+                               {item.label -> f:format.htmlspecialchars()}
+                       </a>
+               </div>
+       </div>
+</f:section>
+
+<f:section name="uncheckedIcon">
+       <span title="{f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_misc.xlf:bookmark_inactive')}">
+               <core:icon identifier="empty-empty" size="small" />
+       </span>
+</f:section>
+</html>
diff --git a/typo3/sysext/workspaces/Resources/Private/Templates/ToolbarItems/ToolbarItem.html b/typo3/sysext/workspaces/Resources/Private/Templates/ToolbarItems/ToolbarItem.html
new file mode 100644 (file)
index 0000000..9948d9f
--- /dev/null
@@ -0,0 +1,6 @@
+<html xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true">
+<f:render partial="ToolbarItem" arguments="{
+       title: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:toolbarItems.workspace',
+       icon: '{core:icon(identifier: \'apps-toolbar-menu-workspace\', size: \'small\', alternativeMarkupIdentifier: \'inline\')}'
+}" />
+</html>