[TASK] ToolbarItem interface improvements 05/34205/12
authorChristian Kuhn <lolli@schwarzbu.ch>
Sat, 15 Nov 2014 12:55:22 +0000 (13:55 +0100)
committerChristian Kuhn <lolli@schwarzbu.ch>
Sat, 15 Nov 2014 21:35:41 +0000 (22:35 +0100)
Change new interface splitting item and drop down.
Refactor all toolbar items accordingly.
Styling changes will be done with second patch.

Change-Id: I6bfa87dbc85eb0312f4748283de788e27dda590e
Resolves: #62997
Releases: master
Reviewed-on: http://review.typo3.org/34205
Reviewed-by: Felix Kopp <felix-source@phorax.com>
Tested-by: Felix Kopp <felix-source@phorax.com>
Reviewed-by: Benjamin Mack <benni@typo3.org>
Tested-by: Benjamin Mack <benni@typo3.org>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
19 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/UserToolbarItem.php
typo3/sysext/backend/Classes/Controller/BackendController.php
typo3/sysext/backend/Classes/Toolbar/ToolbarItemInterface.php
typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/ClearCacheMenu.js
typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/ShortcutMenu.js
typo3/sysext/backend/ext_localconf.php
typo3/sysext/core/Classes/Page/PageRenderer.php
typo3/sysext/core/Configuration/DefaultConfiguration.php
typo3/sysext/opendocs/Classes/Backend/ToolbarItems/OpendocsToolbarItem.php
typo3/sysext/opendocs/Resources/Public/JavaScript/Toolbar/OpendocsMenu.js
typo3/sysext/sys_action/Classes/Backend/ToolbarItems/ActionToolbarItem.php
typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_topbar.less
typo3/sysext/t3skin/Resources/Public/Css/visual/t3skin.css
typo3/sysext/workspaces/Classes/Backend/ToolbarItems/WorkspaceSelectorToolbarItem.php
typo3/sysext/workspaces/Resources/Public/JavaScript/Toolbar/WorkspacesMenu.js

index bccb8a5..3d72180 100644 (file)
@@ -18,9 +18,10 @@ use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Backend\Utility\IconUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
+use TYPO3\CMS\Backend\Toolbar\ClearCacheActionsHookInterface;
 
 /**
- * class to render the menu for the cache clearing actions
+ * Render cache clearing toolbar item
  *
  * @author Ingo Renner <ingo@typo3.org>
  */
@@ -29,43 +30,31 @@ class ClearCacheToolbarItem implements ToolbarItemInterface {
        /**
         * @var array
         */
-       protected $cacheActions;
+       protected $cacheActions = array();
 
        /**
         * @var array
         */
-       protected $optionValues;
-
-       /**
-        * @var \TYPO3\CMS\Backend\Controller\BackendController
-        */
-       protected $backendReference;
-
-       /**
-        * TODO potentially unused
-        * @var string
-        */
-       public $backPath = '';
+       protected $optionValues = array();
 
        /**
         * Constructor
         *
-        * @param \TYPO3\CMS\Backend\Controller\BackendController $backendReference TYPO3 backend object reference
         * @throws \UnexpectedValueException
         */
-       public function __construct(\TYPO3\CMS\Backend\Controller\BackendController &$backendReference = NULL) {
-               $this->backendReference = $backendReference;
-               $this->cacheActions = array();
-               $this->optionValues = array();
+       public function __construct() {
                $backendUser = $this->getBackendUser();
+               $languageService = $this->getLanguageService();
+
+               $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Toolbar/ClearCacheMenu');
 
                // Clear all page-related caches
                if ($backendUser->isAdmin() || $backendUser->getTSConfigVal('options.clearCache.pages')) {
                        $this->cacheActions[] = array(
                                'id' => 'pages',
-                               'title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:flushPageCachesTitle', TRUE),
-                               'description' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:flushPageCachesDescription', TRUE),
-                               'href' => $this->backPath . 'tce_db.php?vC=' . $backendUser->veriCode() . '&cacheCmd=pages&ajaxCall=1' . BackendUtility::getUrlToken('tceAction'),
+                               'title' => $languageService->sL('LLL:EXT:lang/locallang_core.xlf:flushPageCachesTitle', TRUE),
+                               'description' => $languageService->sL('LLL:EXT:lang/locallang_core.xlf:flushPageCachesDescription', TRUE),
+                               'href' => 'tce_db.php?vC=' . $backendUser->veriCode() . '&cacheCmd=pages&ajaxCall=1' . BackendUtility::getUrlToken('tceAction'),
                                'icon' => IconUtility::getSpriteIcon('actions-system-cache-clear-impact-low')
                        );
                        $this->optionValues[] = 'pages';
@@ -75,9 +64,9 @@ class ClearCacheToolbarItem implements ToolbarItemInterface {
                if ($backendUser->isAdmin() || $backendUser->getTSConfigVal('options.clearCache.all')) {
                        $this->cacheActions[] = array(
                                'id' => 'all',
-                               'title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:flushGeneralCachesTitle', TRUE),
-                               'description' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:flushGeneralCachesDescription', TRUE),
-                               'href' => $this->backPath . 'tce_db.php?vC=' . $backendUser->veriCode() . '&cacheCmd=all&ajaxCall=1' . BackendUtility::getUrlToken('tceAction'),
+                               'title' => $languageService->sL('LLL:EXT:lang/locallang_core.xlf:flushGeneralCachesTitle', TRUE),
+                               'description' => $languageService->sL('LLL:EXT:lang/locallang_core.xlf:flushGeneralCachesDescription', TRUE),
+                               'href' => 'tce_db.php?vC=' . $backendUser->veriCode() . '&cacheCmd=all&ajaxCall=1' . BackendUtility::getUrlToken('tceAction'),
                                'icon' => IconUtility::getSpriteIcon('actions-system-cache-clear-impact-medium')
                        );
                        $this->optionValues[] = 'all';
@@ -91,18 +80,19 @@ class ClearCacheToolbarItem implements ToolbarItemInterface {
                        || ((bool)$GLOBALS['TYPO3_CONF_VARS']['SYS']['clearCacheSystem'] === TRUE && $backendUser->isAdmin())) {
                        $this->cacheActions[] = array(
                                'id' => 'system',
-                               'title' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:flushSystemCachesTitle', TRUE),
-                               'description' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:flushSystemCachesDescription', TRUE),
-                               'href' => $this->backPath . 'tce_db.php?vC=' . $backendUser->veriCode() . '&cacheCmd=system&ajaxCall=1' . BackendUtility::getUrlToken('tceAction'),
+                               'title' => $languageService->sL('LLL:EXT:lang/locallang_core.xlf:flushSystemCachesTitle', TRUE),
+                               'description' => $languageService->sL('LLL:EXT:lang/locallang_core.xlf:flushSystemCachesDescription', TRUE),
+                               'href' => 'tce_db.php?vC=' . $backendUser->veriCode() . '&cacheCmd=system&ajaxCall=1' . BackendUtility::getUrlToken('tceAction'),
                                'icon' => IconUtility::getSpriteIcon('actions-system-cache-clear-impact-high')
                        );
                        $this->optionValues[] = 'system';
                }
+
                // Hook for manipulating cacheActions
                if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['additionalBackendItems']['cacheActions'])) {
                        foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['additionalBackendItems']['cacheActions'] as $cacheAction) {
                                $hookObject = GeneralUtility::getUserObj($cacheAction);
-                               if (!$hookObject instanceof \TYPO3\CMS\Backend\Toolbar\ClearCacheActionsHookInterface) {
+                               if (!$hookObject instanceof ClearCacheActionsHookInterface) {
                                        throw new \UnexpectedValueException('$hookObject must implement interface TYPO3\\CMS\\Backend\\Toolbar\\ClearCacheActionsHookInterface', 1228262000);
                                }
                                $hookObject->manipulateCacheActions($this->cacheActions, $this->optionValues);
@@ -131,89 +121,89 @@ class ClearCacheToolbarItem implements ToolbarItemInterface {
        }
 
        /**
-        * Creates the selector for workspaces
+        * Render clear cache icon
         *
-        * @return string Workspace selector as HTML select
+        * @return string Icon HTML
         */
-       public function render() {
-               $title = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:rm.clearCache_clearCache', TRUE);
-               $this->addJavascriptToBackend();
-               $cacheMenu = array();
-               $cacheMenu[] = '<a href="#" class="dropdown-toggle" data-toggle="dropdown">' . IconUtility::getSpriteIcon('apps-toolbar-menu-cache', array('title' => $title)) . '</a>';
-               $cacheMenu[] = '<ul class="dropdown-menu" role="menu">';
-               foreach ($this->cacheActions as $cacheAction) {
-                       $cacheMenu[] = '<li><a href="' . htmlspecialchars($cacheAction['href'])
-                               . '" title="' . htmlspecialchars($cacheAction['description'] ?: $cacheAction['title']) . '">'
-                               . $cacheAction['icon'] . ' ' . htmlspecialchars($cacheAction['title']) . '</a></li>';
-               }
-               $cacheMenu[] = '</ul>';
-               return implode(LF, $cacheMenu);
+       public function getItem() {
+               $title = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:rm.clearCache_clearCache', TRUE);
+               return IconUtility::getSpriteIcon('apps-toolbar-menu-cache', array('title' => $title));
        }
 
        /**
-        * Adds the necessary JavaScript to the backend
+        * Render drop down
         *
-        * @return void
+        * @return string Drop down HTML
         */
-       protected function addJavascriptToBackend() {
-               $this->backendReference->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Toolbar/ClearCacheMenu');
+       public function getDropDown() {
+               $result = array();
+               $result[] = '<ul>';
+               foreach ($this->cacheActions as $cacheAction) {
+                       $title = $cacheAction['description'] ?: $cacheAction['title'];
+                       $result[] = '<li>';
+                       $result[] = '<a href="' . htmlspecialchars($cacheAction['href']) . '" title="' . htmlspecialchars($title) . '">';
+                       $result[] = $cacheAction['icon'] . ' ' . htmlspecialchars($cacheAction['title']);
+                       $result[] = '</a>';
+                       $result[] = '</li>';
+               }
+               $result[] = '</ul>';
+               return implode(LF, $result);
        }
 
        /**
-        * Returns additional attributes for the list item in the toolbar
-        *
-        * This should not contain the "class" or "id" attribute.
-        * Use the methods for setting these attributes
+        * No additional attributes needed.
         *
-        * @return string List item HTML attibutes
+        * @return array
         */
        public function getAdditionalAttributes() {
-               return '';
+               return array();
        }
 
        /**
-        * Return attribute id name
+        * This item has a drop down
         *
-        * @return string The name of the ID attribute
+        * @return bool
         */
-       public function getIdAttribute() {
-               return 'clear-cache-actions-menu';
+       public function hasDropDown() {
+               return TRUE;
        }
 
        /**
-        * Returns extra classes
+        * Position relative to others
         *
-        * @return array
+        * @return int
         */
-       public function getExtraClasses() {
-               return array();
+       public function getIndex() {
+               return 25;
        }
 
        /**
-        * This item has a drop down
+        * Returns the current BE user.
         *
-        * @return bool
+        * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
         */
-       public function hasDropDown() {
-               return TRUE;
+       protected function getBackendUser() {
+               return $GLOBALS['BE_USER'];
        }
 
        /**
-        * Returns the current BE user.
+        * Returns current PageRenderer
         *
-        * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
+        * @return \TYPO3\CMS\Core\Page\PageRenderer
         */
-       protected function getBackendUser() {
-               return $GLOBALS['BE_USER'];
+       protected function getPageRenderer() {
+               /** @var  \TYPO3\CMS\Backend\Template\DocumentTemplate $documentTemplate */
+               $documentTemplate = $GLOBALS['TBE_TEMPLATE'];
+               return $documentTemplate->getPageRenderer();
        }
 
        /**
-        * Position relative to others
+        * Returns LanguageService
         *
-        * @return int
+        * @return \TYPO3\CMS\Lang\LanguageService
         */
-       public function getIndex() {
-               return 25;
+       protected function getLanguageService() {
+               return $GLOBALS['LANG'];
        }
 
 }
index 3f61b6a..0ff60fa 100644 (file)
@@ -16,94 +16,86 @@ namespace TYPO3\CMS\Backend\Backend\ToolbarItems;
 
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
+use TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository;
+use TYPO3\CMS\Backend\Domain\Model\Module\BackendModule;
 
 /**
- * Help toobar item
+ * Help toolbar item
  */
 class HelpToolbarItem implements ToolbarItemInterface {
 
        /**
+        * @var \SplObjectStorage<BackendModule>
+        */
+       protected $helpModuleMenu = NULL;
+
+       /**
         * Constructor
-        *
-        * @param \TYPO3\CMS\Backend\Controller\BackendController $backendReference TYPO3 backend object reference
-        * @throws \UnexpectedValueException
         */
-       public function __construct(\TYPO3\CMS\Backend\Controller\BackendController &$backendReference = NULL) {
+       public function __construct() {
+               /** @var BackendModuleRepository $backendModuleRepository */
+               $backendModuleRepository = GeneralUtility::makeInstance(BackendModuleRepository::class);
+               /** @var \TYPO3\CMS\Backend\Domain\Model\Module\BackendModule $userModuleMenu */
+               $helpModuleMenu = $backendModuleRepository->findByModuleName('help');
+               if ($helpModuleMenu && $helpModuleMenu->getChildren()->count() > 0) {
+                       $this->helpModuleMenu = $helpModuleMenu;
+               }
        }
 
        /**
-        * Checks whether the user has access to this toolbar item
+        * Users see this if a module is available
         *
-        * @return bool TRUE if user has access, FALSE if not
+        * @return bool TRUE
         */
        public function checkAccess() {
-               return TRUE;
+               $result = $this->helpModuleMenu ? TRUE : FALSE;
+               return $result;
        }
 
        /**
-        * Creates the selector for workspaces
+        * Render help icon
         *
         * @return string Help
         */
-       public function render() {
-               /** @var \TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository $backendModuleRepository */
-               $backendModuleRepository = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository::class);
-               /** @var \TYPO3\CMS\Backend\Domain\Model\Module\BackendModule $userModuleMenu */
-               $helpModuleMenu = $backendModuleRepository->findByModuleName('help');
-
-               if ($helpModuleMenu === FALSE || $helpModuleMenu->getChildren()->count() < 1) {
-                       return '';
-               }
+       public function getItem() {
+               return '<span class="fa fa-fw fa-question-circle"></span>';
+       }
 
+       /**
+        * Render drop down
+        *
+        * @return string
+        */
+       public function getDropDown() {
                $dropdown = array();
-
-               $dropdown[] = '<a href="#" class="dropdown-toggle" data-toggle="dropdown">';
-               $dropdown[] = '<span class="fa fa-fw fa-question-circle"></span>';
-               $dropdown[] = '</a>';
-
-               $dropdown[] = '<ul class="dropdown-menu">';
-               foreach ($helpModuleMenu->getChildren() as $module) {
+               $dropdown[] = '<ul>';
+               foreach ($this->helpModuleMenu->getChildren() as $module) {
+                       /** @var BackendModule $module */
                        $moduleIcon = $module->getIcon();
-                       $dropdown[] = '
-                               <li id="' . $module->getName() . '" class="t3-menuitem-submodule submodule mod-' . $module->getName() . '" data-modulename="' . $module->getName() . '" data-navigationcomponentid="' . $module->getNavigationComponentId() . '" data-navigationframescript="' . $module->getNavigationFrameScript() . '" data-navigationframescriptparameters="' . $module->getNavigationFrameScriptParameters() . '">
-                                       <a title="' .$module->getDescription() . '" href="' . $module->getLink() . '" class="modlink">
-                                               <span class="submodule-icon">' . ($moduleIcon['html'] ?: $moduleIcon['html']) . '</span>
-                                               <span class="submodule-label">' . $module->getTitle() . '</span>
-                                       </a>
-                               </li>';
+                       $dropdown[] ='<li'
+                               . ' id="' . $module->getName() . '"'
+                               . ' class="t3-menuitem-submodule submodule mod-' . $module->getName() . '" '
+                               . ' data-modulename="' . $module->getName() . '"'
+                               . ' data-navigationcomponentid="' . $module->getNavigationComponentId() . '"'
+                               . ' data-navigationframescript="' . $module->getNavigationFrameScript() . '"'
+                               . ' data-navigationframescriptparameters="' . $module->getNavigationFrameScriptParameters() . '"'
+                               . '>';
+                       $dropdown[] = '<a title="' .$module->getDescription() . '" href="' . $module->getLink() . '" class="modlink">';
+                       $dropdown[] = '<span class="submodule-icon">' . ($moduleIcon['html'] ?: $moduleIcon['html']) . '</span>';
+                       $dropdown[] = '<span class="submodule-label">' . $module->getTitle() . '</span>';
+                       $dropdown[] = '</a>';
+                       $dropdown[] = '</li>';
                }
                $dropdown[] = '</ul>';
-
                return implode(LF, $dropdown);
        }
 
        /**
-        * Returns additional attributes for the list item in the toolbar
-        *
-        * This should not contain the "class" or "id" attribute.
-        * Use the methods for setting these attributes
-        *
-        * @return string List item HTML attibutes
-        */
-       public function getAdditionalAttributes() {
-               return '';
-       }
-
-       /**
-        * Return attribute id name
-        *
-        * @return string The name of the ID attribute
-        */
-       public function getIdAttribute() {
-               return 'topbar-help-menu';
-       }
-
-       /**
-        * Returns extra classes
+        * No additional attributes needed.
         *
         * @return array
         */
-       public function getExtraClasses() {
+       public function getAdditionalAttributes() {
                return array();
        }
 
index 3f64333..8992a03 100644 (file)
@@ -15,6 +15,8 @@ namespace TYPO3\CMS\Backend\Backend\ToolbarItems;
  */
 
 use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
+use TYPO3\CMS\Backend\Module\ModuleLoader;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
  * Adds backend live search to the toolbar
@@ -25,17 +27,10 @@ use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
 class LiveSearchToolbarItem implements ToolbarItemInterface {
 
        /**
-        * @var \TYPO3\CMS\Backend\Controller\BackendController
-        */
-       protected $backendReference;
-
-       /**
         * Constructor
-        *
-        * @param \TYPO3\CMS\Backend\Controller\BackendController $backendReference TYPO3 backend object reference
         */
-       public function __construct(\TYPO3\CMS\Backend\Controller\BackendController &$backendReference = NULL) {
-               $this->backendReference = $backendReference;
+       public function __construct() {
+               $this->getPageRenderer()->addJsFile('sysext/backend/Resources/Public/JavaScript/livesearch.js');
        }
 
        /**
@@ -46,7 +41,7 @@ class LiveSearchToolbarItem implements ToolbarItemInterface {
        public function checkAccess() {
                $access = FALSE;
                // Loads the backend modules available for the logged in user.
-               $loadModules = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Module\ModuleLoader::class);
+               $loadModules = GeneralUtility::makeInstance(ModuleLoader::class);
                $loadModules->observeWorkspaces = TRUE;
                $loadModules->load($GLOBALS['TBE_MODULES']);
                // Live search is heavily dependent on the list module and only available when that module is.
@@ -57,13 +52,11 @@ class LiveSearchToolbarItem implements ToolbarItemInterface {
        }
 
        /**
-        * Creates the selector for workspaces
+        * Render search field
         *
-        * @return string Workspace selector as HTML select
+        * @return string Live search form HTML
         */
-       public function render() {
-               $this->backendReference->addJavascriptFile('sysext/backend/Resources/Public/JavaScript/livesearch.js');
-
+       public function getItem() {
                return '
                        <form class="navbar-form" role="search">
                                <div class="live-search-wrapper">
@@ -76,51 +69,50 @@ class LiveSearchToolbarItem implements ToolbarItemInterface {
        }
 
        /**
-        * Returns additional attributes for the list item in the toolbar
-        *
-        * This should not contain the "class" or "id" attribute.
-        * Use the methods for setting these attributes
+        * This item needs to additional attributes
         *
-        * @return string List item HTML attibutes
+        * @return array
         */
        public function getAdditionalAttributes() {
-               return '';
+               return array();
        }
 
        /**
-        * Return attribute id name
+        * This item has no drop down
         *
-        * @return string The name of the ID attribute
+        * @return bool
         */
-       public function getIdAttribute() {
-               return 'livesearch-menu';
+       public function hasDropDown() {
+               return FALSE;
        }
 
        /**
-        * Returns extra classes
+        * No drop down here
         *
-        * @return array
+        * @return string
         */
-       public function getExtraClasses() {
-               return array();
+       public function getDropDown() {
+               return '';
        }
 
        /**
-        * This item has no drop down
+        * Position relative to others, live search should be very right
         *
-        * @return bool
+        * @return int
         */
-       public function hasDropDown() {
-               return FALSE;
+       public function getIndex() {
+               return 90;
        }
 
        /**
-        * Position relative to others, live search should be very right
+        * Returns current PageRenderer
         *
-        * @return int
+        * @return \TYPO3\CMS\Core\Page\PageRenderer
         */
-       public function getIndex() {
-               return 90;
+       protected function getPageRenderer() {
+               /** @var  \TYPO3\CMS\Backend\Template\DocumentTemplate $documentTemplate */
+               $documentTemplate = $GLOBALS['TBE_TEMPLATE'];
+               return $documentTemplate->getPageRenderer();
        }
 
 }
index cba7542..93ceab6 100644 (file)
@@ -19,6 +19,7 @@ use TYPO3\CMS\Backend\Utility\IconUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
 use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
+use TYPO3\CMS\Backend\Module\ModuleLoader;
 
 /**
  * Class to render the shortcut menu
@@ -27,17 +28,15 @@ use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
  */
 class ShortcutToolbarItem implements ToolbarItemInterface {
 
-       const SUPERGLOBAL_GROUP = -100;
-
        /**
-        * @var string
+        * @const integer Number of super global group
         */
-       public $perms_clause;
+       const SUPERGLOBAL_GROUP = -100;
 
        /**
         * @var string
         */
-       public $backPath;
+       public $perms_clause;
 
        /**
         * @var array
@@ -65,26 +64,16 @@ class ShortcutToolbarItem implements ToolbarItemInterface {
        protected $groupLabels;
 
        /**
-        * Reference back to the backend object
-        *
-        * @var \TYPO3\CMS\Backend\Controller\BackendController
-        */
-       protected $backendReference;
-
-       /**
         * Constructor
-        *
-        * @param \TYPO3\CMS\Backend\Controller\BackendController $backendReference TYPO3 backend object reference
         */
-       public function __construct(\TYPO3\CMS\Backend\Controller\BackendController &$backendReference = NULL) {
+       public function __construct() {
                if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX) {
-                       $GLOBALS['LANG']->includeLLFile('EXT:lang/locallang_misc.xlf');
+                       $this->getLanguageService()->includeLLFile('EXT:lang/locallang_misc.xlf');
                        // Needed to get the correct icons when reloading the menu after saving it
-                       $loadModules = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Module\ModuleLoader::class);
+                       $loadModules = GeneralUtility::makeInstance(ModuleLoader::class);
                        $loadModules->load($GLOBALS['TBE_MODULES']);
                }
-               $this->backendReference = $backendReference;
-               $this->shortcuts = array();
+
                // By default, 5 groups are set
                $this->shortcutGroups = array(
                        1 => '1',
@@ -95,6 +84,8 @@ class ShortcutToolbarItem implements ToolbarItemInterface {
                );
                $this->shortcutGroups = $this->initShortcutGroups();
                $this->shortcuts = $this->initShortcuts();
+
+               $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Toolbar/ShortcutMenu');
        }
 
        /**
@@ -103,38 +94,37 @@ class ShortcutToolbarItem implements ToolbarItemInterface {
         * @return bool TRUE if user has access, FALSE if not
         */
        public function checkAccess() {
-               return (bool)$GLOBALS['BE_USER']->getTSConfigVal('options.enableBookmarks');
+               return (bool)$this->getBackendUser()->getTSConfigVal('options.enableBookmarks');
        }
 
        /**
-        * Creates the shortcut menu (default renderer)
+        * Render shortcut icon
         *
-        * @return string Workspace selector as HTML select
-        */
-       public function render() {
-               $title = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.bookmarks', TRUE);
-               $this->backendReference->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Toolbar/ShortcutMenu');
-               $shortcutMenu = array();
-               $shortcutMenu[] = '<a href="#" class="dropdown-toggle" data-toggle="dropdown">' . IconUtility::getSpriteIcon('apps-toolbar-menu-shortcut', array('title' => $title)) . '</a>';
-               $shortcutMenu[] = '<div class="dropdown-menu" role="menu">';
-               $shortcutMenu[] = $this->renderMenu();
-               $shortcutMenu[] = '</div>';
-               return implode(LF, $shortcutMenu);
+        * @return string HTML
+        */
+       public function getItem() {
+               return IconUtility::getSpriteIcon(
+                       'apps-toolbar-menu-shortcut',
+                       array(
+                               'title' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.bookmarks', TRUE),
+                       )
+               );
        }
 
        /**
-        * Renders the pure contents of the menu
+        * Render drop down content
         *
-        * @return string The menu's content
-        */
-       public function renderMenu() {
-               $shortcutGroup = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.bookmarksGroup', TRUE);
-               $shortcutEdit = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.bookmarksEdit', TRUE);
-               $shortcutDelete = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.bookmarksDelete', TRUE);
-               $groupIcon = '<img' . IconUtility::skinImg($this->backPath, 'gfx/i/sysf.gif', 'width="18" height="16"') . ' title="' . $shortcutGroup . '" alt="' . $shortcutGroup . '" />';
-               $editIcon = '<img' . IconUtility::skinImg($this->backPath, 'gfx/edit2.gif', 'width="11" height="12"') . ' title="' . $shortcutEdit . '" alt="' . $shortcutEdit . '"';
-               $deleteIcon = '<img' . IconUtility::skinImg($this->backPath, 'gfx/garbage.gif', 'width="11" height="12"') . ' title="' . $shortcutDelete . '" alt="' . $shortcutDelete . '" />';
-               $shortcutMenu[] = '<table border="0" cellspacing="0" cellpadding="0" class="shortcut-list">';
+        * @return string HTML
+        */
+       public function getDropDown() {
+               $languageService = $this->getLanguageService();
+               $shortcutGroup = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.bookmarksGroup', TRUE);
+               $shortcutEdit = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.bookmarksEdit', TRUE);
+               $shortcutDelete = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.bookmarksDelete', TRUE);
+               $groupIcon = '<img' . IconUtility::skinImg('', 'gfx/i/sysf.gif', 'width="18" height="16"') . ' title="' . $shortcutGroup . '" alt="' . $shortcutGroup . '" />';
+               $editIcon = '<img' . IconUtility::skinImg('', 'gfx/edit2.gif', 'width="11" height="12"') . ' title="' . $shortcutEdit . '" alt="' . $shortcutEdit . '"';
+               $deleteIcon = '<img' . IconUtility::skinImg('', 'gfx/garbage.gif', 'width="11" height="12"') . ' title="' . $shortcutDelete . '" alt="' . $shortcutDelete . '" />';
+               $shortcutMenu[] = '<table border="0" class="shortcut-list">';
                // Render shortcuts with no group (group id = 0) first
                $noGroupShortcuts = $this->getShortcutsByGroup(0);
                foreach ($noGroupShortcuts as $shortcut) {
@@ -182,11 +172,11 @@ class ShortcutToolbarItem implements ToolbarItemInterface {
                }
                if (count($shortcutMenu) == 1) {
                        // No shortcuts added yet, show a small help message how to add shortcuts
-                       $title = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.bookmarks', TRUE);
+                       $title = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.bookmarks', TRUE);
                        $icon = IconUtility::getSpriteIcon('actions-system-shortcut-new', array(
                                'title' => $title
                        ));
-                       $label = str_replace('%icon%', $icon, $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xlf:bookmarkDescription'));
+                       $label = str_replace('%icon%', $icon, $languageService->sL('LLL:EXT:lang/locallang_misc.xlf:bookmarkDescription'));
                        $shortcutMenu[] = '<tr><td style="padding:1px 2px; color: #838383;">' . $label . '</td></tr>';
                }
                $shortcutMenu[] = '</table>';
@@ -201,38 +191,17 @@ class ShortcutToolbarItem implements ToolbarItemInterface {
         * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj Object of type AjaxRequestHandler
         * @return void
         */
-       public function renderAjaxMenu($params = array(), \TYPO3\CMS\Core\Http\AjaxRequestHandler &$ajaxObj = NULL) {
-               $menuContent = $this->renderMenu();
+       public function renderAjaxMenu($params = array(), \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj = NULL) {
+               $menuContent = $this->getDropDown();
                $ajaxObj->addContent('shortcutMenu', $menuContent);
        }
 
        /**
-        * Returns additional attributes for the list item in the toolbar
-        *
-        * This should not contain the "class" or "id" attribute.
-        * Use the methods for setting these attributes
-        *
-        * @return string List item HTML attibutes
-        */
-       public function getAdditionalAttributes() {
-               return '';
-       }
-
-       /**
-        * Return attribute id name
-        *
-        * @return string The name of the ID attribute
-        */
-       public function getIdAttribute() {
-               return 'shortcut-menu';
-       }
-
-       /**
-        * Returns extra classes
+        * This toolbar item needs no additional attributes
         *
         * @return array
         */
-       public function getExtraClasses() {
+       public function getAdditionalAttributes() {
                return array();
        }
 
@@ -251,18 +220,20 @@ class ShortcutToolbarItem implements ToolbarItemInterface {
         * @return array Array of shortcuts
         */
        protected function initShortcuts() {
+               $databaseConnection = $this->getDatabaseConnection();
                $globalGroupIdList = implode(',', array_keys($this->getGlobalShortcutGroups()));
-               $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
+               $backendUser = $this->getBackendUser();
+               $res = $databaseConnection->exec_SELECTquery(
                        '*',
                        'sys_be_shortcuts',
-                       '(userid = ' . (int)$GLOBALS['BE_USER']->user['uid'] . ' AND sc_group>=0) OR sc_group IN (' . $globalGroupIdList . ')',
+                       '(userid = ' . (int)$backendUser->user['uid'] . ' AND sc_group>=0) OR sc_group IN (' . $globalGroupIdList . ')',
                        '',
                        'sc_group,sorting'
                );
                // Traverse shortcuts
                $lastGroup = 0;
                $shortcuts = array();
-               while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
+               while ($row = $databaseConnection->sql_fetch_assoc($res)) {
                        $shortcut = array('raw' => $row);
 
                        list($row['module_name'], $row['M_module_name']) = explode('|', $row['module_name']);
@@ -286,20 +257,20 @@ class ShortcutToolbarItem implements ToolbarItemInterface {
                        // Check for module access
                        $moduleName = $row['M_module_name'] ?: $row['module_name'];
                        $pageId = $this->getLinkedPageId($row['url']);
-                       if (!$GLOBALS['BE_USER']->isAdmin()) {
-                               if (!isset($GLOBALS['LANG']->moduleLabels['tabs_images'][$moduleName . '_tab'])) {
+                       if (!$backendUser->isAdmin()) {
+                               if (!isset($this->getLanguageService()->moduleLabels['tabs_images'][$moduleName . '_tab'])) {
                                        // Nice hack to check if the user has access to this module
                                        // - otherwise the translation label would not have been loaded :-)
                                        continue;
                                }
                                if (MathUtility::canBeInterpretedAsInteger($pageId)) {
                                        // Check for webmount access
-                                       if (!$GLOBALS['BE_USER']->isInWebMount($pageId)) {
+                                       if (!$backendUser->isInWebMount($pageId)) {
                                                continue;
                                        }
                                        // Check for record access
                                        $pageRow = BackendUtility::getRecord('pages', $pageId);
-                                       if (!$GLOBALS['BE_USER']->doesUserHaveAccess($pageRow, ($perms = 1))) {
+                                       if (!$backendUser->doesUserHaveAccess($pageRow, ($perms = 1))) {
                                                continue;
                                        }
                                }
@@ -394,13 +365,15 @@ class ShortcutToolbarItem implements ToolbarItemInterface {
         * @return array
         */
        protected function initShortcutGroups() {
+               $languageService = $this->getLanguageService();
+               $backendUser = $this->getBackendUser();
                // Groups from TSConfig
-               $bookmarkGroups = $GLOBALS['BE_USER']->getTSConfigProp('options.bookmarkGroups');
+               $bookmarkGroups = $backendUser->getTSConfigProp('options.bookmarkGroups');
                if (is_array($bookmarkGroups) && count($bookmarkGroups)) {
                        foreach ($bookmarkGroups as $groupId => $label) {
                                if (!empty($label)) {
                                        $this->shortcutGroups[$groupId] = (string)$label;
-                               } elseif ($GLOBALS['BE_USER']->isAdmin()) {
+                               } elseif ($backendUser->isAdmin()) {
                                        unset($this->shortcutGroups[$groupId]);
                                }
                        }
@@ -419,17 +392,17 @@ class ShortcutToolbarItem implements ToolbarItemInterface {
                        $groupId = (int)$groupId;
                        $label = $groupLabel;
                        if ($groupLabel == '1') {
-                               $label = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xlf:bookmark_group_' . abs($groupId), TRUE);
+                               $label = $languageService->sL('LLL:EXT:lang/locallang_misc.xlf:bookmark_group_' . abs($groupId), TRUE);
                                if (empty($label)) {
                                        // Fallback label
-                                       $label = $GLOBALS['LANG']->getLL('bookmark_group', 1) . ' ' . abs($groupId);
+                                       $label = $languageService->getLL('bookmark_group', 1) . ' ' . abs($groupId);
                                }
                        }
                        if ($groupId < 0) {
                                // Global group
-                               $label = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xlf:bookmark_global', TRUE) . ': ' . (!empty($label) ? $label : abs($groupId));
+                               $label = $languageService->sL('LLL:EXT:lang/locallang_misc.xlf:bookmark_global', TRUE) . ': ' . (!empty($label) ? $label : abs($groupId));
                                if ($groupId === self::SUPERGLOBAL_GROUP) {
-                                       $label = $GLOBALS['LANG']->getLL('bookmark_global', 1) . ': ' . $GLOBALS['LANG']->getLL('bookmark_all', 1);
+                                       $label = $languageService->getLL('bookmark_global', 1) . ': ' . $languageService->getLL('bookmark_all', 1);
                                }
                        }
                        $this->shortcutGroups[$groupId] = $label;
@@ -444,13 +417,13 @@ class ShortcutToolbarItem implements ToolbarItemInterface {
         * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj Object of type AjaxRequestHandler
         * @return void
         */
-       public function getAjaxShortcutEditForm($params = array(), \TYPO3\CMS\Core\Http\AjaxRequestHandler &$ajaxObj = NULL) {
+       public function getAjaxShortcutEditForm($params = array(), \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj = NULL) {
                $selectedShortcutId = (int)GeneralUtility::_GP('shortcutId');
                $selectedShortcutGroupId = (int)GeneralUtility::_GP('shortcutGroup');
                $selectedShortcut = $this->getShortcutById($selectedShortcutId);
 
                $shortcutGroups = $this->shortcutGroups;
-               if (!$GLOBALS['BE_USER']->isAdmin()) {
+               if (!$this->getBackendUser()->isAdmin()) {
                        foreach ($shortcutGroups as $groupId => $groupName) {
                                if ((int)$groupId < 0) {
                                        unset($shortcutGroups[$groupId]);
@@ -478,13 +451,14 @@ class ShortcutToolbarItem implements ToolbarItemInterface {
         * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj Object of type AjaxRequestHandler
         * @return void
         */
-       public function deleteAjaxShortcut($params = array(), \TYPO3\CMS\Core\Http\AjaxRequestHandler &$ajaxObj = NULL) {
+       public function deleteAjaxShortcut($params = array(), \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj = NULL) {
+               $databaseConnection = $this->getDatabaseConnection();
                $shortcutId = (int)GeneralUtility::_POST('shortcutId');
                $fullShortcut = $this->getShortcutById($shortcutId);
                $ajaxReturn = 'failed';
-               if ($fullShortcut['raw']['userid'] == $GLOBALS['BE_USER']->user['uid']) {
-                       $GLOBALS['TYPO3_DB']->exec_DELETEquery('sys_be_shortcuts', 'uid = ' . $shortcutId);
-                       if ($GLOBALS['TYPO3_DB']->sql_affected_rows() == 1) {
+               if ($fullShortcut['raw']['userid'] == $this->getBackendUser()->user['uid']) {
+                       $databaseConnection->exec_DELETEquery('sys_be_shortcuts', 'uid = ' . $shortcutId);
+                       if ($databaseConnection->sql_affected_rows() == 1) {
                                $ajaxReturn = 'deleted';
                        }
                }
@@ -498,7 +472,9 @@ class ShortcutToolbarItem implements ToolbarItemInterface {
         * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj Oject of type AjaxRequestHandler
         * @return void
         */
-       public function createAjaxShortcut($params = array(), \TYPO3\CMS\Core\Http\AjaxRequestHandler &$ajaxObj = NULL) {
+       public function createAjaxShortcut($params = array(), \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj = NULL) {
+               $databaseConnection = $this->getDatabaseConnection();
+               $languageService = $this->getLanguageService();
                $shortcutCreated = 'failed';
                // Default name
                $shortcutName = 'Shortcut';
@@ -517,10 +493,10 @@ class ShortcutToolbarItem implements ToolbarItemInterface {
                                $shortcut['recordid'] = key($queryParameters['edit'][$shortcut['table']]);
                                if ($queryParameters['edit'][$shortcut['table']][$shortcut['recordid']] == 'edit') {
                                        $shortcut['type'] = 'edit';
-                                       $shortcutNamePrepend = $GLOBALS['LANG']->getLL('shortcut_edit', 1);
+                                       $shortcutNamePrepend = $languageService->getLL('shortcut_edit', 1);
                                } elseif ($queryParameters['edit'][$shortcut['table']][$shortcut['recordid']] == 'new') {
                                        $shortcut['type'] = 'new';
-                                       $shortcutNamePrepend = $GLOBALS['LANG']->getLL('shortcut_create', 1);
+                                       $shortcutNamePrepend = $languageService->getLL('shortcut_create', 1);
                                }
                        } else {
                                $shortcut['type'] = 'other';
@@ -534,7 +510,7 @@ class ShortcutToolbarItem implements ToolbarItemInterface {
                                        if ($shortcut['type'] == 'other') {
                                                $shortcutName = $page['title'];
                                        } else {
-                                               $shortcutName = $shortcutNamePrepend . ' ' . $GLOBALS['LANG']->sL($GLOBALS['TCA'][$shortcut['table']]['ctrl']['title']) . ' (' . $page['title'] . ')';
+                                               $shortcutName = $shortcutNamePrepend . ' ' . $languageService->sL($GLOBALS['TCA'][$shortcut['table']]['ctrl']['title']) . ' (' . $page['title'] . ')';
                                        }
                                }
                        } else {
@@ -549,14 +525,14 @@ class ShortcutToolbarItem implements ToolbarItemInterface {
                        // adding the shortcut
                        if ($module && $url) {
                                $fieldValues = array(
-                                       'userid' => $GLOBALS['BE_USER']->user['uid'],
+                                       'userid' => $this->getBackendUser()->user['uid'],
                                        'module_name' => $module . '|' . $motherModule,
                                        'url' => $url,
                                        'description' => $shortcutName,
                                        'sorting' => $GLOBALS['EXEC_TIME']
                                );
-                               $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_be_shortcuts', $fieldValues);
-                               if ($GLOBALS['TYPO3_DB']->sql_affected_rows() == 1) {
+                               $databaseConnection->exec_INSERTquery('sys_be_shortcuts', $fieldValues);
+                               if ($databaseConnection->sql_affected_rows() == 1) {
                                        $shortcutCreated = 'success';
                                }
                        }
@@ -572,22 +548,24 @@ class ShortcutToolbarItem implements ToolbarItemInterface {
         * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj Object of type AjaxRequestHandler
         * @return void
         */
-       public function setAjaxShortcut($params = array(), \TYPO3\CMS\Core\Http\AjaxRequestHandler &$ajaxObj = NULL) {
+       public function setAjaxShortcut($params = array(), \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj = NULL) {
+               $databaseConnection = $this->getDatabaseConnection();
+               $backendUser = $this->getBackendUser();
                $shortcutId = (int)GeneralUtility::_POST('shortcutId');
                $shortcutName = strip_tags(GeneralUtility::_POST('shortcutTitle'));
                $shortcutGroupId = (int)GeneralUtility::_POST('shortcutGroup');
-               if ($shortcutGroupId > 0 || $GLOBALS['BE_USER']->isAdmin()) {
+               if ($shortcutGroupId > 0 || $backendUser->isAdmin()) {
                        // Users can delete only their own shortcuts (except admins)
-                       $addUserWhere = !$GLOBALS['BE_USER']->isAdmin() ? ' AND userid=' . (int)$GLOBALS['BE_USER']->user['uid'] : '';
+                       $addUserWhere = !$backendUser->isAdmin() ? ' AND userid=' . (int)$backendUser->user['uid'] : '';
                        $fieldValues = array(
                                'description' => $shortcutName,
                                'sc_group' => $shortcutGroupId
                        );
-                       if ($fieldValues['sc_group'] < 0 && !$GLOBALS['BE_USER']->isAdmin()) {
+                       if ($fieldValues['sc_group'] < 0 && !$backendUser->isAdmin()) {
                                $fieldValues['sc_group'] = 0;
                        }
-                       $GLOBALS['TYPO3_DB']->exec_UPDATEquery('sys_be_shortcuts', 'uid=' . $shortcutId . $addUserWhere, $fieldValues);
-                       $affectedRows = $GLOBALS['TYPO3_DB']->sql_affected_rows();
+                       $databaseConnection->exec_UPDATEquery('sys_be_shortcuts', 'uid=' . $shortcutId . $addUserWhere, $fieldValues);
+                       $affectedRows = $databaseConnection->sql_affected_rows();
                        if ($affectedRows == 1) {
                                $ajaxObj->addContent('shortcut', $shortcutName);
                        } else {
@@ -643,6 +621,8 @@ class ShortcutToolbarItem implements ToolbarItemInterface {
         * @return string Shortcut icon as img tag
         */
        protected function getShortcutIcon($row, $shortcut) {
+               $databaseConnection = $this->getDatabaseConnection();
+               $languageService = $this->getLanguageService();
                switch ($row['module_name']) {
                        case 'xMOD_alt_doc.php':
                                $table = $shortcut['table'];
@@ -678,13 +658,13 @@ class ShortcutToolbarItem implements ToolbarItemInterface {
                                                'FROM' => $table,
                                                'WHERE' => 'uid IN (' . $recordid . ') ' . $permissionClause . BackendUtility::deleteClause($table) . BackendUtility::versioningPlaceholderClause($table)
                                        );
-                                       $result = $GLOBALS['TYPO3_DB']->exec_SELECT_queryArray($sqlQueryParts);
-                                       $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result);
-                                       $icon = IconUtility::getIcon($table, $row, $this->backPath);
+                                       $result = $databaseConnection->exec_SELECT_queryArray($sqlQueryParts);
+                                       $row = $databaseConnection->sql_fetch_assoc($result);
+                                       $icon = IconUtility::getIcon($table, $row);
                                } elseif ($shortcut['type'] == 'new') {
-                                       $icon = IconUtility::getIcon($table, array(), $this->backPath);
+                                       $icon = IconUtility::getIcon($table, array());
                                }
-                               $icon = IconUtility::skinImg($this->backPath, $icon, '', 1);
+                               $icon = IconUtility::skinImg('', $icon, '', 1);
                                break;
                        case 'file_edit':
                                $icon = 'gfx/edit_file.gif';
@@ -693,8 +673,8 @@ class ShortcutToolbarItem implements ToolbarItemInterface {
                                $icon = 'gfx/edit_rtewiz.gif';
                                break;
                        default:
-                               if ($GLOBALS['LANG']->moduleLabels['tabs_images'][$row['module_name'] . '_tab']) {
-                                       $icon = $GLOBALS['LANG']->moduleLabels['tabs_images'][$row['module_name'] . '_tab'];
+                               if ($languageService->moduleLabels['tabs_images'][$row['module_name'] . '_tab']) {
+                                       $icon = $languageService->moduleLabels['tabs_images'][$row['module_name'] . '_tab'];
                                        // Change icon of fileadmin references - otherwise it doesn't differ with Web->List
                                        $icon = str_replace('mod/file/list/list.gif', 'mod/file/file.gif', $icon);
                                        if (GeneralUtility::isAbsPath($icon)) {
@@ -704,7 +684,7 @@ class ShortcutToolbarItem implements ToolbarItemInterface {
                                        $icon = 'gfx/dummy_module.gif';
                                }
                }
-               return '<img src="' . $icon . '" alt="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.shortcut', TRUE) . '" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.shortcut', TRUE) . '" />';
+               return '<img src="' . $icon . '" alt="' . $languageService->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.shortcut', TRUE) . '" title="' . $languageService->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.shortcut', TRUE) . '" />';
        }
 
        /**
@@ -716,14 +696,14 @@ class ShortcutToolbarItem implements ToolbarItemInterface {
         * @return string Title for the shortcut icon
         */
        protected function getShortcutIconTitle($shortcutLabel, $moduleName, $parentModuleName = '') {
-               $title = '';
+               $languageService = $this->getLanguageService();
                if (substr($moduleName, 0, 5) == 'xMOD_') {
                        $title = substr($moduleName, 5);
                } else {
                        $splitModuleName = explode('_', $moduleName);
-                       $title = $GLOBALS['LANG']->moduleLabels['tabs'][$splitModuleName[0] . '_tab'];
+                       $title = $languageService->moduleLabels['tabs'][$splitModuleName[0] . '_tab'];
                        if (count($splitModuleName) > 1) {
-                               $title .= '>' . $GLOBALS['LANG']->moduleLabels['tabs'][($moduleName . '_tab')];
+                               $title .= '>' . $languageService->moduleLabels['tabs'][($moduleName . '_tab')];
                        }
                }
                if ($parentModuleName) {
@@ -752,4 +732,42 @@ class ShortcutToolbarItem implements ToolbarItemInterface {
                return 20;
        }
 
+       /**
+        * Returns the current BE user.
+        *
+        * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
+        */
+       protected function getBackendUser() {
+               return $GLOBALS['BE_USER'];
+       }
+
+       /**
+        * Returns current PageRenderer
+        *
+        * @return \TYPO3\CMS\Core\Page\PageRenderer
+        */
+       protected function getPageRenderer() {
+               /** @var  \TYPO3\CMS\Backend\Template\DocumentTemplate $documentTemplate */
+               $documentTemplate = $GLOBALS['TBE_TEMPLATE'];
+               return $documentTemplate->getPageRenderer();
+       }
+
+       /**
+        * Returns LanguageService
+        *
+        * @return \TYPO3\CMS\Lang\LanguageService
+        */
+       protected function getLanguageService() {
+               return $GLOBALS['LANG'];
+       }
+
+       /**
+        * Return DatabaseConnection
+        *
+        * @return \TYPO3\CMS\Core\Database\DatabaseConnection
+        */
+       protected function getDatabaseConnection() {
+               return $GLOBALS['TYPO3_DB'];
+       }
+
 }
index b62182d..baf091c 100644 (file)
@@ -16,132 +16,151 @@ namespace TYPO3\CMS\Backend\Backend\ToolbarItems;
 
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
+use TYPO3\CMS\Backend\Utility\IconUtility;
+use TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository;
+use TYPO3\CMS\Backend\Domain\Model\Module\BackendModule;
 
 /**
- * User toobar item
+ * User toolbar item
  */
 class UserToolbarItem implements ToolbarItemInterface {
 
        /**
-        * Constructor
+        * Item is always enabled
         *
-        * @param \TYPO3\CMS\Backend\Controller\BackendController $backendReference TYPO3 backend object reference
-        * @throws \UnexpectedValueException
-        */
-       public function __construct(\TYPO3\CMS\Backend\Controller\BackendController &$backendReference = NULL) {
-       }
-
-       /**
-        * Checks whether the user has access to this toolbar item
-        *
-        * @return bool TRUE if user has access, FALSE if not
+        * @return bool TRUE
         */
        public function checkAccess() {
                return TRUE;
        }
 
        /**
-        * Creates the selector for workspaces
+        * Render username
         *
-        * @return string Workspace selector as HTML select
+        * @return string HTML
         */
-       public function render() {
-               $icon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('status-user-' . ($GLOBALS['BE_USER']->isAdmin() ? 'admin' : 'backend'));
+       public function getItem() {
+               $backendUser = $this->getBackendUser();
+               $languageService = $this->getLanguageService();
+               $icon = IconUtility::getSpriteIcon('status-user-' . ($backendUser->isAdmin() ? 'admin' : 'backend'));
 
-               $realName = $GLOBALS['BE_USER']->user['realName'];
-               $username = $GLOBALS['BE_USER']->user['username'];
+               $realName = $backendUser->user['realName'];
+               $username = $backendUser->user['username'];
                $label = $realName ?: $username;
                $title = $username;
 
-               // Superuser mode
-               if ($GLOBALS['BE_USER']->user['ses_backuserid']) {
-                       $title = $GLOBALS['LANG']->getLL('switchtouser') . ': ' . $username;
-                       $label = $GLOBALS['LANG']->getLL('switchtousershort') . ' ' . ($realName ? $realName . ' (' . $username . ')' : $username);
+               // Switch user mode
+               if ($backendUser->user['ses_backuserid']) {
+                       $title = $languageService->getLL('switchtouser') . ': ' . $username;
+                       $label = $languageService->getLL('switchtousershort') . ' ' . ($realName ? $realName . ' (' . $username . ')' : $username);
                }
 
-
                $html = array();
-               $html[] = '<a href="#" class="dropdown-toggle" data-toggle="dropdown">';
-               $html[] = $icon . '<span title="' . htmlspecialchars($title) . '">' . htmlspecialchars($label) . ' <span class="caret"></span></span>';
-               $html[] = '</a>';
+               $html[] = $icon;
+               $html[] = '<span title="' . htmlspecialchars($title) . '">';
+               $html[] = htmlspecialchars($label);
+               $html[] = '<span class="caret"></span></span>';
 
-               $html[] = '<ul class="dropdown-menu" role="menu">';
+               return implode(LF, $html);
+       }
 
-               /** @var \TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository $backendModuleRepository */
-               $backendModuleRepository = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository::class);
+       /**
+        * Render drop down
+        *
+        * @return string HTML
+        */
+       public function getDropDown() {
+               $backendUser = $this->getBackendUser();
+               $languageService = $this->getLanguageService();
+
+               $dropdown = array();
+               $dropdown[] = '<ul>';
+
+               /** @var BackendModuleRepository $backendModuleRepository */
+               $backendModuleRepository = GeneralUtility::makeInstance(BackendModuleRepository::class);
                /** @var \TYPO3\CMS\Backend\Domain\Model\Module\BackendModule $userModuleMenu */
                $userModuleMenu = $backendModuleRepository->findByModuleName('user');
                if ($userModuleMenu != FALSE && $userModuleMenu->getChildren()->count() > 0) {
                        foreach ($userModuleMenu->getChildren() as $module) {
+                               /** @var BackendModule $module */
                                $moduleIcon = $module->getIcon();
-                               $html[] = '
-                                       <li id="' . $module->getName() . '" class="t3-menuitem-submodule submodule mod-' . $module->getName() . '" data-modulename="' . $module->getName() . '" data-navigationcomponentid="' . $module->getNavigationComponentId() . '" data-navigationframescript="' . $module->getNavigationFrameScript() . '" data-navigationframescriptparameters="' . $module->getNavigationFrameScriptParameters() . '">
-                                               <a title="' .$module->getDescription() . '" href="' . $module->getLink() . '" class="modlink">
-                                                       <span class="submodule-icon">' . ($moduleIcon['html'] ?: $moduleIcon['html']) . '</span>
-                                                       <span class="submodule-label">' . $module->getTitle() . '</span>
-                                               </a>
-                                       </li>';
+                               $dropdown[] ='<li'
+                                       . ' id="' . $module->getName() . '"'
+                                       . ' class="t3-menuitem-submodule submodule mod-' . $module->getName() . '" '
+                                       . ' data-modulename="' . $module->getName() . '"'
+                                       . ' data-navigationcomponentid="' . $module->getNavigationComponentId() . '"'
+                                       . ' data-navigationframescript="' . $module->getNavigationFrameScript() . '"'
+                                       . ' data-navigationframescriptparameters="' . $module->getNavigationFrameScriptParameters() . '"'
+                                       . '>';
+                               $dropdown[] = '<a title="' .$module->getDescription() . '" href="' . $module->getLink() . '" class="modlink">';
+                               $dropdown[] = '<span class="submodule-icon">' . ($moduleIcon['html'] ?: $moduleIcon['html']) . '</span>';
+                               $dropdown[] = '<span class="submodule-label">' . $module->getTitle() . '</span>';
+                               $dropdown[] = '</a>';
+                               $dropdown[] = '</li>';
                        }
-                       $html[] = '<li class="divider"></li>';
+                       $dropdown[] = '<li class="divider"></li>';
                }
 
-               // logout button
-               $buttonLabel = 'LLL:EXT:lang/locallang_core.xlf:' . ($GLOBALS['BE_USER']->user['ses_backuserid'] ? 'buttons.exit' : 'buttons.logout');
-               $html[] = '<li><a href="logout.php" target="_top">' . $GLOBALS['LANG']->sL($buttonLabel, TRUE) . '</a></li>';
+               // Logout button
+               $buttonLabel = 'LLL:EXT:lang/locallang_core.xlf:' . ($backendUser->user['ses_backuserid'] ? 'buttons.exit' : 'buttons.logout');
+               $dropdown[] = '<li>';
+               $dropdown[] = '<a href="logout.php" target="_top">';
+               $dropdown[] = $languageService->sL($buttonLabel, TRUE);
+               $dropdown[] = '</a>';
+               $dropdown[] = '</li>';
 
-               $html[] = '</ul>';
+               $dropdown[] = '</ul>';
 
-               return implode(LF, $html);
+               return implode(LF, $dropdown);
        }
 
        /**
-        * Returns additional attributes for the list item in the toolbar
-        *
-        * This should not contain the "class" or "id" attribute.
-        * Use the methods for setting these attributes
+        * Returns an additional class if user is in "switch user" mode
         *
-        * @return string List item HTML attibutes
+        * @return array
         */
        public function getAdditionalAttributes() {
-               if ($GLOBALS['BE_USER']->user['ses_backuserid']) {
-                       return 'su-user';
+               $result = array();
+               if ($this->getBackendUser()->user['ses_backuserid']) {
+                       $result['class'] = 'su-user';
                }
+               return $result;
        }
 
        /**
-        * Return attribute id name
+        * This item has a drop down
         *
-        * @return string The name of the ID attribute
+        * @return bool
         */
-       public function getIdAttribute() {
-               return 'topbar-user-menu';
+       public function hasDropDown() {
+               return TRUE;
        }
 
        /**
-        * Returns extra classes
+        * Position relative to others
         *
-        * @return array
+        * @return int
         */
-       public function getExtraClasses() {
-               return array();
+       public function getIndex() {
+               return 80;
        }
 
        /**
-        * This item has a drop down
+        * Returns the current BE user.
         *
-        * @return bool
+        * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
         */
-       public function hasDropDown() {
-               return TRUE;
+       protected function getBackendUser() {
+               return $GLOBALS['BE_USER'];
        }
 
        /**
-        * Position relative to others
+        * Returns LanguageService
         *
-        * @return int
+        * @return \TYPO3\CMS\Lang\LanguageService
         */
-       public function getIndex() {
-               return 80;
+       protected function getLanguageService() {
+               return $GLOBALS['LANG'];
        }
 
 }
index cd1f5bd..07c7662 100644 (file)
@@ -157,7 +157,7 @@ class BackendController {
                $toolbarItemInstances = array();
                $classNameRegistry = $GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'];
                foreach ($classNameRegistry as $className) {
-                       $toolbarItemInstance = GeneralUtility::makeInstance($className, $this);
+                       $toolbarItemInstance = GeneralUtility::makeInstance($className);
                        if (!$toolbarItemInstance instanceof \TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface) {
                                throw new \RuntimeException(
                                        'class ' . $className . ' is registered as toolbar item but does not implement'
@@ -172,10 +172,10 @@ class BackendController {
                                        1415968498
                                );
                        }
+                       // Find next free position in array
                        while(array_key_exists($index, $toolbarItemInstances)) {
                                $index++;
                        }
-                       // Find next free position in
                        $toolbarItemInstances[$index] = $toolbarItemInstance;
                }
                ksort($toolbarItemInstances);
@@ -200,11 +200,9 @@ class BackendController {
                                        <div class="navbar-header" id="typo3-logo">' .
                                                $logo->render() .
                                        '</div>
-                                       <div id="typo3-top">
-                                               <ul class="nav navbar-nav navbar-right typo3-top-toolbar" id="typo3-toolbar">' .
-                                                       $this->renderToolbar() .
-                                               '</ul>
-                                       </div>
+                                       <div id="typo3-top">' .
+                                               $this->renderToolbar() .
+                                       '</div>
                                </div>
                        </div>' .
                        $this->generateModuleMenu();
@@ -315,26 +313,57 @@ class BackendController {
         * @return string top toolbar elements as HTML
         */
        protected function renderToolbar() {
-               $toolbar = '';
+               $toolbar = array();
+               $toolbar[] = '<ul class="nav navbar-nav navbar-right typo3-top-toolbar" id="typo3-toolbar">';
                foreach ($this->toolbarItems as $toolbarItem) {
-                       $menu = $toolbarItem->render();
-                       if ($menu) {
-                               // @TODO: Should throw as soon as "loading by convention" is implemented
-                               if ($toolbarItem instanceof \TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface) {
-                                       $classes = $toolbarItem->getExtraClasses();
-                                       if ($toolbarItem->hasDropdown()) {
-                                               $classes[] = 'dropdown';
-                                       }
-
-                                       $class = implode(' ', $classes);
-                                       if ($class !== '') {
-                                               $class = ' class="' . $class . '"';
-                                       }
-                                       $toolbar .= '<li' . $class . ' id="' . $toolbarItem->getIdAttribute() . '"' . $toolbarItem->getAdditionalAttributes() . '>' . $menu . '</li>';
+                       /** @var \TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface $toolbarItem */
+                       if ($toolbarItem->checkAccess()) {
+                               $hasDropDown = (bool)$toolbarItem->hasDropDown();
+                               $additionalAttributes = (array)$toolbarItem->getAdditionalAttributes();
+
+                               $liAttributes = array();
+
+                               // Merge class: Add dropdown class if hasDropDown, add classes from additonal attributes
+                               $classes = array();
+                               if ($hasDropDown) {
+                                       $classes[] = 'dropdown';
                                }
+                               if (isset($additionalAttributes['class'])) {
+                                       $classes[] = $additionalAttributes['class'];
+                                       unset($additionalAttributes['class']);
+                               }
+                               $liAttributes[] = 'class="' . implode(' ', $classes) . '"';
+
+                               // Add further attributes
+                               foreach($additionalAttributes as $name => $value) {
+                                       $liAttributes[] = $name . '="' . $value . '"';
+                               }
+
+                               // Create a unique id from class name
+                               $className = get_class($toolbarItem);
+                               $className = GeneralUtility::underscoredToLowerCamelCase($className);
+                               $className = GeneralUtility::camelCaseToLowerCaseUnderscored($className);
+                               $className = str_replace(array('_', '\\'), '-', $className);
+                               $liAttributes[] = 'id="' . $className . '"';
+
+                               $toolbar[] = '<li ' . implode(' ', $liAttributes) . '>';
+
+                               if ($hasDropDown) {
+                                       $toolbar[] = '<a href="#" class="dropdown-toggle" data-toggle="dropdown">';
+                                       $toolbar[] = $toolbarItem->getItem();
+                                       $toolbar[] = '</a>';
+                                       $toolbar[] = '<div class="dropdown-menu" role="menu">';
+                                       $toolbar[] = $toolbarItem->getDropDown();
+                                       $toolbar[] = '</div>';
+                               } else {
+                                       $toolbar[] = $toolbarItem->getItem();
+                               }
+                               $toolbar[] = '</li>';
                        }
                }
-               return $toolbar;
+               $toolbar[] = '</ul>';
+
+               return implode(LF, $toolbar);
        }
 
        /**
index 03fa952..1b475e3 100644 (file)
@@ -23,13 +23,6 @@ namespace TYPO3\CMS\Backend\Toolbar;
 interface ToolbarItemInterface {
 
        /**
-        * Constructor that receives a back reference to the backend
-        *
-        * @param \TYPO3\CMS\Backend\Controller\BackendController TYPO3 backend object reference
-        */
-       public function __construct(\TYPO3\CMS\Backend\Controller\BackendController &$backendReference = NULL);
-
-       /**
         * Checks whether the user has access to this toolbar item
         *
         * @return boolean TRUE if user has access, FALSE if not
@@ -37,38 +30,36 @@ interface ToolbarItemInterface {
        public function checkAccess();
 
        /**
-        * Renders the toolbar item
+        * Render "item" part of this toolbar
         *
-        * @return string The toolbar item rendered as HTML string
+        * @return string Toolbar item HTML
         */
-       public function render();
+       public function getItem();
 
        /**
-        * Return attribute id name
+        * TRUE if this toolbar item has a collapsible drop down
         *
-        * @return string The name of the ID attribute
+        * @return bool
         */
-       public function getIdAttribute();
+       public function hasDropDown();
 
        /**
-        * Returns extra classes
+        * Render "drop down" part of this toolbar
         *
-        * @return array
+        * @return string Drop down HTML
         */
-       public function getExtraClasses();
+       public function getDropDown();
 
        /**
-        * TRUE if this toolbar item has a collapsible drop down
+        * Returns an array with additional attributes added to containing <li> tag of the item.
         *
-        * @return bool
-        */
-//     public function hasDropDrown();
-// TODO put that back in action and fix all classes by 2014-11-15
-       /**
-        * Returns additional attributes for the list item in the toolbar
+        * Typical usages are additional css classes and data-* attributes, classes may be merged
+        * with other classes needed by the framework. Do NOT set an id attribute here.
         *
-        * This should not contain the "class" or "id" attribute.
-        * Use the methods for setting these attributes
+        * array(
+        *     'class' => 'my-class',
+        *     'data-foo' => '42',
+        * )
         *
         * @return string List item HTML attibutes
         */
index 24bf19d..d9fd9f7 100644 (file)
@@ -18,11 +18,11 @@ define('TYPO3/CMS/Backend/Toolbar/ClearCacheMenu', ['jquery'], function($) {
 
        var ClearCacheMenu = {
                $spinnerElement: $('<span>', {
-                       'class': 't3-icon fa fa-circle-o-notch spinner fa-spin'
+                       'class': 't3-icon fa fa-circle-o-notch fa-spin'
                }),
                options: {
-                       containerSelector: '#clear-cache-actions-menu',
-                       menuItemSelector: '.dropdown-menu li a',
+                       containerSelector: '#typo3-cms-backend-backend-toolbaritems-clearcachetoolbaritem',
+                       menuItemSelector: '.dropdown-menu a',
                        toolbarIconSelector: '.dropdown-toggle span.t3-icon'
                }
        };
@@ -32,7 +32,7 @@ define('TYPO3/CMS/Backend/Toolbar/ClearCacheMenu', ['jquery'], function($) {
         * the clear cache call
         */
        ClearCacheMenu.initializeEvents = function() {
-               $(ClearCacheMenu.options.menuItemSelector, ClearCacheMenu.options.containerSelector).on('click', function(evt) {
+               $(ClearCacheMenu.options.containerSelector).on('click', ClearCacheMenu.options.menuItemSelector, function(evt) {
                        evt.preventDefault();
                        var ajaxUrl = $(this).attr('href');
                        if (ajaxUrl) {
index e9fcdc1..265bbf9 100644 (file)
@@ -21,7 +21,7 @@ define('TYPO3/CMS/Backend/Toolbar/ShortcutMenu', ['jquery'], function($) {
                        class: 't3-icon fa fa-circle-o-notch fa-spin'
                }),
                options: {
-                       containerSelector: '#shortcut-menu',
+                       containerSelector: '#typo3-cms-backend-backend-toolbaritems-shortcuttoolbaritem',
                        toolbarIconSelector: '.dropdown-toggle span.t3-icon',
                        toolbarMenuSelector: '.dropdown-menu',
                        shortcutItemSelector: '.dropdown-menu .shortcut',
index f6f76ff..54f6107 100644 (file)
@@ -10,10 +10,10 @@ if (TYPO3_MODE === 'BE') {
        );
 
        $GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][] = 'TYPO3\\CMS\\Backend\\Backend\\ToolbarItems\\ClearCacheToolbarItem';
+       $GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][] = 'TYPO3\\CMS\\Backend\\Backend\\ToolbarItems\\HelpToolbarItem';
        $GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][] = 'TYPO3\\CMS\\Backend\\Backend\\ToolbarItems\\LiveSearchToolbarItem';
        $GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][] = 'TYPO3\\CMS\\Backend\\Backend\\ToolbarItems\\ShortcutToolbarItem';
        $GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][] = 'TYPO3\\CMS\\Backend\\Backend\\ToolbarItems\\UserToolbarItem';
-       $GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][] = 'TYPO3\\CMS\\Backend\\Backend\\ToolbarItems\\HelpToolbarItem';
 }
 
 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default'] = 'TYPO3\\CMS\\Core\\FrontendEditing\\FrontendEditingController';
index c1109ee..ec1651e 100644 (file)
@@ -1671,7 +1671,7 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface {
         *              "Backend": Extension Name
         *              "FormEngine": FileName in the Resources/Public/JavaScript folder
         *
-        * @param $mainModuleName must be in the form of "TYPO3/CMS/PackageName/ModuleName" e.g. "TYPO3/CMS/Backend/FormEngine"
+        * @param string $mainModuleName Must be in the form of "TYPO3/CMS/PackageName/ModuleName" e.g. "TYPO3/CMS/Backend/FormEngine"
         * @return void
         */
        public function loadRequireJsModule($mainModuleName) {
index 9e97542..249c561 100644 (file)
@@ -635,23 +635,23 @@ return array(
                                'csrfTokenCheck' => TRUE
                        ),
                        'ShortcutMenu::getShortcutEditForm' => array(
-                               'callbackMethod' => 'TYPO3\\CMS\\Backend\\Toolbar\\ShortcutToolbarItem->getAjaxShortcutEditForm',
+                               'callbackMethod' => 'TYPO3\\CMS\\Backend\\Backend\\ToolbarItems\\ShortcutToolbarItem->getAjaxShortcutEditForm',
                                'csrfTokenCheck' => TRUE
                        ),
                        'ShortcutMenu::saveShortcut' => array(
-                               'callbackMethod' => 'TYPO3\\CMS\\Backend\\Toolbar\\ShortcutToolbarItem->setAjaxShortcut',
+                               'callbackMethod' => 'TYPO3\\CMS\\Backend\\Backend\\ToolbarItems\\ShortcutToolbarItem->setAjaxShortcut',
                                'csrfTokenCheck' => TRUE
                        ),
                        'ShortcutMenu::render' => array(
-                               'callbackMethod' => 'TYPO3\\CMS\\Backend\\Toolbar\\ShortcutToolbarItem->renderAjaxMenu',
+                               'callbackMethod' => 'TYPO3\\CMS\\Backend\\Backend\\ToolbarItems\\ShortcutToolbarItem->renderAjaxMenu',
                                'csrfTokenCheck' => TRUE
                        ),
                        'ShortcutMenu::delete' => array(
-                               'callbackMethod' => 'TYPO3\\CMS\\Backend\\Toolbar\\ShortcutToolbarItem->deleteAjaxShortcut',
+                               'callbackMethod' => 'TYPO3\\CMS\\Backend\\Backend\\ToolbarItems\\ShortcutToolbarItem->deleteAjaxShortcut',
                                'csrfTokenCheck' => TRUE
                        ),
                        'ShortcutMenu::create' => array(
-                               'callbackMethod' => 'TYPO3\\CMS\\Backend\\Toolbar\\ShortcutToolbarItem->createAjaxShortcut',
+                               'callbackMethod' => 'TYPO3\\CMS\\Backend\\Backend\\ToolbarItems\\ShortcutToolbarItem->createAjaxShortcut',
                                'csrfTokenCheck' => TRUE
                        ),
                        'ModuleMenu::reload' => array(
index b678cda..bdacab2 100644 (file)
@@ -15,9 +15,10 @@ namespace TYPO3\CMS\Opendocs\Backend\ToolbarItems;
  */
 
 use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
+use TYPO3\CMS\Backend\Utility\IconUtility;
 
 /**
- * Adding a list of all open documents of a user to the backend.php
+ * Alist of all open documents
  *
  * @author Benjamin Mack <benni@typo3.org>
  * @author Ingo Renner <ingo@typo3.org>
@@ -25,11 +26,6 @@ use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
 class OpendocsToolbarItem implements ToolbarItemInterface {
 
        /**
-        * @var \TYPO3\CMS\Backend\Controller\BackendController
-        */
-       protected $backendReference;
-
-       /**
         * @var array
         */
        protected $openDocs;
@@ -40,19 +36,14 @@ class OpendocsToolbarItem implements ToolbarItemInterface {
        protected $recentDocs;
 
        /**
-        * @var string
-        */
-       protected $EXTKEY = 'opendocs';
-
-       /**
-        * Constructor, loads the documents from the user control
-        *
-        * @param \TYPO3\CMS\Backend\Controller\BackendController TYPO3 backend object reference
+        * Constructor
         */
-       public function __construct(\TYPO3\CMS\Backend\Controller\BackendController &$backendReference = NULL) {
-               $GLOBALS['LANG']->includeLLFile('EXT:opendocs/locallang_opendocs.xlf');
-               $this->backendReference = $backendReference;
+       public function __construct() {
+               $this->getLanguageService()->includeLLFile('EXT:opendocs/locallang_opendocs.xlf');
                $this->loadDocsFromUserSession();
+               $pageRenderer = $this->getPageRenderer();
+               $pageRenderer->loadRequireJsModule('TYPO3/CMS/Opendocs/Toolbar/OpendocsMenu');
+               $pageRenderer->addCssFile(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath('opendocs') . '/Resources/Public/Css/opendocs.css');
        }
 
        /**
@@ -61,7 +52,7 @@ class OpendocsToolbarItem implements ToolbarItemInterface {
         * @return bool TRUE if user has access, FALSE if not
         */
        public function checkAccess() {
-               $conf = $GLOBALS['BE_USER']->getTSConfig('backendToolbarItem.tx_opendocs.disabled');
+               $conf = $this->getBackendUser()->getTSConfig('backendToolbarItem.tx_opendocs.disabled');
                return $conf['value'] != 1;
        }
 
@@ -71,47 +62,39 @@ class OpendocsToolbarItem implements ToolbarItemInterface {
         * @return void
         */
        public function loadDocsFromUserSession() {
-               list($this->openDocs, ) = $GLOBALS['BE_USER']->getModuleData('alt_doc.php', 'ses');
-               $this->recentDocs = $GLOBALS['BE_USER']->getModuleData('opendocs::recent');
+               $backendUser = $this->getBackendUser();
+               list($this->openDocs, ) = $backendUser->getModuleData('alt_doc.php', 'ses');
+               $this->recentDocs = $backendUser->getModuleData('opendocs::recent');
        }
 
        /**
-        * Renders the toolbar item and the initial menu
+        * Render toolbar icon
         *
-        * @return string The toolbar item including the initial menu content as HTML
+        * @return string HTML
         */
-       public function render() {
-               $this->addJavascriptToBackend();
-               $this->addCssToBackend();
+       public function getItem() {
                $numDocs = count($this->openDocs);
-               $opendocsMenu = array();
-               $title = $GLOBALS['LANG']->getLL('toolbaritem', TRUE);
+               $title = $this->getLanguageService()->getLL('toolbaritem', TRUE);
 
-               // Toolbar item icon
-               $opendocsMenu[] = '<a href="#" class="dropdown-toggle" data-toggle="dropdown">';
-               $opendocsMenu[] = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('apps-toolbar-menu-opendocs', array('title' => $title));
+               $opendocsMenu = array();
+               $opendocsMenu[] = IconUtility::getSpriteIcon('apps-toolbar-menu-opendocs', array('title' => $title));
                $opendocsMenu[] = '<span class="badge" id="tx-opendocs-counter">' . $numDocs . '</span>';
-               $opendocsMenu[] = '</a>';
 
-               // Toolbar item menu and initial content
-               $opendocsMenu[] = '<ul class="dropdown-menu" role="menu">';
-               $opendocsMenu[] = $this->renderMenu();
-               $opendocsMenu[] = '</ul>';
                return implode(LF, $opendocsMenu);
        }
 
        /**
-        * renders the pure contents of the menu
+        * Render drop down
         *
-        * @return string The menu's content
+        * @return string HTML
         */
-       public function renderMenu() {
+       public function getDropDown() {
+               $languageService = $this->getLanguageService();
                $openDocuments = $this->openDocs;
                $recentDocuments = $this->recentDocs;
                $entries = array();
-               $content = '';
                if (count($openDocuments)) {
-                       $entries[] = '<li class="dropdown-header">' . $GLOBALS['LANG']->getLL('open_docs', TRUE) . '</li>';
+                       $entries[] = '<li class="dropdown-header">' . $languageService->getLL('open_docs', TRUE) . '</li>';
                        $i = 0;
                        foreach ($openDocuments as $md5sum => $openDocument) {
                                $i++;
@@ -120,7 +103,7 @@ class OpendocsToolbarItem implements ToolbarItemInterface {
                }
                // If there are "recent documents" in the list, add them
                if (count($recentDocuments)) {
-                       $entries[] = '<li class="dropdown-header">' . $GLOBALS['LANG']->getLL('recent_docs', TRUE) . '</li>';
+                       $entries[] = '<li class="dropdown-header">' . $languageService->getLL('recent_docs', TRUE) . '</li>';
                        $i = 0;
                        foreach ($recentDocuments as $md5sum => $recentDocument) {
                                $i++;
@@ -128,9 +111,9 @@ class OpendocsToolbarItem implements ToolbarItemInterface {
                        }
                }
                if (count($entries)) {
-                       $content = implode('', $entries);
+                       $content = '<ul>' . implode('', $entries) . '</ul>';
                } else {
-                       $content = '<li class="noOpenDocs">' . $GLOBALS['LANG']->getLL('no_docs', TRUE) . '</li>';
+                       $content = '<ul><li class="noOpenDocs">' . $languageService->getLL('no_docs', TRUE) . '</li></ul>';
                }
                return $content;
        }
@@ -138,9 +121,13 @@ class OpendocsToolbarItem implements ToolbarItemInterface {
        /**
         * Returns the recent documents list as an array
         *
+        * @param array $document
+        * @param string $md5sum
+        * @param bool $isRecentDoc
+        * @param bool $isFirstDoc
         * @return array All recent documents as list-items
         */
-       public function renderMenuEntry($document, $md5sum, $isRecentDoc = FALSE, $isFirstDoc = FALSE) {
+       protected function renderMenuEntry($document, $md5sum, $isRecentDoc = FALSE, $isFirstDoc = FALSE) {
                $table = $document[3]['table'];
                $uid = $document[3]['uid'];
                $record = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordWSOL($table, $uid);
@@ -181,32 +168,11 @@ class OpendocsToolbarItem implements ToolbarItemInterface {
        }
 
        /**
-        * Returns additional attributes for the list item in the toolbar
-        *
-        * This should not contain the "class" or "id" attribute.
-        * Use the methods for setting these attributes
+        * No additional attributes
         *
         * @return string List item HTML attibutes
         */
        public function getAdditionalAttributes() {
-               return '';
-       }
-
-       /**
-        * Return attribute id name
-        *
-        * @return string The name of the ID attribute
-        */
-       public function getIdAttribute() {
-               return 'tx-opendocs-menu';
-       }
-
-       /**
-        * Returns extra classes
-        *
-        * @return array
-        */
-       public function getExtraClasses() {
                return array();
        }
 
@@ -219,26 +185,6 @@ class OpendocsToolbarItem implements ToolbarItemInterface {
                return TRUE;
        }
 
-       /**
-        * Adds the necessary javascript to the backend
-        *
-        * @return void
-        */
-       protected function addJavascriptToBackend() {
-               $this->backendReference->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Opendocs/Toolbar/OpendocsMenu');
-       }
-
-       /**
-        * Adds the necessary CSS to the backend
-        *
-        * @return void
-        */
-       protected function addCssToBackend() {
-               $this->backendReference->addCssFile(
-                       'opendocs',
-                               \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath($this->EXTKEY) . '/Resources/Public/Css/opendocs.css'
-               );
-       }
 
        /*******************
         ***    HOOKS    ***
@@ -295,8 +241,7 @@ class OpendocsToolbarItem implements ToolbarItemInterface {
         * @return void
         */
        public function renderAjax($params = array(), \TYPO3\CMS\Core\Http\AjaxRequestHandler &$ajaxObj = NULL) {
-               $menuContent = $this->renderMenu();
-               $ajaxObj->addContent('opendocsMenu', $menuContent);
+               $ajaxObj->addContent('opendocsMenu', $this->getDropDown());
        }
 
        /**
@@ -308,4 +253,42 @@ class OpendocsToolbarItem implements ToolbarItemInterface {
                return 30;
        }
 
+       /**
+        * Returns the current BE user.
+        *
+        * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
+        */
+       protected function getBackendUser() {
+               return $GLOBALS['BE_USER'];
+       }
+
+       /**
+        * Returns current PageRenderer
+        *
+        * @return \TYPO3\CMS\Core\Page\PageRenderer
+        */
+       protected function getPageRenderer() {
+               /** @var  \TYPO3\CMS\Backend\Template\DocumentTemplate $documentTemplate */
+               $documentTemplate = $GLOBALS['TBE_TEMPLATE'];
+               return $documentTemplate->getPageRenderer();
+       }
+
+       /**
+        * Returns LanguageService
+        *
+        * @return \TYPO3\CMS\Lang\LanguageService
+        */
+       protected function getLanguageService() {
+               return $GLOBALS['LANG'];
+       }
+
+       /**
+        * Return DatabaseConnection
+        *
+        * @return \TYPO3\CMS\Core\Database\DatabaseConnection
+        */
+       protected function getDatabaseConnection() {
+               return $GLOBALS['TYPO3_DB'];
+       }
+
 }
index 4f57705..abb59ef 100644 (file)
@@ -22,7 +22,7 @@ define('TYPO3/CMS/Opendocs/Toolbar/OpendocsMenu', ['jquery'], function($) {
                        'class': 't3-icon fa fa-circle-o-notch spinner fa-spin'
                }),
                options: {
-                       containerSelector: '#tx-opendocs-menu',
+                       containerSelector: '#typo3-cms-opendocs-backend-toolbaritems-opendocstoolbaritem',
                        hashDataAttributeName: 'opendocsidentifier',
                        closeSelector: '.close',
                        menuContainerSelector: '.dropdown-menu',
index d106c1c..26f08f2 100644 (file)
@@ -16,6 +16,7 @@ namespace TYPO3\CMS\SysAction\Backend\ToolbarItems;
 
 use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
+use TYPO3\CMS\Backend\Utility\IconUtility;
 
 /**
  * Adds action links to the backend's toolbar
@@ -25,73 +26,68 @@ use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
 class ActionToolbarItem implements ToolbarItemInterface {
 
        /**
-        * @var \TYPO3\CMS\Backend\Controller\BackendController
+        * @var array List of action entries
         */
-       protected $backendReference;
-
-       /**
-        * @var string
-        */
-       protected $extensionKey = 'sys_action';
+       protected $actionEntries = array();
 
        /**
         * Constructor
         */
-       public function __construct(\TYPO3\CMS\Backend\Controller\BackendController &$backendReference = NULL) {
-               $GLOBALS['LANG']->includeLLFile('EXT:sys_action/locallang.xlf');
-               $this->backendReference = $backendReference;
+       public function __construct() {
+               $this->getLanguageService()->includeLLFile('EXT:sys_action/locallang.xlf');
+               $this->initializeActionEntries();
        }
 
        /**
-        * Sets the backend reference
+        * Render toolbar icon
         *
-        * @param \TYPO3\CMS\Backend\Controller\BackendController $backendReference Backend object reference
-        * @return void
+        * @return string HTML
         */
-       public function setBackend(\TYPO3\CMS\Backend\Controller\BackendController &$backendReference) {
-               $this->backendReference = $backendReference;
+       public function getItem() {
+               return IconUtility::getSpriteIcon(
+                       'apps-toolbar-menu-actions',
+                       array(
+                               'title' => $this->getLanguageService()->getLL('action_toolbaritem', TRUE)
+                       )
+               );
        }
 
        /**
-        * Renders the toolbar menu
+        * Render drop down
         *
-        * @return string The rendered backend menu
-        * @author Ingo Renner <ingo@typo3.org>
+        * @return string HTML
         */
-       public function render() {
+       public function getDropDown() {
                $actionMenu = array();
-               $actionEntries = $this->getActionEntries();
-               if ($actionEntries) {
-                       $title = $GLOBALS['LANG']->getLL('action_toolbaritem', TRUE);
-                       $actionMenu[] = '<a href="#" class="dropdown-toggle" data-toggle="dropdown">' . \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('apps-toolbar-menu-actions', array('title' => $title)) . '</a>';
-                       $actionMenu[] = '<ul class="dropdown-menu" role="menu">';
-                       foreach ($actionEntries as $linkConf) {
-                               $actionMenu[] = '<li><a href="' . htmlspecialchars($linkConf[1]) . '" target="content">' . $linkConf[2] . htmlspecialchars($linkConf[0]) . '</a></li>';
-                       }
-                       $actionMenu[] = '</ul>';
-                       return implode(LF, $actionMenu);
-               } else {
-                       return '';
+               $actionMenu[] = '<ul>';
+               foreach ($this->actionEntries as $linkConf) {
+                       $actionMenu[] = '<li>';
+                       $actionMenu[] = '<a href="' . htmlspecialchars($linkConf[1]) . '" target="content">';
+                       $actionMenu[] = $linkConf[2] . htmlspecialchars($linkConf[0]);
+                       $actionMenu[] = '</a>';
+                       $actionMenu[] = '</li>';
                }
+               $actionMenu[] = '</ul>';
+               return implode(LF, $actionMenu);
        }
 
        /**
         * Gets the entries for the action menu
         *
         * @return array Array of action menu entries
-        * @author Steffen Kamper <info@sk-typo3.de>
-        * @author Ingo Renner <ingo@typo3.org>
         */
-       protected function getActionEntries() {
+       protected function initializeActionEntries() {
+               $backendUser = $this->getBackendUser();
+               $databaseConnection = $this->getDatabaseConnection();
                $actions = array();
-               if ($GLOBALS['BE_USER']->isAdmin()) {
-                       $queryResource = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_action', 'pid = 0 AND hidden=0', '', 'sys_action.sorting');
+               if ($backendUser->isAdmin()) {
+                       $queryResource = $databaseConnection->exec_SELECTquery('*', 'sys_action', 'pid = 0 AND hidden=0', '', 'sys_action.sorting');
                } else {
                        $groupList = 0;
-                       if ($GLOBALS['BE_USER']->groupList) {
-                               $groupList = $GLOBALS['BE_USER']->groupList;
+                       if ($backendUser->groupList) {
+                               $groupList = $backendUser->groupList;
                        }
-                       $queryResource = $GLOBALS['TYPO3_DB']->exec_SELECT_mm_query(
+                       $queryResource = $databaseConnection->exec_SELECT_mm_query(
                                'sys_action.*',
                                'sys_action',
                                'sys_action_asgr_mm',
@@ -103,45 +99,24 @@ class ActionToolbarItem implements ToolbarItemInterface {
                }
 
                if ($queryResource) {
-                       while ($actionRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($queryResource)) {
+                       while ($actionRow = $databaseConnection->sql_fetch_assoc($queryResource)) {
                                $actions[] = array(
                                        $actionRow['title'],
                                        BackendUtility::getModuleUrl('user_task') . '&SET[mode]=tasks&SET[function]=sys_action.TYPO3\\CMS\\SysAction\\ActionTask&show=' . $actionRow['uid'],
-                                       \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForRecord('sys_action', $actionRow)
+                                       IconUtility::getSpriteIconForRecord('sys_action', $actionRow)
                                );
                        }
-                       $GLOBALS['TYPO3_DB']->sql_free_result($queryResource);
+                       $databaseConnection->sql_free_result($queryResource);
                }
-               return $actions;
-       }
-
-       /**
-        * Returns additional attributes for the list item in the toolbar
-        *
-        * This should not contain the "class" or "id" attribute.
-        * Use the methods for setting these attributes
-        *
-        * @return string List item HTML attibutes
-        */
-       public function getAdditionalAttributes() {
-               return '';
+               $this->actionEntries = $actions;
        }
 
        /**
-        * Return attribute id name
-        *
-        * @return string The name of the ID attribute
-        */
-       public function getIdAttribute() {
-               return 'tx-sys-action-menu';
-       }
-
-       /**
-        * Returns extra classes
+        * This toolbar needs no additional attributes
         *
         * @return array
         */
-       public function getExtraClasses() {
+       public function getAdditionalAttributes() {
                return array();
        }
 
@@ -155,13 +130,16 @@ class ActionToolbarItem implements ToolbarItemInterface {
        }
 
        /**
-        * Checks if user has access to the sys action menu
+        * This toolbar is rendered if there are action entries, no further user restriction
         *
-        * @return bool TRUE if the user has access, FALSE otherwise
+        * @return bool TRUE
         */
        public function checkAccess() {
-               // Taskcenter is enabled for everybody
-               return TRUE;
+               $result = FALSE;
+               if (count($this->actionEntries)) {
+                       $result = TRUE;
+               }
+               return $result;
        }
 
        /**
@@ -173,4 +151,31 @@ class ActionToolbarItem implements ToolbarItemInterface {
                return 35;
        }
 
+       /**
+        * Returns the current BE user.
+        *
+        * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
+        */
+       protected function getBackendUser() {
+               return $GLOBALS['BE_USER'];
+       }
+
+       /**
+        * Returns LanguageService
+        *
+        * @return \TYPO3\CMS\Lang\LanguageService
+        */
+       protected function getLanguageService() {
+               return $GLOBALS['LANG'];
+       }
+
+       /**
+        * Return DatabaseConnection
+        *
+        * @return \TYPO3\CMS\Core\Database\DatabaseConnection
+        */
+       protected function getDatabaseConnection() {
+               return $GLOBALS['TYPO3_DB'];
+       }
+
 }
index 8be0193..bff82fc 100644 (file)
@@ -69,12 +69,30 @@ Topbar
                        .dropdown-menu {
                                background-color: @navbar-inverse-link-active-bg;
                                color: @navbar-inverse-link-active-color;
-                               border: 0;
-                               margin: 0;
+                               border: none;
 
-                               .active {
-                                       a {
-                                               background-color: darken(@navbar-inverse-link-active-bg, 15%);
+                               // Dropdown-menu with UL
+                               > ul {
+                                       .list-unstyled;
+
+                                       > li {
+                                               > a {
+                                                       color: @navbar-inverse-link-active-color;
+                                                       display: block;
+                                                       padding: 3px 20px;
+                                                       clear: both;
+                                                       font-weight: normal;
+                                                       line-height: @line-height-base;
+                                                       white-space: nowrap;
+                                               }
+
+                                               &.active {
+                                                       > a {
+                                                               background-color: darken(@navbar-inverse-link-active-bg, 15%);
+
+                                                       }
+
+                                               }
                                        }
                                }
 
index 0e818d7..c6e2ec4 100644 (file)
@@ -11419,10 +11419,22 @@ Topbar
 #typo3-topbar #typo3-top-container #typo3-toolbar .dropdown-menu {
   background-color: #4e4e4e;
   color: #ffffff;
-  border: 0;
-  margin: 0;
+  border: none;
+}
+#typo3-topbar #typo3-top-container #typo3-toolbar .dropdown-menu > ul {
+  padding-left: 0;
+  list-style: none;
+}
+#typo3-topbar #typo3-top-container #typo3-toolbar .dropdown-menu > ul > li > a {
+  color: #ffffff;
+  display: block;
+  padding: 3px 20px;
+  clear: both;
+  font-weight: normal;
+  line-height: 1.5;
+  white-space: nowrap;
 }
-#typo3-topbar #typo3-top-container #typo3-toolbar .dropdown-menu .active a {
+#typo3-topbar #typo3-top-container #typo3-toolbar .dropdown-menu > ul > li.active > a {
   background-color: #282828;
 }
 #typo3-topbar #typo3-top-container #typo3-toolbar .dropdown-menu li a,
index c980baa..eaa79de 100644 (file)
@@ -15,32 +15,24 @@ namespace TYPO3\CMS\Workspaces\Backend\ToolbarItems;
  */
 
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
+use \TYPO3\CMS\Workspaces\Service\WorkspaceService;
+use TYPO3\CMS\Backend\Utility\IconUtility;
 
 /**
  * Class to render the workspace selector
  *
  * @author Ingo Renner <ingo@typo3.org>
  */
-class WorkspaceSelectorToolbarItem implements \TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface {
-
-       /**
-        * @var \TYPO3\CMS\Backend\Controller\BackendController
-        */
-       protected $backendReference;
-
-       /**
-        * @var bool|null
-        */
-       protected $checkAccess = NULL;
+class WorkspaceSelectorToolbarItem implements ToolbarItemInterface {
 
        /**
         * Constructor
-        *
-        * @param \TYPO3\CMS\Backend\Controller\BackendController $backendReference TYPO3 backend object reference
         */
-       public function __construct(\TYPO3\CMS\Backend\Controller\BackendController &$backendReference = NULL) {
-               $this->backendReference = $backendReference;
-               $this->backendReference->getPageRenderer()->addInlineLanguageLabel('Workspaces.workspaceTitle', \TYPO3\CMS\Workspaces\Service\WorkspaceService::getWorkspaceTitle($GLOBALS['BE_USER']->workspace));
+       public function __construct() {
+               $pageRenderer = $this->getPageRenderer();
+               $pageRenderer->addInlineLanguageLabel('Workspaces.workspaceTitle', WorkspaceService::getWorkspaceTitle($this->getBackendUser()->workspace));
+               $pageRenderer->loadRequireJsModule('TYPO3/CMS/Workspaces/Toolbar/WorkspacesMenu');
        }
 
        /**
@@ -49,36 +41,43 @@ class WorkspaceSelectorToolbarItem implements \TYPO3\CMS\Backend\Toolbar\Toolbar
         * @return bool TRUE if user has access, FALSE if not
         */
        public function checkAccess() {
-               if ($this->checkAccess === NULL) {
-                       /** @var \TYPO3\CMS\Workspaces\Service\WorkspaceService $wsService */
-                       $wsService = GeneralUtility::makeInstance(\TYPO3\CMS\Workspaces\Service\WorkspaceService::class);
-                       $availableWorkspaces = $wsService->getAvailableWorkspaces();
-                       if (count($availableWorkspaces) > 0) {
-                               $this->checkAccess = TRUE;
-                       } else {
-                               $this->checkAccess = FALSE;
-                       }
+               /** @var \TYPO3\CMS\Workspaces\Service\WorkspaceService $wsService */
+               $wsService = GeneralUtility::makeInstance(WorkspaceService::class);
+               $availableWorkspaces = $wsService->getAvailableWorkspaces();
+               if (count($availableWorkspaces) > 0) {
+                       $result = TRUE;
+               } else {
+                       $result = FALSE;
                }
-               return $this->checkAccess;
+               return $result;
        }
 
        /**
-        * Creates the selector for workspaces
+        * Render item
         *
-        * @return string workspace selector as HTML select
+        * @return string HTML
         */
-       public function render() {
-               $title = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.workspace', TRUE);
-               $this->backendReference->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Workspaces/Toolbar/WorkspacesMenu');
+       public function getItem() {
+               return IconUtility::getSpriteIcon(
+                       'apps-toolbar-menu-workspace',
+                       array(
+                               'title' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:toolbarItems.workspace', TRUE),
+                       )
+               );
+       }
+
+       public function getDropDown() {
+               $backendUser = $this->getBackendUser();
+               $languageService = $this->getLanguageService();
 
                $index = 0;
-               /** @var \TYPO3\CMS\Workspaces\Service\WorkspaceService $wsService */
-               $wsService = GeneralUtility::makeInstance(\TYPO3\CMS\Workspaces\Service\WorkspaceService::class);
+               /** @var WorkspaceService $wsService */
+               $wsService = GeneralUtility::makeInstance(WorkspaceService::class);
                $availableWorkspaces = $wsService->getAvailableWorkspaces();
-               $activeWorkspace = (int)$GLOBALS['BE_USER']->workspace;
-               $stateCheckedIcon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('status-status-checked');
-               $stateUncheckedIcon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('empty-empty', array(
-                       'title' => $GLOBALS['LANG']->getLL('bookmark_inactive')
+               $activeWorkspace = (int)$backendUser->workspace;
+               $stateCheckedIcon = IconUtility::getSpriteIcon('status-status-checked');
+               $stateUncheckedIcon = IconUtility::getSpriteIcon('empty-empty', array(
+                       'title' => $languageService->getLL('bookmark_inactive')
                ));
 
                $workspaceSections = array(
@@ -91,23 +90,27 @@ class WorkspaceSelectorToolbarItem implements \TYPO3\CMS\Backend\Toolbar\Toolbar
                        $iconState = ($workspaceId === $activeWorkspace ? $stateCheckedIcon : $stateUncheckedIcon);
                        $classValue = ($workspaceId === $activeWorkspace ? ' class="selected"' : '');
                        $sectionName = ($index++ === 0 ? 'top' : 'items');
-                       $workspaceSections[$sectionName][] = '<li' . $classValue . '>' . '<a href="backend.php?changeWorkspace=' . $workspaceId . '" data-workspaceid="' . $workspaceId . '" class="tx-workspaces-switchlink">' . $iconState . ' ' . htmlspecialchars($label) . '</a></li>';
+                       $workspaceSections[$sectionName][] = '<li' . $classValue . '>'
+                               . '<a href="backend.php?changeWorkspace=' . $workspaceId . '" data-workspaceid="' . $workspaceId . '" class="tx-workspaces-switchlink">'
+                               . $iconState . ' ' . htmlspecialchars($label)
+                               . '</a></li>';
                }
 
                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 ($GLOBALS['BE_USER']->check('modules', 'web_WorkspacesWorkspaces')) {
-                               $workspaceSections['top'][] = '<li><a target="content" data-module="web_WorkspacesWorkspaces" class="tx-workspaces-modulelink">' . $stateUncheckedIcon . ' ' . $GLOBALS['LANG']->getLL('bookmark_workspace', TRUE) . '</a></li>';
+                       if ($backendUser->check('modules', 'web_WorkspacesWorkspaces')) {
+                               $workspaceSections['top'][] = '<li><a target="content" data-module="web_WorkspacesWorkspaces" class="tx-workspaces-modulelink">'
+                                       . $stateUncheckedIcon . ' ' . $languageService->getLL('bookmark_workspace', TRUE)
+                                       . '</a></li>';
                        }
                } else {
                        // no items on top (= no workspace to work in)
-                       $workspaceSections['top'][] = '<li>' . $stateUncheckedIcon . ' ' . $GLOBALS['LANG']->getLL('bookmark_noWSfound', TRUE) . '</li>';
+                       $workspaceSections['top'][] = '<li>' . $stateUncheckedIcon . ' ' . $languageService->getLL('bookmark_noWSfound', TRUE) . '</li>';
                }
 
                $workspaceMenu = array(
-                       '<a href="#" class="dropdown-toggle" data-toggle="dropdown">' . \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('apps-toolbar-menu-workspace', array('title' => $title)) . '</a>',
-                       '<ul class="dropdown-menu" role="menu">' ,
+                       '<ul>' ,
                                implode(LF, $workspaceSections['top']),
                                (!empty($workspaceSections['items']) ? '<li class="divider"></li>' : ''),
                                implode(LF, $workspaceSections['items']),
@@ -118,51 +121,59 @@ class WorkspaceSelectorToolbarItem implements \TYPO3\CMS\Backend\Toolbar\Toolbar
        }
 
        /**
-        * Returns additional attributes for the list item in the toolbar
-        *
-        * This should not contain the "class" or "id" attribute.
-        * Use the methods for setting these attributes
+        * This toolbar needs no additional attributes
         *
-        * @return string List item HTML attibutes
+        * @return array
         */
        public function getAdditionalAttributes() {
-               return '';
+               return array();
        }
 
        /**
-        * Return attribute id name
+        * This item has a drop down
         *
-        * @return string The name of the ID attribute
+        * @return bool
         */
-       public function getIdAttribute() {
-               return 'workspace-selector-menu';
+       public function hasDropDown() {
+               return TRUE;
        }
 
        /**
-        * Returns extra classes
+        * Position relative to others
         *
-        * @return array
+        * @return int
         */
-       public function getExtraClasses() {
-               return array();
+       public function getIndex() {
+               return 40;
        }
 
        /**
-        * This item has a drop down
+        * Returns the current BE user.
         *
-        * @return bool
+        * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
         */
-       public function hasDropDown() {
-               return TRUE;
+       protected function getBackendUser() {
+               return $GLOBALS['BE_USER'];
        }
 
        /**
-        * Position relative to others
+        * Returns current PageRenderer
         *
-        * @return int
+        * @return \TYPO3\CMS\Core\Page\PageRenderer
         */
-       public function getIndex() {
-               return 40;
+       protected function getPageRenderer() {
+               /** @var  \TYPO3\CMS\Backend\Template\DocumentTemplate $documentTemplate */
+               $documentTemplate = $GLOBALS['TBE_TEMPLATE'];
+               return $documentTemplate->getPageRenderer();
+       }
+
+       /**
+        * Returns LanguageService
+        *
+        * @return \TYPO3\CMS\Lang\LanguageService
+        */
+       protected function getLanguageService() {
+               return $GLOBALS['LANG'];
        }
 
 }
index c1e445d..06ad04e 100644 (file)
@@ -18,7 +18,7 @@ define('TYPO3/CMS/Workspaces/Toolbar/WorkspacesMenu', ['jquery'], function($) {
 
        var WorkspacesMenu = {
                options: {
-                       containerSelector: '#workspace-selector-menu',
+                       containerSelector: '#typo3-cms-workspaces-backend-toolbaritems-workspaceselectortoolbaritem',
                        menuItemSelector: '.dropdown-menu li a.tx-workspaces-switchlink',
                        activeMenuItemSelector: '.dropdown-menu .selected',
                        toolbarItemSelector: '.dropdown-toggle',