[TASK] ToolbarItem registration and position 49/34149/6
authorChristian Kuhn <lolli@schwarzbu.ch>
Fri, 14 Nov 2014 10:32:46 +0000 (11:32 +0100)
committerFelix Kopp <felix-source@phorax.com>
Fri, 14 Nov 2014 17:30:50 +0000 (18:30 +0100)
Toolbar items are now registered with its class name in array
$GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'].

The ToolbarItem interface adds a position method to determine
the order of items.

Resolves: #62959
Releases: master
Change-Id: Ie18d4b2148093f28c1f5387907912d8591797582
Reviewed-on: http://review.typo3.org/34149
Reviewed-by: Benjamin Mack <benni@typo3.org>
Tested-by: Benjamin Mack <benni@typo3.org>
Reviewed-by: Felix Kopp <felix-source@phorax.com>
Tested-by: Felix Kopp <felix-source@phorax.com>
27 files changed:
typo3/sysext/backend/Classes/Backend/ToolbarItems/ClearCacheToolbarItem.php [new file with mode: 0644]
typo3/sysext/backend/Classes/Backend/ToolbarItems/LiveSearchToolbarItem.php [new file with mode: 0644]
typo3/sysext/backend/Classes/Backend/ToolbarItems/ShortcutToolbarItem.php [new file with mode: 0644]
typo3/sysext/backend/Classes/Backend/ToolbarItems/UserToolbarItem.php [new file with mode: 0644]
typo3/sysext/backend/Classes/Controller/BackendController.php
typo3/sysext/backend/Classes/Toolbar/ClearCacheToolbarItem.php [deleted file]
typo3/sysext/backend/Classes/Toolbar/LiveSearchToolbarItem.php [deleted file]
typo3/sysext/backend/Classes/Toolbar/ShortcutToolbarItem.php [deleted file]
typo3/sysext/backend/Classes/Toolbar/ToolbarItemHookInterface.php [deleted file]
typo3/sysext/backend/Classes/Toolbar/ToolbarItemInterface.php
typo3/sysext/backend/ext_localconf.php
typo3/sysext/compatibility6/Migrations/Code/ClassAliasMap.php
typo3/sysext/compatibility6/Migrations/Code/LegacyClassesForIde.php
typo3/sysext/core/Configuration/DefaultConfiguration.php
typo3/sysext/opendocs/Classes/Backend/ToolbarItems/OpendocsToolbarItem.php [new file with mode: 0644]
typo3/sysext/opendocs/Classes/Controller/OpendocsController.php [deleted file]
typo3/sysext/opendocs/Migrations/Code/ClassAliasMap.php
typo3/sysext/opendocs/Resources/PHP/RegisterToolbarItem.php [deleted file]
typo3/sysext/opendocs/ext_localconf.php
typo3/sysext/sys_action/Classes/ActionToolbarMenu.php [deleted file]
typo3/sysext/sys_action/Classes/Backend/ToolbarItems/ActionToolbarItem.php [new file with mode: 0644]
typo3/sysext/sys_action/Resources/PHP/RegisterToolbarItem.php [deleted file]
typo3/sysext/sys_action/ext_localconf.php
typo3/sysext/workspaces/Classes/Backend/ToolbarItems/WorkspaceSelectorToolbarItem.php [new file with mode: 0644]
typo3/sysext/workspaces/Classes/ExtDirect/WorkspaceSelectorToolbarItem.php [deleted file]
typo3/sysext/workspaces/Resources/PHP/RegisterToolbarItem.php [deleted file]
typo3/sysext/workspaces/ext_localconf.php

diff --git a/typo3/sysext/backend/Classes/Backend/ToolbarItems/ClearCacheToolbarItem.php b/typo3/sysext/backend/Classes/Backend/ToolbarItems/ClearCacheToolbarItem.php
new file mode 100644 (file)
index 0000000..4d5cc32
--- /dev/null
@@ -0,0 +1,219 @@
+<?php
+namespace TYPO3\CMS\Backend\Backend\ToolbarItems;
+
+/**
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Backend\Utility\IconUtility;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
+
+/**
+ * class to render the menu for the cache clearing actions
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ */
+class ClearCacheToolbarItem implements ToolbarItemInterface {
+
+       /**
+        * @var array
+        */
+       protected $cacheActions;
+
+       /**
+        * @var array
+        */
+       protected $optionValues;
+
+       /**
+        * @var \TYPO3\CMS\Backend\Controller\BackendController
+        */
+       protected $backendReference;
+
+       /**
+        * TODO potentially unused
+        * @var string
+        */
+       public $backPath = '';
+
+       /**
+        * 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();
+               $backendUser = $this->getBackendUser();
+
+               // 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'),
+                               'icon' => IconUtility::getSpriteIcon('actions-system-cache-clear-impact-low')
+                       );
+                       $this->optionValues[] = 'pages';
+               }
+
+               // Clear cache for ALL tables!
+               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'),
+                               'icon' => IconUtility::getSpriteIcon('actions-system-cache-clear-impact-medium')
+                       );
+                       $this->optionValues[] = 'all';
+               }
+
+               // Clearing of system cache (core cache, class cache etc)
+               // is only shown explicitly if activated for a BE-user (not activated for admins by default)
+               // or if the system runs in development mode
+               // or if $GLOBALS['TYPO3_CONF_VARS']['SYS']['clearCacheSystem'] is set (only for admins)
+               if ($backendUser->getTSConfigVal('options.clearCache.system') || GeneralUtility::getApplicationContext()->isDevelopment()
+                       || ((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'),
+                               '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) {
+                                       throw new \UnexpectedValueException('$hookObject must implement interface TYPO3\\CMS\\Backend\\Toolbar\\ClearCacheActionsHookInterface', 1228262000);
+                               }
+                               $hookObject->manipulateCacheActions($this->cacheActions, $this->optionValues);
+                       }
+               }
+       }
+
+       /**
+        * Checks whether the user has access to this toolbar item
+        *
+        * @return bool TRUE if user has access, FALSE if not
+        */
+       public function checkAccess() {
+               $backendUser = $this->getBackendUser();
+               if ($backendUser->isAdmin()) {
+                       return TRUE;
+               }
+               if (is_array($this->optionValues)) {
+                       foreach ($this->optionValues as $value) {
+                               if ($backendUser->getTSConfigVal('options.clearCache.' . $value)) {
+                                       return TRUE;
+                               }
+                       }
+               }
+               return FALSE;
+       }
+
+       /**
+        * Creates the selector for workspaces
+        *
+        * @return string Workspace selector as HTML select
+        */
+       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);
+       }
+
+       /**
+        * Adds the necessary JavaScript to the backend
+        *
+        * @return void
+        */
+       protected function addJavascriptToBackend() {
+               $this->backendReference->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Toolbar/ClearCacheMenu');
+       }
+
+       /**
+        * 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 'clear-cache-actions-menu';
+       }
+
+       /**
+        * Returns extra classes
+        *
+        * @return array
+        */
+       public function getExtraClasses() {
+               return array();
+       }
+
+       /**
+        * Get dropdown
+        *
+        * @return bool
+        */
+       public function getDropdown() {
+               return TRUE;
+       }
+
+       /**
+        * Returns the current BE user.
+        *
+        * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
+        */
+       protected function getBackendUser() {
+               return $GLOBALS['BE_USER'];
+       }
+
+       /**
+        * Position relative to others
+        *
+        * @return int
+        */
+       public function getIndex() {
+               return 25;
+       }
+
+}
diff --git a/typo3/sysext/backend/Classes/Backend/ToolbarItems/LiveSearchToolbarItem.php b/typo3/sysext/backend/Classes/Backend/ToolbarItems/LiveSearchToolbarItem.php
new file mode 100644 (file)
index 0000000..90b2f3e
--- /dev/null
@@ -0,0 +1,126 @@
+<?php
+namespace TYPO3\CMS\Backend\Backend\ToolbarItems;
+
+/**
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
+
+/**
+ * Adds backend live search to the toolbar
+ *
+ * @author Michael Klapper <michael.klapper@aoemedia.de>
+ * @author Jeff Segars <jeff@webempoweredchurch.org>
+ */
+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;
+       }
+
+       /**
+        * Checks whether the user has access to this toolbar item
+        *
+        * @return bool TRUE if user has access, FALSE if not
+        */
+       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->observeWorkspaces = TRUE;
+               $loadModules->load($GLOBALS['TBE_MODULES']);
+               // Live search is heavily dependent on the list module and only available when that module is.
+               if (is_array($loadModules->modules['web']['sub']['list'])) {
+                       $access = TRUE;
+               }
+               return $access;
+       }
+
+       /**
+        * Creates the selector for workspaces
+        *
+        * @return string Workspace selector as HTML select
+        */
+       public function render() {
+               $this->backendReference->addJavascriptFile('sysext/backend/Resources/Public/JavaScript/livesearch.js');
+
+               return '
+                       <form class="navbar-form" role="search">
+                               <div class="live-search-wrapper">
+                                       <div class="form-group">
+                                               <input type="text" class="form-control" placeholder="Search" id="live-search-box">
+                                       </div>
+                               </div>
+                       </form>
+               ';
+       }
+
+       /**
+        * 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 'livesearch-menu';
+       }
+
+       /**
+        * Returns extra classes
+        *
+        * @return array
+        */
+       public function getExtraClasses() {
+               return array();
+       }
+
+       /**
+        * Get dropdown
+        *
+        * @return bool
+        */
+       public function getDropdown() {
+               return FALSE;
+       }
+
+       /**
+        * Position relative to others, live search should be very right
+        *
+        * @return int
+        */
+       public function getIndex() {
+               return 90;
+       }
+
+}
diff --git a/typo3/sysext/backend/Classes/Backend/ToolbarItems/ShortcutToolbarItem.php b/typo3/sysext/backend/Classes/Backend/ToolbarItems/ShortcutToolbarItem.php
new file mode 100644 (file)
index 0000000..4cece5a
--- /dev/null
@@ -0,0 +1,755 @@
+<?php
+namespace TYPO3\CMS\Backend\Backend\ToolbarItems;
+
+/**
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Backend\Utility\IconUtility;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\MathUtility;
+use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
+
+/**
+ * Class to render the shortcut menu
+ *
+ * @author Ingo Renner <ingo@typo3.org>
+ */
+class ShortcutToolbarItem implements ToolbarItemInterface {
+
+       const SUPERGLOBAL_GROUP = -100;
+
+       /**
+        * @var string
+        */
+       public $perms_clause;
+
+       /**
+        * @var string
+        */
+       public $backPath;
+
+       /**
+        * @var array
+        */
+       public $fieldArray;
+
+       /**
+        * All available shortcuts
+        *
+        * @var array
+        */
+       protected $shortcuts;
+
+       /**
+        * @var array
+        */
+       protected $shortcutGroups;
+
+       /**
+        * Labels of all groups.
+        * If value is 1, the system will try to find a label in the locallang array.
+        *
+        * @var array
+        */
+       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) {
+               if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX) {
+                       $GLOBALS['LANG']->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->load($GLOBALS['TBE_MODULES']);
+               }
+               $this->backendReference = $backendReference;
+               $this->shortcuts = array();
+               // By default, 5 groups are set
+               $this->shortcutGroups = array(
+                       1 => '1',
+                       2 => '1',
+                       3 => '1',
+                       4 => '1',
+                       5 => '1'
+               );
+               $this->shortcutGroups = $this->initShortcutGroups();
+               $this->shortcuts = $this->initShortcuts();
+       }
+
+       /**
+        * Checks whether the user has access to this toolbar item
+        *
+        * @return bool TRUE if user has access, FALSE if not
+        */
+       public function checkAccess() {
+               return (bool)$GLOBALS['BE_USER']->getTSConfigVal('options.enableBookmarks');
+       }
+
+       /**
+        * Creates the shortcut menu (default renderer)
+        *
+        * @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);
+       }
+
+       /**
+        * Renders the pure contents of the menu
+        *
+        * @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">';
+               // Render shortcuts with no group (group id = 0) first
+               $noGroupShortcuts = $this->getShortcutsByGroup(0);
+               foreach ($noGroupShortcuts as $shortcut) {
+                       $shortcutMenu[] = '
+                       <tr class="shortcut" data-shortcutid="' . $shortcut['raw']['uid'] . '">
+                               <td class="shortcut-icon">' . $shortcut['icon'] . '</td>
+                               <td class="shortcut-label">
+                                       <a href="#" onclick="' . $shortcut['action'] . '; return false;">' . htmlspecialchars($shortcut['label']) . '</a>
+                               </td>
+                               <td class="shortcut-edit">' . $editIcon . ' /></td>
+                               <td class="shortcut-delete">' . $deleteIcon . '</td>
+                       </tr>';
+               }
+               // Now render groups and the contained shortcuts
+               $groups = $this->getGroupsFromShortcuts();
+               krsort($groups, SORT_NUMERIC);
+               foreach ($groups as $groupId => $groupLabel) {
+                       if ($groupId != 0) {
+                               $shortcutGroup = '
+                               <tr class="shortcut-group" id="shortcut-group-' . $groupId . '">
+                                       <td class="shortcut-group-icon">' . $groupIcon . '</td>
+                                       <td class="shortcut-group-label">' . $groupLabel . '</td>
+                                       <td colspan="2">&nbsp;</td>
+                               </tr>';
+                               $shortcuts = $this->getShortcutsByGroup($groupId);
+                               $i = 0;
+                               foreach ($shortcuts as $shortcut) {
+                                       $i++;
+                                       $firstRow = '';
+                                       if ($i == 1) {
+                                               $firstRow = ' first-row';
+                                       }
+                                       $shortcutGroup .= '
+                                       <tr class="shortcut' . $firstRow . '" data-shortcutid="' . $shortcut['raw']['uid'] . '" data-shortcutgroup="' . $groupId . '">
+                                               <td class="shortcut-icon">' . $shortcut['icon'] . '</td>
+                                               <td class="shortcut-label">
+                                                       <a href="#" onclick="' . $shortcut['action'] . '; return false;">' . htmlspecialchars($shortcut['label']) . '</a>
+                                               </td>
+                                               <td class="shortcut-edit">' . $editIcon . ' /></td>
+                                               <td class="shortcut-delete">' . $deleteIcon . '</td>
+                                       </tr>';
+                               }
+                               $shortcutMenu[] = $shortcutGroup;
+                       }
+               }
+               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);
+                       $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'));
+                       $shortcutMenu[] = '<tr><td style="padding:1px 2px; color: #838383;">' . $label . '</td></tr>';
+               }
+               $shortcutMenu[] = '</table>';
+               $compiledShortcutMenu = implode(LF, $shortcutMenu);
+               return $compiledShortcutMenu;
+       }
+
+       /**
+        * Renders the menu so that it can be returned as response to an AJAX call
+        *
+        * @param array $params Array of parameters from the AJAX interface, currently unused
+        * @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();
+               $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
+        *
+        * @return array
+        */
+       public function getExtraClasses() {
+               return array();
+       }
+
+       /**
+        * Get dropdown
+        *
+        * @return bool
+        */
+       public function getDropdown() {
+               return TRUE;
+       }
+
+       /**
+        * Retrieves the shortcuts for the current user
+        *
+        * @return array Array of shortcuts
+        */
+       protected function initShortcuts() {
+               $globalGroupIdList = implode(',', array_keys($this->getGlobalShortcutGroups()));
+               $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
+                       '*',
+                       'sys_be_shortcuts',
+                       '(userid = ' . (int)$GLOBALS['BE_USER']->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)) {
+                       $shortcut = array('raw' => $row);
+
+                       list($row['module_name'], $row['M_module_name']) = explode('|', $row['module_name']);
+
+                       $queryParts = parse_url($row['url']);
+                       $queryParameters = GeneralUtility::explodeUrl2Array($queryParts['query'], 1);
+                       if ($row['module_name'] === 'xMOD_alt_doc.php' && is_array($queryParameters['edit'])) {
+                               $shortcut['table'] = key($queryParameters['edit']);
+                               $shortcut['recordid'] = key($queryParameters['edit'][$shortcut['table']]);
+                               if ($queryParameters['edit'][$shortcut['table']][$shortcut['recordid']] === 'edit') {
+                                       $shortcut['type'] = 'edit';
+                               } elseif ($queryParameters['edit'][$shortcut['table']][$shortcut['recordid']] === 'new') {
+                                       $shortcut['type'] = 'new';
+                               }
+                               if (substr($shortcut['recordid'], -1) === ',') {
+                                       $shortcut['recordid'] = substr($shortcut['recordid'], 0, -1);
+                               }
+                       } else {
+                               $shortcut['type'] = 'other';
+                       }
+                       // 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'])) {
+                                       // 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)) {
+                                               continue;
+                                       }
+                                       // Check for record access
+                                       $pageRow = BackendUtility::getRecord('pages', $pageId);
+                                       if (!$GLOBALS['BE_USER']->doesUserHaveAccess($pageRow, ($perms = 1))) {
+                                               continue;
+                                       }
+                               }
+                       }
+                       $moduleParts = explode('_', $moduleName);
+                       $shortcutGroup = (int)$row['sc_group'];
+                       if ($shortcutGroup && $lastGroup !== $shortcutGroup && $shortcutGroup !== self::SUPERGLOBAL_GROUP) {
+                               $shortcut['groupLabel'] = $this->getShortcutGroupLabel($shortcutGroup);
+                       }
+                       $lastGroup = $shortcutGroup;
+
+                       if ($row['description']) {
+                               $shortcut['label'] = $row['description'];
+                       } else {
+                               $shortcut['label'] = GeneralUtility::fixed_lgd_cs(rawurldecode($queryParts['query']), 150);
+                       }
+                       $shortcut['group'] = $shortcutGroup;
+                       $shortcut['icon'] = $this->getShortcutIcon($row, $shortcut);
+                       $shortcut['iconTitle'] = $this->getShortcutIconTitle($shortcut['label'], $row['module_name'], $row['M_module_name']);
+                       $shortcut['action'] = 'jump(unescape(\'' . rawurlencode($this->getTokenUrl($row['url'])) . '\'),\'' . $moduleName . '\',\'' . $moduleParts[0] . '\', ' . (int)$pageId . ');';
+
+                       $shortcuts[] = $shortcut;
+               }
+               return $shortcuts;
+       }
+
+       /**
+        * Adds the correct token, if the url is a mod.php script
+        *
+        * @param string $url
+        * @return string
+        */
+       protected function getTokenUrl($url) {
+               $parsedUrl = parse_url($url);
+               parse_str($parsedUrl['query'], $parameters);
+
+               // parse the returnUrl and replace the module token of it
+               if (isset($parameters['returnUrl'])) {
+                       $parsedReturnUrl = parse_url($parameters['returnUrl']);
+                       parse_str($parsedReturnUrl['query'], $returnUrlParameters);
+                       if (strpos($parsedReturnUrl['path'], 'mod.php') !== FALSE && isset($returnUrlParameters['M'])) {
+                               $module = $returnUrlParameters['M'];
+                               $returnUrl = BackendUtility::getModuleUrl($module, $returnUrlParameters);
+                               $parameters['returnUrl'] = $returnUrl;
+                               $url = $parsedUrl['path'] . '?' . http_build_query($parameters);
+                       }
+               }
+
+               if (strpos($parsedUrl['path'], 'mod.php') !== FALSE && isset($parameters['M'])) {
+                       $module = $parameters['M'];
+                       $url = str_replace('mod.php', '', $parsedUrl['path']) . BackendUtility::getModuleUrl($module, $parameters);
+               }
+               return $url;
+       }
+
+       /**
+        * Gets shortcuts for a specific group
+        *
+        * @param int $groupId Group Id
+        * @return array Array of shortcuts that matched the group
+        */
+       protected function getShortcutsByGroup($groupId) {
+               $shortcuts = array();
+               foreach ($this->shortcuts as $shortcut) {
+                       if ($shortcut['group'] == $groupId) {
+                               $shortcuts[] = $shortcut;
+                       }
+               }
+               return $shortcuts;
+       }
+
+       /**
+        * Gets a shortcut by its uid
+        *
+        * @param int $shortcutId Shortcut id to get the complete shortcut for
+        * @return mixed An array containing the shortcut's data on success or FALSE on failure
+        */
+       protected function getShortcutById($shortcutId) {
+               $returnShortcut = FALSE;
+               foreach ($this->shortcuts as $shortcut) {
+                       if ($shortcut['raw']['uid'] == (int)$shortcutId) {
+                               $returnShortcut = $shortcut;
+                               continue;
+                       }
+               }
+               return $returnShortcut;
+       }
+
+       /**
+        * Gets the available shortcut groups from default groups, user TSConfig, and global groups
+        *
+        * @return array
+        */
+       protected function initShortcutGroups() {
+               // Groups from TSConfig
+               $bookmarkGroups = $GLOBALS['BE_USER']->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()) {
+                                       unset($this->shortcutGroups[$groupId]);
+                               }
+                       }
+               }
+               // Generate global groups, all global groups have negative IDs.
+               if (count($this->shortcutGroups)) {
+                       $groups = $this->shortcutGroups;
+                       foreach ($groups as $groupId => $groupLabel) {
+                               $this->shortcutGroups[$groupId * -1] = $groupLabel;
+                       }
+               }
+               // Group -100 is kind of superglobal and can't be changed.
+               $this->shortcutGroups[self::SUPERGLOBAL_GROUP] = 1;
+               // Add labels
+               foreach ($this->shortcutGroups as $groupId => $groupLabel) {
+                       $groupId = (int)$groupId;
+                       $label = $groupLabel;
+                       if ($groupLabel == '1') {
+                               $label = $GLOBALS['LANG']->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);
+                               }
+                       }
+                       if ($groupId < 0) {
+                               // Global group
+                               $label = $GLOBALS['LANG']->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);
+                               }
+                       }
+                       $this->shortcutGroups[$groupId] = $label;
+               }
+               return $this->shortcutGroups;
+       }
+
+       /**
+        * gets the available shortcut groups, renders a form so it can be saved lateron
+        *
+        * @param array $params Array of parameters from the AJAX interface, currently unused
+        * @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) {
+               $selectedShortcutId = (int)GeneralUtility::_GP('shortcutId');
+               $selectedShortcutGroupId = (int)GeneralUtility::_GP('shortcutGroup');
+               $selectedShortcut = $this->getShortcutById($selectedShortcutId);
+
+               $shortcutGroups = $this->shortcutGroups;
+               if (!$GLOBALS['BE_USER']->isAdmin()) {
+                       foreach ($shortcutGroups as $groupId => $groupName) {
+                               if ((int)$groupId < 0) {
+                                       unset($shortcutGroups[$groupId]);
+                               }
+                       }
+               }
+
+               // build the form
+               $content = '<form class="shortcut-form">' .
+                       '<input type="text" name="shortcut-title" value="' . htmlspecialchars($selectedShortcut['label']) . '">';
+
+               $content .= '<select name="shortcut-group">';
+               foreach ($shortcutGroups as $shortcutGroupId => $shortcutGroupTitle) {
+                       $content .= '<option value="' . (int)$shortcutGroupId . '"' . ($selectedShortcutGroupId == $shortcutGroupId ? ' selected="selected"' : '') . '>' . htmlspecialchars($shortcutGroupTitle) . '</option>';
+               }
+               $content .= '</select><input type="button" class="shortcut-form-save" value="Save"><input type="button" class="shortcut-form-cancel" value="Cancel"></form>';
+
+               $ajaxObj->addContent('data', $content);
+       }
+
+       /**
+        * Deletes a shortcut through an AJAX call
+        *
+        * @param array $params Array of parameters from the AJAX interface, currently unused
+        * @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) {
+               $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) {
+                               $ajaxReturn = 'deleted';
+                       }
+               }
+               $ajaxObj->addContent('delete', $ajaxReturn);
+       }
+
+       /**
+        * Creates a shortcut through an AJAX call
+        *
+        * @param array $params Array of parameters from the AJAX interface, currently unused
+        * @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) {
+               $shortcutCreated = 'failed';
+               // Default name
+               $shortcutName = 'Shortcut';
+               $shortcutNamePrepend = '';
+               $url = GeneralUtility::_POST('url');
+               $module = GeneralUtility::_POST('module');
+               $motherModule = GeneralUtility::_POST('motherModName');
+               // Determine shortcut type
+               $url = rawurldecode($url);
+               $queryParts = parse_url($url);
+               $queryParameters = GeneralUtility::explodeUrl2Array($queryParts['query'], 1);
+               // Proceed only if no scheme is defined, as URL is expected to be relative
+               if (empty($queryParts['scheme'])) {
+                       if (is_array($queryParameters['edit'])) {
+                               $shortcut['table'] = key($queryParameters['edit']);
+                               $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);
+                               } elseif ($queryParameters['edit'][$shortcut['table']][$shortcut['recordid']] == 'new') {
+                                       $shortcut['type'] = 'new';
+                                       $shortcutNamePrepend = $GLOBALS['LANG']->getLL('shortcut_create', 1);
+                               }
+                       } else {
+                               $shortcut['type'] = 'other';
+                       }
+                       // Lookup the title of this page and use it as default description
+                       $pageId = $shortcut['recordid'] ? $shortcut['recordid'] : $this->getLinkedPageId($url);
+                       if (MathUtility::canBeInterpretedAsInteger($pageId)) {
+                               $page = BackendUtility::getRecord('pages', $pageId);
+                               if (count($page)) {
+                                       // Set the name to the title of the page
+                                       if ($shortcut['type'] == 'other') {
+                                               $shortcutName = $page['title'];
+                                       } else {
+                                               $shortcutName = $shortcutNamePrepend . ' ' . $GLOBALS['LANG']->sL($GLOBALS['TCA'][$shortcut['table']]['ctrl']['title']) . ' (' . $page['title'] . ')';
+                                       }
+                               }
+                       } else {
+                               $dirName = urldecode($pageId);
+                               if (preg_match('/\\/$/', $dirName)) {
+                                       // If $pageId is a string and ends with a slash,
+                                       // assume it is a fileadmin reference and set
+                                       // the description to the basename of that path
+                                       $shortcutName .= ' ' . basename($dirName);
+                               }
+                       }
+                       // adding the shortcut
+                       if ($module && $url) {
+                               $fieldValues = array(
+                                       'userid' => $GLOBALS['BE_USER']->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) {
+                                       $shortcutCreated = 'success';
+                               }
+                       }
+                       $ajaxObj->addContent('create', $shortcutCreated);
+               }
+       }
+
+       /**
+        * Gets called when a shortcut is changed, checks whether the user has
+        * permissions to do so and saves the changes if everything is ok
+        *
+        * @param array $params Array of parameters from the AJAX interface, currently unused
+        * @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) {
+               $shortcutId = (int)GeneralUtility::_POST('shortcutId');
+               $shortcutName = strip_tags(GeneralUtility::_POST('shortcutTitle'));
+               $shortcutGroupId = (int)GeneralUtility::_POST('shortcutGroup');
+               if ($shortcutGroupId > 0 || $GLOBALS['BE_USER']->isAdmin()) {
+                       // Users can delete only their own shortcuts (except admins)
+                       $addUserWhere = !$GLOBALS['BE_USER']->isAdmin() ? ' AND userid=' . (int)$GLOBALS['BE_USER']->user['uid'] : '';
+                       $fieldValues = array(
+                               'description' => $shortcutName,
+                               'sc_group' => $shortcutGroupId
+                       );
+                       if ($fieldValues['sc_group'] < 0 && !$GLOBALS['BE_USER']->isAdmin()) {
+                               $fieldValues['sc_group'] = 0;
+                       }
+                       $GLOBALS['TYPO3_DB']->exec_UPDATEquery('sys_be_shortcuts', 'uid=' . $shortcutId . $addUserWhere, $fieldValues);
+                       $affectedRows = $GLOBALS['TYPO3_DB']->sql_affected_rows();
+                       if ($affectedRows == 1) {
+                               $ajaxObj->addContent('shortcut', $shortcutName);
+                       } else {
+                               $ajaxObj->addContent('shortcut', 'failed');
+                       }
+               }
+               $ajaxObj->setContentFormat('plain');
+       }
+
+       /**
+        * Gets the label for a shortcut group
+        *
+        * @param int $groupId A shortcut group id
+        * @return string The shortcut group label, can be an empty string if no group was found for the id
+        */
+       protected function getShortcutGroupLabel($groupId) {
+               return isset($this->shortcutGroups[$groupId]) ? $this->shortcutGroups[$groupId] : '';
+       }
+
+       /**
+        * Gets a list of global groups, shortcuts in these groups are available to all users
+        *
+        * @return array Array of global groups
+        */
+       protected function getGlobalShortcutGroups() {
+               $globalGroups = array();
+               foreach ($this->shortcutGroups as $groupId => $groupLabel) {
+                       if ($groupId < 0) {
+                               $globalGroups[$groupId] = $groupLabel;
+                       }
+               }
+               return $globalGroups;
+       }
+
+       /**
+        * runs through the available shortcuts an collects their groups
+        *
+        * @return array Array of groups which have shortcuts
+        */
+       protected function getGroupsFromShortcuts() {
+               $groups = array();
+               foreach ($this->shortcuts as $shortcut) {
+                       $groups[$shortcut['group']] = $this->shortcutGroups[$shortcut['group']];
+               }
+               return array_unique($groups);
+       }
+
+       /**
+        * Gets the icon for the shortcut
+        *
+        * @param array $row
+        * @param array $shortcut
+        * @return string Shortcut icon as img tag
+        */
+       protected function getShortcutIcon($row, $shortcut) {
+               switch ($row['module_name']) {
+                       case 'xMOD_alt_doc.php':
+                               $table = $shortcut['table'];
+                               $recordid = $shortcut['recordid'];
+                               $icon = '';
+                               if ($shortcut['type'] == 'edit') {
+                                       // Creating the list of fields to include in the SQL query:
+                                       $selectFields = $this->fieldArray;
+                                       $selectFields[] = 'uid';
+                                       $selectFields[] = 'pid';
+                                       if ($table == 'pages') {
+                                               $selectFields[] = 'module';
+                                               $selectFields[] = 'extendToSubpages';
+                                               $selectFields[] = 'doktype';
+                                       }
+                                       if (is_array($GLOBALS['TCA'][$table]['ctrl']['enablecolumns'])) {
+                                               $selectFields = array_merge($selectFields, $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']);
+                                       }
+                                       if ($GLOBALS['TCA'][$table]['ctrl']['type']) {
+                                               $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['type'];
+                                       }
+                                       if ($GLOBALS['TCA'][$table]['ctrl']['typeicon_column']) {
+                                               $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['typeicon_column'];
+                                       }
+                                       if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
+                                               $selectFields[] = 't3ver_state';
+                                       }
+                                       // Unique list!
+                                       $selectFields = array_unique($selectFields);
+                                       $permissionClause = $table === 'pages' && $this->perms_clause ? ' AND ' . $this->perms_clause : '';
+                                       $sqlQueryParts = array(
+                                               'SELECT' => implode(',', $selectFields),
+                                               '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);
+                               } elseif ($shortcut['type'] == 'new') {
+                                       $icon = IconUtility::getIcon($table, array(), $this->backPath);
+                               }
+                               $icon = IconUtility::skinImg($this->backPath, $icon, '', 1);
+                               break;
+                       case 'file_edit':
+                               $icon = 'gfx/edit_file.gif';
+                               break;
+                       case 'wizard_rte':
+                               $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'];
+                                       // 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)) {
+                                               $icon = '../' . \TYPO3\CMS\Core\Utility\PathUtility::stripPathSitePrefix($icon);
+                                       }
+                               } else {
+                                       $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) . '" />';
+       }
+
+       /**
+        * Returns title for the shortcut icon
+        *
+        * @param string $shortcutLabel Shortcut label
+        * @param string $moduleName Backend module name (key)
+        * @param string $parentModuleName Parent module label
+        * @return string Title for the shortcut icon
+        */
+       protected function getShortcutIconTitle($shortcutLabel, $moduleName, $parentModuleName = '') {
+               $title = '';
+               if (substr($moduleName, 0, 5) == 'xMOD_') {
+                       $title = substr($moduleName, 5);
+               } else {
+                       $splitModuleName = explode('_', $moduleName);
+                       $title = $GLOBALS['LANG']->moduleLabels['tabs'][$splitModuleName[0] . '_tab'];
+                       if (count($splitModuleName) > 1) {
+                               $title .= '>' . $GLOBALS['LANG']->moduleLabels['tabs'][($moduleName . '_tab')];
+                       }
+               }
+               if ($parentModuleName) {
+                       $title .= ' (' . $parentModuleName . ')';
+               }
+               $title .= ': ' . $shortcutLabel;
+               return $title;
+       }
+
+       /**
+        * Return the ID of the page in the URL if found.
+        *
+        * @param string $url The URL of the current shortcut link
+        * @return string If a page ID was found, it is returned. Otherwise: 0
+        */
+       protected function getLinkedPageId($url) {
+               return preg_replace('/.*[\\?&]id=([^&]+).*/', '$1', $url);
+       }
+
+       /**
+        * Position relative to others, live search should be very right
+        *
+        * @return int
+        */
+       public function getIndex() {
+               return 20;
+       }
+
+}
diff --git a/typo3/sysext/backend/Classes/Backend/ToolbarItems/UserToolbarItem.php b/typo3/sysext/backend/Classes/Backend/ToolbarItems/UserToolbarItem.php
new file mode 100644 (file)
index 0000000..ac9c013
--- /dev/null
@@ -0,0 +1,147 @@
+<?php
+namespace TYPO3\CMS\Backend\Backend\ToolbarItems;
+
+/**
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
+
+/**
+ * User toobar item
+ */
+class UserToolbarItem implements ToolbarItemInterface {
+
+       /**
+        * Constructor
+        *
+        * @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
+        */
+       public function checkAccess() {
+               return TRUE;
+       }
+
+       /**
+        * Creates the selector for workspaces
+        *
+        * @return string Workspace selector as HTML select
+        */
+       public function render() {
+               $icon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('status-user-' . ($GLOBALS['BE_USER']->isAdmin() ? 'admin' : 'backend'));
+
+               $realName = $GLOBALS['BE_USER']->user['realName'];
+               $username = $GLOBALS['BE_USER']->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);
+               }
+
+
+               $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[] = '<ul class="dropdown-menu" role="menu">';
+
+               /** @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 */
+               $userModuleMenu = $backendModuleRepository->findByModuleName('user');
+               if ($userModuleMenu != FALSE && $userModuleMenu->getChildren()->count() > 0) {
+                       foreach ($userModuleMenu->getChildren() as $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>';
+                       }
+                       $html[] = '<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>';
+
+               $html[] = '</ul>';
+
+               return implode(LF, $html);
+       }
+
+       /**
+        * 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() {
+               if ($GLOBALS['BE_USER']->user['ses_backuserid']) {
+                       return 'su-user';
+               }
+       }
+
+       /**
+        * Return attribute id name
+        *
+        * @return string The name of the ID attribute
+        */
+       public function getIdAttribute() {
+               return 'topbar-user-menu';
+       }
+
+       /**
+        * Returns extra classes
+        *
+        * @return array
+        */
+       public function getExtraClasses() {
+               return array();
+       }
+
+       /**
+        * Get dropdown
+        *
+        * @return bool
+        */
+       public function getDropdown() {
+               return TRUE;
+       }
+
+       /**
+        * Position relative to others
+        *
+        * @return int
+        */
+       public function getIndex() {
+               return 80;
+       }
+
+}
index 6abeeec..a1fd5bc 100644 (file)
@@ -38,7 +38,7 @@ class BackendController {
        /**
         * @var array
         */
-       protected $cssFiles;
+       protected $cssFiles = array();
 
        /**
         * @var string
@@ -53,7 +53,7 @@ class BackendController {
        /**
         * @var array
         */
-       protected $toolbarItems;
+       protected $toolbarItems = array();
 
        /**
         * @var int Intentionally private as nobody should modify defaults
@@ -143,9 +143,7 @@ class BackendController {
                $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Toolbar/UserMenu');
 
                $this->css = '';
-               $this->cssFiles = array();
-               $this->toolbarItems = array();
-               $this->initializeCoreToolbarItems();
+               $this->initializeToolbarItems();
                $this->menuWidth = $this->menuWidthDefault;
                if (isset($GLOBALS['TBE_STYLES']['dims']['leftMenuFrameW']) && (int)$GLOBALS['TBE_STYLES']['dims']['leftMenuFrameW'] != (int)$this->menuWidth) {
                        $this->menuWidth = (int)$GLOBALS['TBE_STYLES']['dims']['leftMenuFrameW'];
@@ -154,28 +152,38 @@ class BackendController {
        }
 
        /**
-        * Initializes the core toolbar items
+        * Initialize toolbar item objects
         *
+        * @throws \RuntimeException
         * @return void
         */
-       protected function initializeCoreToolbarItems() {
-               $coreToolbarItems = array(
-                       'shortcuts' => 'TYPO3\\CMS\\Backend\\Toolbar\\ShortcutToolbarItem',
-                       'clearCacheActions' => 'TYPO3\\CMS\\Backend\\Toolbar\\ClearCacheToolbarItem',
-                       'liveSearch' => 'TYPO3\\CMS\\Backend\\Toolbar\\LiveSearchToolbarItem'
-               );
-               foreach ($coreToolbarItems as $toolbarItemName => $toolbarItemClassName) {
-                       $toolbarItem = GeneralUtility::makeInstance($toolbarItemClassName, $this);
-                       // @TODO: Should throw as soon as "loading by convention" is implemented
-                       if (!$toolbarItem instanceof \TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface) {
-                               continue;
+       protected function initializeToolbarItems() {
+               $toolbarItemInstances = array();
+               $classNameRegistry = $GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'];
+               foreach ($classNameRegistry as $className) {
+                       $toolbarItemInstance = GeneralUtility::makeInstance($className, $this);
+                       if (!$toolbarItemInstance instanceof \TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface) {
+                               throw new \RuntimeException(
+                                       'class ' . $className . ' is registered as toolbar item but does not implement'
+                                               . '\TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface',
+                                       1415958218
+                               );
                        }
-                       if ($toolbarItem->checkAccess()) {
-                               $this->toolbarItems[$toolbarItemName] = $toolbarItem;
-                       } else {
-                               unset($toolbarItem);
+                       $index = (int)$toolbarItemInstance->getIndex();
+                       if ($index < 0 || $index > 100) {
+                               throw new \RuntimeException(
+                                       'getIndex() must return an integer between 0 and 100',
+                                       1415968498
+                               );
+                       }
+                       while(array_key_exists($index, $toolbarItemInstances)) {
+                               $index++;
                        }
+                       // Find next free position in
+                       $toolbarItemInstances[$index] = $toolbarItemInstance;
                }
+               ksort($toolbarItemInstances);
+               $this->toolbarItems = $toolbarItemInstances;
        }
 
        /**
@@ -311,15 +319,8 @@ class BackendController {
         * @return string top toolbar elements as HTML
         */
        protected function renderToolbar() {
-               // Move search to last position
-               if (array_key_exists('liveSearch', $this->toolbarItems)) {
-                       $search = $this->toolbarItems['liveSearch'];
-                       unset($this->toolbarItems['liveSearch']);
-               }
-
                $toolbar = '';
-
-               foreach ($this->toolbarItems as $key => $toolbarItem) {
+               foreach ($this->toolbarItems as $toolbarItem) {
                        $menu = $toolbarItem->render();
                        if ($menu) {
                                // @TODO: Should throw as soon as "loading by convention" is implemented
@@ -337,65 +338,10 @@ class BackendController {
                                }
                        }
                }
-
-               $toolbar .= $this->renderUserToolbar();
-
-               if ($search) {
-                       $toolbar .= '<li ' . $search->getAdditionalAttributes() . ' role="menu">' . $search->render() . '</li>';
-               }
                return $toolbar;
        }
 
        /**
-        * Gets the label of the BE user currently logged in
-        *
-        * @return string Html code snippet displaying the currently logged in user
-        */
-       protected function renderUserToolbar() {
-               $css = 'dropdown';
-               $icon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('status-user-' . ($GLOBALS['BE_USER']->isAdmin() ? 'admin' : 'backend'));
-               $realName = $GLOBALS['BE_USER']->user['realName'];
-               $username = $GLOBALS['BE_USER']->user['username'];
-               $label = $realName ?: $username;
-               $title = $username;
-
-               // Superuser mode
-               if ($GLOBALS['BE_USER']->user['ses_backuserid']) {
-                       $css .= ' su-user';
-                       $title = $GLOBALS['LANG']->getLL('switchtouser') . ': ' . $username;
-                       $label = $GLOBALS['LANG']->getLL('switchtousershort') . ' ' . ($realName ? $realName . ' (' . $username . ')' : $username);
-               }
-
-               $toolbar = '<ul class="dropdown-menu" role="menu">';
-
-               /** @var \TYPO3\CMS\Backend\Domain\Model\Module\BackendModule $userModuleMenu */
-               $userModuleMenu = $this->backendModuleRepository->findByModuleName('user');
-               if ($userModuleMenu != FALSE && $userModuleMenu->getChildren()->count() > 0) {
-                       foreach ($userModuleMenu->getChildren() as $key => $module) {
-                               $moduleIcon = $module->getIcon();
-                               $toolbar .= '
-                                       <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>';
-                       }
-                       $toolbar .= '<li class="divider"></li>';
-               }
-
-               $toolbar .= '<li>' . $this->renderLogoutButton() . '</li>';
-               $toolbar .= '</ul>';
-
-               return '<li id="topbar-user-menu" class="' . $css . '" role="menu">' .
-                       '<a href="#" class="dropdown-toggle" data-toggle="dropdown">' .
-                       $icon . '<span title="' . htmlspecialchars($title) . '">' . htmlspecialchars($label) . ' <span class="caret"></span></span>' .
-                       '</a>' .
-                       $toolbar .
-               '</li>';
-       }
-
-       /**
         * Returns the file name  to the LLL JavaScript, containing the localized labels,
         * which can be used in JavaScript code.
         *
@@ -749,18 +695,10 @@ class BackendController {
         * @param string $toolbarItemClassName Toolbar item class name, f.e. tx_toolbarExtension_coolItem
         * @return void
         * @throws \UnexpectedValueException
+        * @deprecated since CMS 7, will be removed with CMS 8. Toolbar items are registered in $GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'] now.
         */
        public function addToolbarItem($toolbarItemName, $toolbarItemClassName) {
-               $toolbarItem = GeneralUtility::makeInstance($toolbarItemClassName, $this);
-               if (!$toolbarItem instanceof \TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface) {
-                       // @TODO: Should throw as soon as "loading by convention" is implemented
-                       return;
-               }
-               if ($toolbarItem->checkAccess()) {
-                       $this->toolbarItems[$toolbarItemName] = $toolbarItem;
-               } else {
-                       unset($toolbarItem);
-               }
+               GeneralUtility::logDeprecatedFunction();
        }
 
        /**
@@ -785,17 +723,6 @@ class BackendController {
        }
 
        /**
-        * Renders the logout button form
-        *
-        * @return string Html code snippet displaying the logout button
-        */
-       protected function renderLogoutButton() {
-               // show logout or "exit" (from switch user mode) label
-               $buttonLabel = 'LLL:EXT:lang/locallang_core.xlf:' . ($GLOBALS['BE_USER']->user['ses_backuserid'] ? 'buttons.exit' : 'buttons.logout');
-               return '<a href="logout.php" target="_top">' . $GLOBALS['LANG']->sL($buttonLabel, TRUE) . '</a>';
-       }
-
-       /**
         * loads all modules from the repository
         * and renders it with a template
         *
diff --git a/typo3/sysext/backend/Classes/Toolbar/ClearCacheToolbarItem.php b/typo3/sysext/backend/Classes/Toolbar/ClearCacheToolbarItem.php
deleted file mode 100644 (file)
index fe12f85..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-<?php
-namespace TYPO3\CMS\Backend\Toolbar;
-
-/**
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\CMS\Backend\Utility\BackendUtility;
-use TYPO3\CMS\Backend\Utility\IconUtility;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-
-/**
- * class to render the menu for the cache clearing actions
- *
- * @author Ingo Renner <ingo@typo3.org>
- */
-class ClearCacheToolbarItem implements ToolbarItemInterface {
-
-       /**
-        * @var array
-        */
-       protected $cacheActions;
-
-       /**
-        * @var array
-        */
-       protected $optionValues;
-
-       /**
-        * @var \TYPO3\CMS\Backend\Controller\BackendController
-        */
-       protected $backendReference;
-
-       /**
-        * TODO potentially unused
-        * @var string
-        */
-       public $backPath = '';
-
-       /**
-        * 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();
-               $backendUser = $this->getBackendUser();
-
-               // 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'),
-                               'icon' => IconUtility::getSpriteIcon('actions-system-cache-clear-impact-low')
-                       );
-                       $this->optionValues[] = 'pages';
-               }
-
-               // Clear cache for ALL tables!
-               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'),
-                               'icon' => IconUtility::getSpriteIcon('actions-system-cache-clear-impact-medium')
-                       );
-                       $this->optionValues[] = 'all';
-               }
-
-               // Clearing of system cache (core cache, class cache etc)
-               // is only shown explicitly if activated for a BE-user (not activated for admins by default)
-               // or if the system runs in development mode
-               // or if $GLOBALS['TYPO3_CONF_VARS']['SYS']['clearCacheSystem'] is set (only for admins)
-               if ($backendUser->getTSConfigVal('options.clearCache.system') || GeneralUtility::getApplicationContext()->isDevelopment()
-                       || ((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'),
-                               '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) {
-                                       throw new \UnexpectedValueException('$hookObject must implement interface TYPO3\\CMS\\Backend\\Toolbar\\ClearCacheActionsHookInterface', 1228262000);
-                               }
-                               $hookObject->manipulateCacheActions($this->cacheActions, $this->optionValues);
-                       }
-               }
-       }
-
-       /**
-        * Checks whether the user has access to this toolbar item
-        *
-        * @return bool TRUE if user has access, FALSE if not
-        */
-       public function checkAccess() {
-               $backendUser = $this->getBackendUser();
-               if ($backendUser->isAdmin()) {
-                       return TRUE;
-               }
-               if (is_array($this->optionValues)) {
-                       foreach ($this->optionValues as $value) {
-                               if ($backendUser->getTSConfigVal('options.clearCache.' . $value)) {
-                                       return TRUE;
-                               }
-                       }
-               }
-               return FALSE;
-       }
-
-       /**
-        * Creates the selector for workspaces
-        *
-        * @return string Workspace selector as HTML select
-        */
-       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 $actionKey => $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);
-       }
-
-       /**
-        * Adds the necessary JavaScript to the backend
-        *
-        * @return void
-        */
-       protected function addJavascriptToBackend() {
-               $this->backendReference->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Toolbar/ClearCacheMenu');
-       }
-
-       /**
-        * 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 'clear-cache-actions-menu';
-       }
-
-       /**
-        * Returns extra classes
-        *
-        * @return array
-        */
-       public function getExtraClasses() {
-               return array();
-       }
-
-       /**
-        * Get dropdown
-        *
-        * @return bool
-        */
-       public function getDropdown() {
-               return TRUE;
-       }
-
-       /**
-        * Returns the current BE user.
-        *
-        * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
-        */
-       protected function getBackendUser() {
-               return $GLOBALS['BE_USER'];
-       }
-
-}
diff --git a/typo3/sysext/backend/Classes/Toolbar/LiveSearchToolbarItem.php b/typo3/sysext/backend/Classes/Toolbar/LiveSearchToolbarItem.php
deleted file mode 100644 (file)
index c6075b0..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-<?php
-namespace TYPO3\CMS\Backend\Toolbar;
-
-/**
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-/**
- * Adds backend live search to the toolbar
- *
- * @author Michael Klapper <michael.klapper@aoemedia.de>
- * @author Jeff Segars <jeff@webempoweredchurch.org>
- */
-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;
-       }
-
-       /**
-        * Checks whether the user has access to this toolbar item
-        *
-        * @return bool TRUE if user has access, FALSE if not
-        */
-       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->observeWorkspaces = TRUE;
-               $loadModules->load($GLOBALS['TBE_MODULES']);
-               // Live search is heavily dependent on the list module and only available when that module is.
-               if (is_array($loadModules->modules['web']['sub']['list'])) {
-                       $access = TRUE;
-               }
-               return $access;
-       }
-
-       /**
-        * Creates the selector for workspaces
-        *
-        * @return string Workspace selector as HTML select
-        */
-       public function render() {
-               $this->backendReference->addJavascriptFile('sysext/backend/Resources/Public/JavaScript/livesearch.js');
-
-               return '
-                       <form class="navbar-form" role="search">
-                               <div class="live-search-wrapper">
-                                       <div class="form-group">
-                                               <input type="text" class="form-control" placeholder="Search" id="live-search-box">
-                                       </div>
-                               </div>
-                       </form>
-               ';
-       }
-
-       /**
-        * 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 'live-search-menu';
-       }
-
-       /**
-        * Returns extra classes
-        *
-        * @return array
-        */
-       public function getExtraClasses() {
-               return array();
-       }
-
-       /**
-        * Get dropdown
-        *
-        * @return bool
-        */
-       public function getDropdown() {
-               return FALSE;
-       }
-
-}
diff --git a/typo3/sysext/backend/Classes/Toolbar/ShortcutToolbarItem.php b/typo3/sysext/backend/Classes/Toolbar/ShortcutToolbarItem.php
deleted file mode 100644 (file)
index 13efcdb..0000000
+++ /dev/null
@@ -1,745 +0,0 @@
-<?php
-namespace TYPO3\CMS\Backend\Toolbar;
-
-/**
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\CMS\Backend\Utility\BackendUtility;
-use TYPO3\CMS\Backend\Utility\IconUtility;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Core\Utility\MathUtility;
-
-/**
- * Class to render the shortcut menu
- *
- * @author Ingo Renner <ingo@typo3.org>
- */
-class ShortcutToolbarItem implements ToolbarItemInterface {
-
-       const SUPERGLOBAL_GROUP = -100;
-
-       /**
-        * @var string
-        */
-       public $perms_clause;
-
-       /**
-        * @var string
-        */
-       public $backPath;
-
-       /**
-        * @var array
-        */
-       public $fieldArray;
-
-       /**
-        * All available shortcuts
-        *
-        * @var array
-        */
-       protected $shortcuts;
-
-       /**
-        * @var array
-        */
-       protected $shortcutGroups;
-
-       /**
-        * Labels of all groups.
-        * If value is 1, the system will try to find a label in the locallang array.
-        *
-        * @var array
-        */
-       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) {
-               if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX) {
-                       $GLOBALS['LANG']->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->load($GLOBALS['TBE_MODULES']);
-               }
-               $this->backendReference = $backendReference;
-               $this->shortcuts = array();
-               // By default, 5 groups are set
-               $this->shortcutGroups = array(
-                       1 => '1',
-                       2 => '1',
-                       3 => '1',
-                       4 => '1',
-                       5 => '1'
-               );
-               $this->shortcutGroups = $this->initShortcutGroups();
-               $this->shortcuts = $this->initShortcuts();
-       }
-
-       /**
-        * Checks whether the user has access to this toolbar item
-        *
-        * @return bool TRUE if user has access, FALSE if not
-        */
-       public function checkAccess() {
-               return (bool)$GLOBALS['BE_USER']->getTSConfigVal('options.enableBookmarks');
-       }
-
-       /**
-        * Creates the shortcut menu (default renderer)
-        *
-        * @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);
-       }
-
-       /**
-        * Renders the pure contents of the menu
-        *
-        * @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">';
-               // Render shortcuts with no group (group id = 0) first
-               $noGroupShortcuts = $this->getShortcutsByGroup(0);
-               foreach ($noGroupShortcuts as $shortcut) {
-                       $shortcutMenu[] = '
-                       <tr class="shortcut" data-shortcutid="' . $shortcut['raw']['uid'] . '">
-                               <td class="shortcut-icon">' . $shortcut['icon'] . '</td>
-                               <td class="shortcut-label">
-                                       <a href="#" onclick="' . $shortcut['action'] . '; return false;">' . htmlspecialchars($shortcut['label']) . '</a>
-                               </td>
-                               <td class="shortcut-edit">' . $editIcon . ' /></td>
-                               <td class="shortcut-delete">' . $deleteIcon . '</td>
-                       </tr>';
-               }
-               // Now render groups and the contained shortcuts
-               $groups = $this->getGroupsFromShortcuts();
-               krsort($groups, SORT_NUMERIC);
-               foreach ($groups as $groupId => $groupLabel) {
-                       if ($groupId != 0) {
-                               $shortcutGroup = '
-                               <tr class="shortcut-group" id="shortcut-group-' . $groupId . '">
-                                       <td class="shortcut-group-icon">' . $groupIcon . '</td>
-                                       <td class="shortcut-group-label">' . $groupLabel . '</td>
-                                       <td colspan="2">&nbsp;</td>
-                               </tr>';
-                               $shortcuts = $this->getShortcutsByGroup($groupId);
-                               $i = 0;
-                               foreach ($shortcuts as $shortcut) {
-                                       $i++;
-                                       $firstRow = '';
-                                       if ($i == 1) {
-                                               $firstRow = ' first-row';
-                                       }
-                                       $shortcutGroup .= '
-                                       <tr class="shortcut' . $firstRow . '" data-shortcutid="' . $shortcut['raw']['uid'] . '" data-shortcutgroup="' . $groupId . '">
-                                               <td class="shortcut-icon">' . $shortcut['icon'] . '</td>
-                                               <td class="shortcut-label">
-                                                       <a href="#" onclick="' . $shortcut['action'] . '; return false;">' . htmlspecialchars($shortcut['label']) . '</a>
-                                               </td>
-                                               <td class="shortcut-edit">' . $editIcon . ' /></td>
-                                               <td class="shortcut-delete">' . $deleteIcon . '</td>
-                                       </tr>';
-                               }
-                               $shortcutMenu[] = $shortcutGroup;
-                       }
-               }
-               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);
-                       $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'));
-                       $shortcutMenu[] = '<tr><td style="padding:1px 2px; color: #838383;">' . $label . '</td></tr>';
-               }
-               $shortcutMenu[] = '</table>';
-               $compiledShortcutMenu = implode(LF, $shortcutMenu);
-               return $compiledShortcutMenu;
-       }
-
-       /**
-        * Renders the menu so that it can be returned as response to an AJAX call
-        *
-        * @param array $params Array of parameters from the AJAX interface, currently unused
-        * @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();
-               $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
-        *
-        * @return array
-        */
-       public function getExtraClasses() {
-               return array();
-       }
-
-       /**
-        * Get dropdown
-        *
-        * @return bool
-        */
-       public function getDropdown() {
-               return TRUE;
-       }
-
-       /**
-        * Retrieves the shortcuts for the current user
-        *
-        * @return array Array of shortcuts
-        */
-       protected function initShortcuts() {
-               $globalGroupIdList = implode(',', array_keys($this->getGlobalShortcutGroups()));
-               $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
-                       '*',
-                       'sys_be_shortcuts',
-                       '(userid = ' . (int)$GLOBALS['BE_USER']->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)) {
-                       $shortcut = array('raw' => $row);
-
-                       list($row['module_name'], $row['M_module_name']) = explode('|', $row['module_name']);
-
-                       $queryParts = parse_url($row['url']);
-                       $queryParameters = GeneralUtility::explodeUrl2Array($queryParts['query'], 1);
-                       if ($row['module_name'] === 'xMOD_alt_doc.php' && is_array($queryParameters['edit'])) {
-                               $shortcut['table'] = key($queryParameters['edit']);
-                               $shortcut['recordid'] = key($queryParameters['edit'][$shortcut['table']]);
-                               if ($queryParameters['edit'][$shortcut['table']][$shortcut['recordid']] === 'edit') {
-                                       $shortcut['type'] = 'edit';
-                               } elseif ($queryParameters['edit'][$shortcut['table']][$shortcut['recordid']] === 'new') {
-                                       $shortcut['type'] = 'new';
-                               }
-                               if (substr($shortcut['recordid'], -1) === ',') {
-                                       $shortcut['recordid'] = substr($shortcut['recordid'], 0, -1);
-                               }
-                       } else {
-                               $shortcut['type'] = 'other';
-                       }
-                       // 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'])) {
-                                       // 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)) {
-                                               continue;
-                                       }
-                                       // Check for record access
-                                       $pageRow = BackendUtility::getRecord('pages', $pageId);
-                                       if (!$GLOBALS['BE_USER']->doesUserHaveAccess($pageRow, ($perms = 1))) {
-                                               continue;
-                                       }
-                               }
-                       }
-                       $moduleParts = explode('_', $moduleName);
-                       $shortcutGroup = (int)$row['sc_group'];
-                       if ($shortcutGroup && $lastGroup !== $shortcutGroup && $shortcutGroup !== self::SUPERGLOBAL_GROUP) {
-                               $shortcut['groupLabel'] = $this->getShortcutGroupLabel($shortcutGroup);
-                       }
-                       $lastGroup = $shortcutGroup;
-
-                       if ($row['description']) {
-                               $shortcut['label'] = $row['description'];
-                       } else {
-                               $shortcut['label'] = GeneralUtility::fixed_lgd_cs(rawurldecode($queryParts['query']), 150);
-                       }
-                       $shortcut['group'] = $shortcutGroup;
-                       $shortcut['icon'] = $this->getShortcutIcon($row, $shortcut);
-                       $shortcut['iconTitle'] = $this->getShortcutIconTitle($shortcut['label'], $row['module_name'], $row['M_module_name']);
-                       $shortcut['action'] = 'jump(unescape(\'' . rawurlencode($this->getTokenUrl($row['url'])) . '\'),\'' . $moduleName . '\',\'' . $moduleParts[0] . '\', ' . (int)$pageId . ');';
-
-                       $shortcuts[] = $shortcut;
-               }
-               return $shortcuts;
-       }
-
-       /**
-        * Adds the correct token, if the url is a mod.php script
-        *
-        * @param string $url
-        * @return string
-        */
-       protected function getTokenUrl($url) {
-               $parsedUrl = parse_url($url);
-               parse_str($parsedUrl['query'], $parameters);
-
-               // parse the returnUrl and replace the module token of it
-               if (isset($parameters['returnUrl'])) {
-                       $parsedReturnUrl = parse_url($parameters['returnUrl']);
-                       parse_str($parsedReturnUrl['query'], $returnUrlParameters);
-                       if (strpos($parsedReturnUrl['path'], 'mod.php') !== FALSE && isset($returnUrlParameters['M'])) {
-                               $module = $returnUrlParameters['M'];
-                               $returnUrl = BackendUtility::getModuleUrl($module, $returnUrlParameters);
-                               $parameters['returnUrl'] = $returnUrl;
-                               $url = $parsedUrl['path'] . '?' . http_build_query($parameters);
-                       }
-               }
-
-               if (strpos($parsedUrl['path'], 'mod.php') !== FALSE && isset($parameters['M'])) {
-                       $module = $parameters['M'];
-                       $url = str_replace('mod.php', '', $parsedUrl['path']) . BackendUtility::getModuleUrl($module, $parameters);
-               }
-               return $url;
-       }
-
-       /**
-        * Gets shortcuts for a specific group
-        *
-        * @param int $groupId Group Id
-        * @return array Array of shortcuts that matched the group
-        */
-       protected function getShortcutsByGroup($groupId) {
-               $shortcuts = array();
-               foreach ($this->shortcuts as $shortcut) {
-                       if ($shortcut['group'] == $groupId) {
-                               $shortcuts[] = $shortcut;
-                       }
-               }
-               return $shortcuts;
-       }
-
-       /**
-        * Gets a shortcut by its uid
-        *
-        * @param int $shortcutId Shortcut id to get the complete shortcut for
-        * @return mixed An array containing the shortcut's data on success or FALSE on failure
-        */
-       protected function getShortcutById($shortcutId) {
-               $returnShortcut = FALSE;
-               foreach ($this->shortcuts as $shortcut) {
-                       if ($shortcut['raw']['uid'] == (int)$shortcutId) {
-                               $returnShortcut = $shortcut;
-                               continue;
-                       }
-               }
-               return $returnShortcut;
-       }
-
-       /**
-        * Gets the available shortcut groups from default groups, user TSConfig, and global groups
-        *
-        * @return array
-        */
-       protected function initShortcutGroups() {
-               // Groups from TSConfig
-               $bookmarkGroups = $GLOBALS['BE_USER']->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()) {
-                                       unset($this->shortcutGroups[$groupId]);
-                               }
-                       }
-               }
-               // Generate global groups, all global groups have negative IDs.
-               if (count($this->shortcutGroups)) {
-                       $groups = $this->shortcutGroups;
-                       foreach ($groups as $groupId => $groupLabel) {
-                               $this->shortcutGroups[$groupId * -1] = $groupLabel;
-                       }
-               }
-               // Group -100 is kind of superglobal and can't be changed.
-               $this->shortcutGroups[self::SUPERGLOBAL_GROUP] = 1;
-               // Add labels
-               foreach ($this->shortcutGroups as $groupId => $groupLabel) {
-                       $groupId = (int)$groupId;
-                       $label = $groupLabel;
-                       if ($groupLabel == '1') {
-                               $label = $GLOBALS['LANG']->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);
-                               }
-                       }
-                       if ($groupId < 0) {
-                               // Global group
-                               $label = $GLOBALS['LANG']->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);
-                               }
-                       }
-                       $this->shortcutGroups[$groupId] = $label;
-               }
-               return $this->shortcutGroups;
-       }
-
-       /**
-        * gets the available shortcut groups, renders a form so it can be saved lateron
-        *
-        * @param array $params Array of parameters from the AJAX interface, currently unused
-        * @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) {
-               $selectedShortcutId = (int)GeneralUtility::_GP('shortcutId');
-               $selectedShortcutGroupId = (int)GeneralUtility::_GP('shortcutGroup');
-               $selectedShortcut = $this->getShortcutById($selectedShortcutId);
-
-               $shortcutGroups = $this->shortcutGroups;
-               if (!$GLOBALS['BE_USER']->isAdmin()) {
-                       foreach ($shortcutGroups as $groupId => $groupName) {
-                               if ((int)$groupId < 0) {
-                                       unset($shortcutGroups[$groupId]);
-                               }
-                       }
-               }
-
-               // build the form
-               $content = '<form class="shortcut-form">' .
-                       '<input type="text" name="shortcut-title" value="' . htmlspecialchars($selectedShortcut['label']) . '">';
-
-               $content .= '<select name="shortcut-group">';
-               foreach ($shortcutGroups as $shortcutGroupId => $shortcutGroupTitle) {
-                       $content .= '<option value="' . (int)$shortcutGroupId . '"' . ($selectedShortcutGroupId == $shortcutGroupId ? ' selected="selected"' : '') . '>' . htmlspecialchars($shortcutGroupTitle) . '</option>';
-               }
-               $content .= '</select><input type="button" class="shortcut-form-save" value="Save"><input type="button" class="shortcut-form-cancel" value="Cancel"></form>';
-
-               $ajaxObj->addContent('data', $content);
-       }
-
-       /**
-        * Deletes a shortcut through an AJAX call
-        *
-        * @param array $params Array of parameters from the AJAX interface, currently unused
-        * @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) {
-               $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) {
-                               $ajaxReturn = 'deleted';
-                       }
-               }
-               $ajaxObj->addContent('delete', $ajaxReturn);
-       }
-
-       /**
-        * Creates a shortcut through an AJAX call
-        *
-        * @param array $params Array of parameters from the AJAX interface, currently unused
-        * @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) {
-               $shortcutCreated = 'failed';
-               // Default name
-               $shortcutName = 'Shortcut';
-               $shortcutNamePrepend = '';
-               $url = GeneralUtility::_POST('url');
-               $module = GeneralUtility::_POST('module');
-               $motherModule = GeneralUtility::_POST('motherModName');
-               // Determine shortcut type
-               $url = rawurldecode($url);
-               $queryParts = parse_url($url);
-               $queryParameters = GeneralUtility::explodeUrl2Array($queryParts['query'], 1);
-               // Proceed only if no scheme is defined, as URL is expected to be relative
-               if (empty($queryParts['scheme'])) {
-                       if (is_array($queryParameters['edit'])) {
-                               $shortcut['table'] = key($queryParameters['edit']);
-                               $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);
-                               } elseif ($queryParameters['edit'][$shortcut['table']][$shortcut['recordid']] == 'new') {
-                                       $shortcut['type'] = 'new';
-                                       $shortcutNamePrepend = $GLOBALS['LANG']->getLL('shortcut_create', 1);
-                               }
-                       } else {
-                               $shortcut['type'] = 'other';
-                       }
-                       // Lookup the title of this page and use it as default description
-                       $pageId = $shortcut['recordid'] ? $shortcut['recordid'] : $this->getLinkedPageId($url);
-                       if (MathUtility::canBeInterpretedAsInteger($pageId)) {
-                               $page = BackendUtility::getRecord('pages', $pageId);
-                               if (count($page)) {
-                                       // Set the name to the title of the page
-                                       if ($shortcut['type'] == 'other') {
-                                               $shortcutName = $page['title'];
-                                       } else {
-                                               $shortcutName = $shortcutNamePrepend . ' ' . $GLOBALS['LANG']->sL($GLOBALS['TCA'][$shortcut['table']]['ctrl']['title']) . ' (' . $page['title'] . ')';
-                                       }
-                               }
-                       } else {
-                               $dirName = urldecode($pageId);
-                               if (preg_match('/\\/$/', $dirName)) {
-                                       // If $pageId is a string and ends with a slash,
-                                       // assume it is a fileadmin reference and set
-                                       // the description to the basename of that path
-                                       $shortcutName .= ' ' . basename($dirName);
-                               }
-                       }
-                       // adding the shortcut
-                       if ($module && $url) {
-                               $fieldValues = array(
-                                       'userid' => $GLOBALS['BE_USER']->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) {
-                                       $shortcutCreated = 'success';
-                               }
-                       }
-                       $ajaxObj->addContent('create', $shortcutCreated);
-               }
-       }
-
-       /**
-        * Gets called when a shortcut is changed, checks whether the user has
-        * permissions to do so and saves the changes if everything is ok
-        *
-        * @param array $params Array of parameters from the AJAX interface, currently unused
-        * @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) {
-               $shortcutId = (int)GeneralUtility::_POST('shortcutId');
-               $shortcutName = strip_tags(GeneralUtility::_POST('shortcutTitle'));
-               $shortcutGroupId = (int)GeneralUtility::_POST('shortcutGroup');
-               if ($shortcutGroupId > 0 || $GLOBALS['BE_USER']->isAdmin()) {
-                       // Users can delete only their own shortcuts (except admins)
-                       $addUserWhere = !$GLOBALS['BE_USER']->isAdmin() ? ' AND userid=' . (int)$GLOBALS['BE_USER']->user['uid'] : '';
-                       $fieldValues = array(
-                               'description' => $shortcutName,
-                               'sc_group' => $shortcutGroupId
-                       );
-                       if ($fieldValues['sc_group'] < 0 && !$GLOBALS['BE_USER']->isAdmin()) {
-                               $fieldValues['sc_group'] = 0;
-                       }
-                       $GLOBALS['TYPO3_DB']->exec_UPDATEquery('sys_be_shortcuts', 'uid=' . $shortcutId . $addUserWhere, $fieldValues);
-                       $affectedRows = $GLOBALS['TYPO3_DB']->sql_affected_rows();
-                       if ($affectedRows == 1) {
-                               $ajaxObj->addContent('shortcut', $shortcutName);
-                       } else {
-                               $ajaxObj->addContent('shortcut', 'failed');
-                       }
-               }
-               $ajaxObj->setContentFormat('plain');
-       }
-
-       /**
-        * Gets the label for a shortcut group
-        *
-        * @param int $groupId A shortcut group id
-        * @return string The shortcut group label, can be an empty string if no group was found for the id
-        */
-       protected function getShortcutGroupLabel($groupId) {
-               return isset($this->shortcutGroups[$groupId]) ? $this->shortcutGroups[$groupId] : '';
-       }
-
-       /**
-        * Gets a list of global groups, shortcuts in these groups are available to all users
-        *
-        * @return array Array of global groups
-        */
-       protected function getGlobalShortcutGroups() {
-               $globalGroups = array();
-               foreach ($this->shortcutGroups as $groupId => $groupLabel) {
-                       if ($groupId < 0) {
-                               $globalGroups[$groupId] = $groupLabel;
-                       }
-               }
-               return $globalGroups;
-       }
-
-       /**
-        * runs through the available shortcuts an collects their groups
-        *
-        * @return array Array of groups which have shortcuts
-        */
-       protected function getGroupsFromShortcuts() {
-               $groups = array();
-               foreach ($this->shortcuts as $shortcut) {
-                       $groups[$shortcut['group']] = $this->shortcutGroups[$shortcut['group']];
-               }
-               return array_unique($groups);
-       }
-
-       /**
-        * Gets the icon for the shortcut
-        *
-        * @param array $row
-        * @param array $shortcut
-        * @return string Shortcut icon as img tag
-        */
-       protected function getShortcutIcon($row, $shortcut) {
-               switch ($row['module_name']) {
-                       case 'xMOD_alt_doc.php':
-                               $table = $shortcut['table'];
-                               $recordid = $shortcut['recordid'];
-                               $icon = '';
-                               if ($shortcut['type'] == 'edit') {
-                                       // Creating the list of fields to include in the SQL query:
-                                       $selectFields = $this->fieldArray;
-                                       $selectFields[] = 'uid';
-                                       $selectFields[] = 'pid';
-                                       if ($table == 'pages') {
-                                               $selectFields[] = 'module';
-                                               $selectFields[] = 'extendToSubpages';
-                                               $selectFields[] = 'doktype';
-                                       }
-                                       if (is_array($GLOBALS['TCA'][$table]['ctrl']['enablecolumns'])) {
-                                               $selectFields = array_merge($selectFields, $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']);
-                                       }
-                                       if ($GLOBALS['TCA'][$table]['ctrl']['type']) {
-                                               $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['type'];
-                                       }
-                                       if ($GLOBALS['TCA'][$table]['ctrl']['typeicon_column']) {
-                                               $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['typeicon_column'];
-                                       }
-                                       if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
-                                               $selectFields[] = 't3ver_state';
-                                       }
-                                       // Unique list!
-                                       $selectFields = array_unique($selectFields);
-                                       $permissionClause = $table === 'pages' && $this->perms_clause ? ' AND ' . $this->perms_clause : '';
-                                       $sqlQueryParts = array(
-                                               'SELECT' => implode(',', $selectFields),
-                                               '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);
-                               } elseif ($shortcut['type'] == 'new') {
-                                       $icon = IconUtility::getIcon($table, array(), $this->backPath);
-                               }
-                               $icon = IconUtility::skinImg($this->backPath, $icon, '', 1);
-                               break;
-                       case 'file_edit':
-                               $icon = 'gfx/edit_file.gif';
-                               break;
-                       case 'wizard_rte':
-                               $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'];
-                                       // 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)) {
-                                               $icon = '../' . \TYPO3\CMS\Core\Utility\PathUtility::stripPathSitePrefix($icon);
-                                       }
-                               } else {
-                                       $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) . '" />';
-       }
-
-       /**
-        * Returns title for the shortcut icon
-        *
-        * @param string $shortcutLabel Shortcut label
-        * @param string $moduleName Backend module name (key)
-        * @param string $parentModuleName Parent module label
-        * @return string Title for the shortcut icon
-        */
-       protected function getShortcutIconTitle($shortcutLabel, $moduleName, $parentModuleName = '') {
-               $title = '';
-               if (substr($moduleName, 0, 5) == 'xMOD_') {
-                       $title = substr($moduleName, 5);
-               } else {
-                       $splitModuleName = explode('_', $moduleName);
-                       $title = $GLOBALS['LANG']->moduleLabels['tabs'][$splitModuleName[0] . '_tab'];
-                       if (count($splitModuleName) > 1) {
-                               $title .= '>' . $GLOBALS['LANG']->moduleLabels['tabs'][($moduleName . '_tab')];
-                       }
-               }
-               if ($parentModuleName) {
-                       $title .= ' (' . $parentModuleName . ')';
-               }
-               $title .= ': ' . $shortcutLabel;
-               return $title;
-       }
-
-       /**
-        * Return the ID of the page in the URL if found.
-        *
-        * @param string $url The URL of the current shortcut link
-        * @return string If a page ID was found, it is returned. Otherwise: 0
-        */
-       protected function getLinkedPageId($url) {
-               return preg_replace('/.*[\\?&]id=([^&]+).*/', '$1', $url);
-       }
-
-}
diff --git a/typo3/sysext/backend/Classes/Toolbar/ToolbarItemHookInterface.php b/typo3/sysext/backend/Classes/Toolbar/ToolbarItemHookInterface.php
deleted file mode 100644 (file)
index f3ba84d..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php
-namespace TYPO3\CMS\Backend\Toolbar;
-
-/**
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-/**
- * Interface for classes which extend the backend by adding items to the top toolbar
- *
- * @author Ingo Renner <ingo@typo3.org>
- */
-interface ToolbarItemHookInterface {
-       /**
-        * Constructor that receives a back reference to the backend
-        *
-        * @param \TYPO3\CMS\Backend\Controller\BackendController $backendReference 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 bool TRUE if user has access, FALSE if not
-        */
-       public function checkAccess();
-
-       /**
-        * Renders the toolbar item
-        *
-        * @return string The toolbar item rendered as HTML string
-        */
-       public function render();
-
-       /**
-        * Returns additional attributes for the list item in the toolbar
-        *
-        * @return string List item HTML attibutes
-        */
-       public function getAdditionalAttributes();
-
-}
index cfb9084..79198e3 100644 (file)
@@ -74,4 +74,15 @@ interface ToolbarItemInterface {
         */
        public function getAdditionalAttributes();
 
+       /**
+        * Returns an integer between 0 and 100 to determine
+        * the position of this item relative to others
+        *
+        * By default, extensions should return 50 to be sorted between main core
+        * items and other items that should be on the very right.
+        *
+        * @return integer 0 .. 100
+        */
+       public function getIndex();
+
 }
index d9c5781..db8bc28 100644 (file)
@@ -8,6 +8,11 @@ if (TYPO3_MODE === 'BE') {
                'TYPO3\\CMS\\Backend\\Security\\CategoryPermissionsAspect',
                'addUserPermissionsToCategoryTreeData'
        );
+
+       $GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][] = 'TYPO3\\CMS\\Backend\\Backend\\ToolbarItems\\ClearCacheToolbarItem';
+       $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']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default'] = 'TYPO3\\CMS\\Core\\FrontendEditing\\FrontendEditingController';
index d9a1b8f..eb83477 100644 (file)
@@ -89,7 +89,6 @@ return array(
        'ClearCacheMenu' => 'TYPO3\\CMS\\Backend\\Toolbar\\ClearCacheToolbarItem',
        'LiveSearch' => 'TYPO3\\CMS\\Backend\\Toolbar\\LiveSearchToolbarItem',
        'ShortcutMenu' => 'TYPO3\\CMS\\Backend\\Toolbar\\ShortcutToolbarItem',
-       'backend_toolbarItem' => 'TYPO3\\CMS\\Backend\\Toolbar\\ToolbarItemHookInterface',
        't3lib_tree_ExtDirect_AbstractExtJsTree' => 'TYPO3\\CMS\\Backend\\Tree\\AbstractExtJsTree',
        't3lib_tree_AbstractTree' => 'TYPO3\\CMS\\Backend\\Tree\\AbstractTree',
        't3lib_tree_AbstractDataProvider' => 'TYPO3\\CMS\\Backend\\Tree\\AbstractTreeDataProvider',
index afb116f..f20b790 100644 (file)
@@ -179,8 +179,6 @@ class LiveSearch extends \TYPO3\CMS\Backend\Toolbar\LiveSearchToolbarItem {}
 
 class ShortcutMenu extends \TYPO3\CMS\Backend\Toolbar\ShortcutToolbarItem {}
 
-interface backend_toolbarItem extends \TYPO3\CMS\Backend\Toolbar\ToolbarItemHookInterface {}
-
 abstract class t3lib_tree_ExtDirect_AbstractExtJsTree extends \TYPO3\CMS\Backend\Tree\AbstractExtJsTree {}
 
 abstract class t3lib_tree_AbstractTree extends \TYPO3\CMS\Backend\Tree\AbstractTree {}
index ce3b058..9e97542 100644 (file)
@@ -702,6 +702,7 @@ return array(
                                'csrfTokenCheck' => TRUE
                        ),
                ),
+               'toolbarItems' => array(), // Array: Registered toolbar items classes
                'HTTP' => array(
                        'Response' => array(
                                'Headers' => array('clickJackingProtection' => 'X-Frame-Options: SAMEORIGIN')
diff --git a/typo3/sysext/opendocs/Classes/Backend/ToolbarItems/OpendocsToolbarItem.php b/typo3/sysext/opendocs/Classes/Backend/ToolbarItems/OpendocsToolbarItem.php
new file mode 100644 (file)
index 0000000..478b3c6
--- /dev/null
@@ -0,0 +1,311 @@
+<?php
+namespace TYPO3\CMS\Opendocs\Backend\ToolbarItems;
+
+/**
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
+
+/**
+ * Adding a list of all open documents of a user to the backend.php
+ *
+ * @author Benjamin Mack <benni@typo3.org>
+ * @author Ingo Renner <ingo@typo3.org>
+ */
+class OpendocsToolbarItem implements ToolbarItemInterface {
+
+       /**
+        * @var \TYPO3\CMS\Backend\Controller\BackendController
+        */
+       protected $backendReference;
+
+       /**
+        * @var array
+        */
+       protected $openDocs;
+
+       /**
+        * @var array
+        */
+       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
+        */
+       public function __construct(\TYPO3\CMS\Backend\Controller\BackendController &$backendReference = NULL) {
+               $GLOBALS['LANG']->includeLLFile('EXT:opendocs/locallang_opendocs.xlf');
+               $this->backendReference = $backendReference;
+               $this->loadDocsFromUserSession();
+       }
+
+       /**
+        * Checks whether the user has access to this toolbar item
+        *
+        * @return bool TRUE if user has access, FALSE if not
+        */
+       public function checkAccess() {
+               $conf = $GLOBALS['BE_USER']->getTSConfig('backendToolbarItem.tx_opendocs.disabled');
+               return $conf['value'] != 1;
+       }
+
+       /**
+        * Loads the opened and recently opened documents from the user
+        *
+        * @return void
+        */
+       public function loadDocsFromUserSession() {
+               list($this->openDocs, ) = $GLOBALS['BE_USER']->getModuleData('alt_doc.php', 'ses');
+               $this->recentDocs = $GLOBALS['BE_USER']->getModuleData('opendocs::recent');
+       }
+
+       /**
+        * Renders the toolbar item and the initial menu
+        *
+        * @return string The toolbar item including the initial menu content as HTML
+        */
+       public function render() {
+               $this->addJavascriptToBackend();
+               $this->addCssToBackend();
+               $numDocs = count($this->openDocs);
+               $opendocsMenu = array();
+               $title = $GLOBALS['LANG']->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[] = '<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
+        *
+        * @return string The menu's content
+        */
+       public function renderMenu() {
+               $openDocuments = $this->openDocs;
+               $recentDocuments = $this->recentDocs;
+               $entries = array();
+               $content = '';
+               if (count($openDocuments)) {
+                       $entries[] = '<li class="dropdown-header">' . $GLOBALS['LANG']->getLL('open_docs', TRUE) . '</li>';
+                       $i = 0;
+                       foreach ($openDocuments as $md5sum => $openDocument) {
+                               $i++;
+                               $entries[] = $this->renderMenuEntry($openDocument, $md5sum, FALSE, $i == 1);
+                       }
+               }
+               // 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>';
+                       $i = 0;
+                       foreach ($recentDocuments as $md5sum => $recentDocument) {
+                               $i++;
+                               $entries[] = $this->renderMenuEntry($recentDocument, $md5sum, TRUE, $i == 1);
+                       }
+               }
+               if (count($entries)) {
+                       $content = implode('', $entries);
+               } else {
+                       $content = '<li class="noOpenDocs">' . $GLOBALS['LANG']->getLL('no_docs', TRUE) . '</li>';
+               }
+               return $content;
+       }
+
+       /**
+        * Returns the recent documents list as an array
+        *
+        * @return array All recent documents as list-items
+        */
+       public 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);
+               if (!is_array($record)) {
+                       // Record seems to be deleted
+                       return '';
+               }
+               $label = htmlspecialchars(strip_tags(htmlspecialchars_decode($document[0])));
+               $icon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForRecord($table, $record);
+               $link = $GLOBALS['BACK_PATH'] . 'alt_doc.php?' . $document[2];
+               $pageId = (int)$document[3]['uid'];
+               if ($document[3]['table'] !== 'pages') {
+                       $pageId = (int)$document[3]['pid'];
+               }
+               $firstRow = '';
+               if ($isFirstDoc) {
+                       $firstRow = ' first-row';
+               }
+               if (!$isRecentDoc) {
+                       $title = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:rm.closeDoc', TRUE);
+                       // Open document
+                       $closeIcon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-document-close');
+                       $entry = '
+                               <li class="opendoc' . $firstRow . '">
+                                       <div class="linkWrap">
+                                               <a href="#" class="opendocLink" onclick="jump(unescape(\'' . htmlspecialchars($link) . '\'), \'web_list\', \'web\', ' . $pageId . ');TYPO3.OpendocsMenu.toggleMenu(); return false;" target="content">' . $icon . $label . '</a>
+                                               <a href="#" class="close" data-opendocsidentifier="' . $md5sum . '">' . $closeIcon . '</a>
+                                       </div>
+                               </li>';
+               } else {
+                       // Recently used document
+                       $entry = '
+                               <li class="recentdoc' . $firstRow . '">
+                                       <a href="#" onclick="jump(unescape(\'' . htmlspecialchars($link) . '\'), \'web_list\', \'web\', ' . $pageId . '); TYPO3.OpendocsMenu.toggleMenu(); return false;" target="content">' . $icon . $label . '</a>
+                               </li>';
+               }
+               return $entry;
+       }
+
+       /**
+        * 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 'tx-opendocs-menu';
+       }
+
+       /**
+        * Returns extra classes
+        *
+        * @return array
+        */
+       public function getExtraClasses() {
+               return array();
+       }
+
+       /**
+        * Get dropdown
+        *
+        * @return bool
+        */
+       public function getDropdown() {
+               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    ***
+        *******************/
+       /**
+        * Called as a hook in \TYPO3\CMS\Backend\Utility\BackendUtility::setUpdateSignal, calls a JS function to change
+        * the number of opened documents
+        *
+        * @param array $params
+        * @param unknown_type $ref
+        * @return string list item HTML attributes
+        */
+       public function updateNumberOfOpenDocsHook(&$params, $ref) {
+               $params['JScode'] = '
+                       if (top && top.TYPO3.OpendocsMenu) {
+                               top.TYPO3.OpendocsMenu.updateMenu();
+                       }
+               ';
+       }
+
+       /******************
+        *** AJAX CALLS ***
+        ******************/
+       /**
+        * Closes a document in the session and
+        *
+        * @param array $params Array of parameters from the AJAX interface, currently unused
+        * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj Object of type AjaxRequestHandler
+        * @return string List item HTML attributes
+        */
+       public function closeDocument($params = array(), \TYPO3\CMS\Core\Http\AjaxRequestHandler &$ajaxObj = NULL) {
+               $md5sum = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('md5sum');
+               if ($md5sum && isset($this->openDocs[$md5sum])) {
+                       // Add the document to be closed to the recent documents
+                       $this->recentDocs = array_merge(array($md5sum => $this->openDocs[$md5sum]), $this->recentDocs);
+                       // Allow a maximum of 8 recent documents
+                       if (count($this->recentDocs) > 8) {
+                               $this->recentDocs = array_slice($this->recentDocs, 0, 8);
+                       }
+                       // Remove it from the list of the open documents, and store the status
+                       unset($this->openDocs[$md5sum]);
+                       list(, $docDat) = $GLOBALS['BE_USER']->getModuleData('alt_doc.php', 'ses');
+                       $GLOBALS['BE_USER']->pushModuleData('alt_doc.php', array($this->openDocs, $docDat));
+                       $GLOBALS['BE_USER']->pushModuleData('opendocs::recent', $this->recentDocs);
+               }
+               $this->renderAjax($params, $ajaxObj);
+       }
+
+       /**
+        * Renders the menu so that it can be returned as response to an AJAX call
+        *
+        * @param array $params Array of parameters from the AJAX interface, currently unused
+        * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj Object of type AjaxRequestHandler
+        * @return void
+        */
+       public function renderAjax($params = array(), \TYPO3\CMS\Core\Http\AjaxRequestHandler &$ajaxObj = NULL) {
+               $menuContent = $this->renderMenu();
+               $ajaxObj->addContent('opendocsMenu', $menuContent);
+       }
+
+       /**
+        * Position relative to others
+        *
+        * @return int
+        */
+       public function getIndex() {
+               return 30;
+       }
+
+}
diff --git a/typo3/sysext/opendocs/Classes/Controller/OpendocsController.php b/typo3/sysext/opendocs/Classes/Controller/OpendocsController.php
deleted file mode 100644 (file)
index 699d166..0000000
+++ /dev/null
@@ -1,300 +0,0 @@
-<?php
-namespace TYPO3\CMS\Opendocs\Controller;
-
-/**
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-/**
- * Adding a list of all open documents of a user to the backend.php
- *
- * @author Benjamin Mack <benni@typo3.org>
- * @author Ingo Renner <ingo@typo3.org>
- */
-class OpendocsController implements \TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface {
-
-       /**
-        * @var \TYPO3\CMS\Backend\Controller\BackendController
-        */
-       protected $backendReference;
-
-       /**
-        * @var array
-        */
-       protected $openDocs;
-
-       /**
-        * @var array
-        */
-       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
-        */
-       public function __construct(\TYPO3\CMS\Backend\Controller\BackendController &$backendReference = NULL) {
-               $GLOBALS['LANG']->includeLLFile('EXT:opendocs/locallang_opendocs.xlf');
-               $this->backendReference = $backendReference;
-               $this->loadDocsFromUserSession();
-       }
-
-       /**
-        * Checks whether the user has access to this toolbar item
-        *
-        * @return bool TRUE if user has access, FALSE if not
-        */
-       public function checkAccess() {
-               $conf = $GLOBALS['BE_USER']->getTSConfig('backendToolbarItem.tx_opendocs.disabled');
-               return $conf['value'] != 1;
-       }
-
-       /**
-        * Loads the opened and recently opened documents from the user
-        *
-        * @return void
-        */
-       public function loadDocsFromUserSession() {
-               list($this->openDocs, ) = $GLOBALS['BE_USER']->getModuleData('alt_doc.php', 'ses');
-               $this->recentDocs = $GLOBALS['BE_USER']->getModuleData('opendocs::recent');
-       }
-
-       /**
-        * Renders the toolbar item and the initial menu
-        *
-        * @return string The toolbar item including the initial menu content as HTML
-        */
-       public function render() {
-               $this->addJavascriptToBackend();
-               $this->addCssToBackend();
-               $numDocs = count($this->openDocs);
-               $opendocsMenu = array();
-               $title = $GLOBALS['LANG']->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[] = '<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
-        *
-        * @return string The menu's content
-        */
-       public function renderMenu() {
-               $openDocuments = $this->openDocs;
-               $recentDocuments = $this->recentDocs;
-               $entries = array();
-               $content = '';
-               if (count($openDocuments)) {
-                       $entries[] = '<li class="dropdown-header">' . $GLOBALS['LANG']->getLL('open_docs', TRUE) . '</li>';
-                       $i = 0;
-                       foreach ($openDocuments as $md5sum => $openDocument) {
-                               $i++;
-                               $entries[] = $this->renderMenuEntry($openDocument, $md5sum, FALSE, $i == 1);
-                       }
-               }
-               // 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>';
-                       $i = 0;
-                       foreach ($recentDocuments as $md5sum => $recentDocument) {
-                               $i++;
-                               $entries[] = $this->renderMenuEntry($recentDocument, $md5sum, TRUE, $i == 1);
-                       }
-               }
-               if (count($entries)) {
-                       $content = implode('', $entries);
-               } else {
-                       $content = '<li class="noOpenDocs">' . $GLOBALS['LANG']->getLL('no_docs', TRUE) . '</li>';
-               }
-               return $content;
-       }
-
-       /**
-        * Returns the recent documents list as an array
-        *
-        * @return array All recent documents as list-items
-        */
-       public 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);
-               if (!is_array($record)) {
-                       // Record seems to be deleted
-                       return '';
-               }
-               $label = htmlspecialchars(strip_tags(htmlspecialchars_decode($document[0])));
-               $icon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconForRecord($table, $record);
-               $link = $GLOBALS['BACK_PATH'] . 'alt_doc.php?' . $document[2];
-               $pageId = (int)$document[3]['uid'];
-               if ($document[3]['table'] !== 'pages') {
-                       $pageId = (int)$document[3]['pid'];
-               }
-               $firstRow = '';
-               if ($isFirstDoc) {
-                       $firstRow = ' first-row';
-               }
-               if (!$isRecentDoc) {
-                       $title = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:rm.closeDoc', TRUE);
-                       // Open document
-                       $closeIcon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-document-close');
-                       $entry = '
-                               <li class="opendoc' . $firstRow . '">
-                                       <div class="linkWrap">
-                                               <a href="#" class="opendocLink" onclick="jump(unescape(\'' . htmlspecialchars($link) . '\'), \'web_list\', \'web\', ' . $pageId . ');TYPO3.OpendocsMenu.toggleMenu(); return false;" target="content">' . $icon . $label . '</a>
-                                               <a href="#" class="close" data-opendocsidentifier="' . $md5sum . '">' . $closeIcon . '</a>
-                                       </div>
-                               </li>';
-               } else {
-                       // Recently used document
-                       $entry = '
-                               <li class="recentdoc' . $firstRow . '">
-                                       <a href="#" onclick="jump(unescape(\'' . htmlspecialchars($link) . '\'), \'web_list\', \'web\', ' . $pageId . '); TYPO3.OpendocsMenu.toggleMenu(); return false;" target="content">' . $icon . $label . '</a>
-                               </li>';
-               }
-               return $entry;
-       }
-
-       /**
-        * 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 'tx-opendocs-menu';
-       }
-
-       /**
-        * Returns extra classes
-        *
-        * @return array
-        */
-       public function getExtraClasses() {
-               return array();
-       }
-
-       /**
-        * Get dropdown
-        *
-        * @return bool
-        */
-       public function getDropdown() {
-               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    ***
-        *******************/
-       /**
-        * Called as a hook in \TYPO3\CMS\Backend\Utility\BackendUtility::setUpdateSignal, calls a JS function to change
-        * the number of opened documents
-        *
-        * @param array $params
-        * @param unknown_type $ref
-        * @return string list item HTML attributes
-        */
-       public function updateNumberOfOpenDocsHook(&$params, $ref) {
-               $params['JScode'] = '
-                       if (top && top.TYPO3.OpendocsMenu) {
-                               top.TYPO3.OpendocsMenu.updateMenu();
-                       }
-               ';
-       }
-
-       /******************
-        *** AJAX CALLS ***
-        ******************/
-       /**
-        * Closes a document in the session and
-        *
-        * @param array $params Array of parameters from the AJAX interface, currently unused
-        * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj Object of type AjaxRequestHandler
-        * @return string List item HTML attributes
-        */
-       public function closeDocument($params = array(), \TYPO3\CMS\Core\Http\AjaxRequestHandler &$ajaxObj = NULL) {
-               $md5sum = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('md5sum');
-               if ($md5sum && isset($this->openDocs[$md5sum])) {
-                       // Add the document to be closed to the recent documents
-                       $this->recentDocs = array_merge(array($md5sum => $this->openDocs[$md5sum]), $this->recentDocs);
-                       // Allow a maximum of 8 recent documents
-                       if (count($this->recentDocs) > 8) {
-                               $this->recentDocs = array_slice($this->recentDocs, 0, 8);
-                       }
-                       // Remove it from the list of the open documents, and store the status
-                       unset($this->openDocs[$md5sum]);
-                       list(, $docDat) = $GLOBALS['BE_USER']->getModuleData('alt_doc.php', 'ses');
-                       $GLOBALS['BE_USER']->pushModuleData('alt_doc.php', array($this->openDocs, $docDat));
-                       $GLOBALS['BE_USER']->pushModuleData('opendocs::recent', $this->recentDocs);
-               }
-               $this->renderAjax($params, $ajaxObj);
-       }
-
-       /**
-        * Renders the menu so that it can be returned as response to an AJAX call
-        *
-        * @param array $params Array of parameters from the AJAX interface, currently unused
-        * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj Object of type AjaxRequestHandler
-        * @return void
-        */
-       public function renderAjax($params = array(), \TYPO3\CMS\Core\Http\AjaxRequestHandler &$ajaxObj = NULL) {
-               $menuContent = $this->renderMenu();
-               $ajaxObj->addContent('opendocsMenu', $menuContent);
-       }
-
-}
index 6b592c2..4648715 100644 (file)
@@ -1,4 +1,6 @@
 <?php
 return array(
-       'tx_opendocs' => 'TYPO3\\CMS\\Opendocs\\Controller\\OpendocsController',
+       'tx_opendocs' => 'TYPO3\\CMS\\Opendocs\\Backend\\ToolbarItems\\OpendocsToolbarItem',
+       // @TODO: Migrate old class name usages to the new one
+       'TYPO3\\CMS\\Opendocs\\Controller\\OpendocsController' => 'TYPO3\\CMS\\Opendocs\\Backend\\ToolbarItems\\OpendocsToolbarItem',
 );
diff --git a/typo3/sysext/opendocs/Resources/PHP/RegisterToolbarItem.php b/typo3/sysext/opendocs/Resources/PHP/RegisterToolbarItem.php
deleted file mode 100644 (file)
index 8fb3567..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?php
-defined('TYPO3_MODE') or die();
-
-if (TYPO3_MODE === 'BE') {
-       // Now register the class as toolbar item
-       $GLOBALS['TYPO3backend']->addToolbarItem('opendocs', 'TYPO3\\CMS\\Opendocs\\Controller\\OpendocsController');
-}
index c77a87b..864cc82 100644 (file)
@@ -1,7 +1,4 @@
 <?php
-defined('TYPO3_MODE') or die();
-
 if (TYPO3_MODE === 'BE') {
-       // Register toolbar item
-       $GLOBALS['TYPO3_CONF_VARS']['typo3/backend.php']['additionalBackendItems'][] = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('opendocs'). 'Resources/PHP/RegisterToolbarItem.php';
+       $GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][] = 'TYPO3\\CMS\\Opendocs\\Backend\\ToolbarItems\\OpendocsToolbarItem';
 }
\ No newline at end of file
diff --git a/typo3/sysext/sys_action/Classes/ActionToolbarMenu.php b/typo3/sysext/sys_action/Classes/ActionToolbarMenu.php
deleted file mode 100644 (file)
index 04615bf..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-<?php
-namespace TYPO3\CMS\SysAction;
-
-/**
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\CMS\Backend\Utility\BackendUtility;
-
-/**
- * Adds action links to the backend's toolbar
- *
- * @author Steffen Kamper <info@sk-typo3.de>
- */
-class ActionToolbarMenu implements \TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface {
-
-       /**
-        * @var \TYPO3\CMS\Backend\Controller\BackendController
-        */
-       protected $backendReference;
-
-       /**
-        * @var string
-        */
-       protected $extensionKey = 'sys_action';
-
-       /**
-        * Constructor
-        */
-       public function __construct(\TYPO3\CMS\Backend\Controller\BackendController &$backendReference = NULL) {
-               $GLOBALS['LANG']->includeLLFile('EXT:sys_action/locallang.xlf');
-               $this->backendReference = $backendReference;
-       }
-
-       /**
-        * Sets the backend reference
-        *
-        * @param \TYPO3\CMS\Backend\Controller\BackendController $backendReference Backend object reference
-        * @return void
-        */
-       public function setBackend(\TYPO3\CMS\Backend\Controller\BackendController &$backendReference) {
-               $this->backendReference = $backendReference;
-       }
-
-       /**
-        * Renders the toolbar menu
-        *
-        * @return string The rendered backend menu
-        * @author Ingo Renner <ingo@typo3.org>
-        */
-       public function render() {
-               $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 '';
-               }
-       }
-
-       /**
-        * 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() {
-               $actions = array();
-               if ($GLOBALS['BE_USER']->isAdmin()) {
-                       $queryResource = $GLOBALS['TYPO3_DB']->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;
-                       }
-                       $queryResource = $GLOBALS['TYPO3_DB']->exec_SELECT_mm_query(
-                               'sys_action.*',
-                               'sys_action',
-                               'sys_action_asgr_mm',
-                               'be_groups',
-                               ' AND be_groups.uid IN (' . $groupList . ') AND sys_action.pid = 0 AND sys_action.hidden = 0',
-                               'sys_action.uid',
-                               'sys_action.sorting'
-                       );
-               }
-
-               if ($queryResource) {
-                       while ($actionRow = $GLOBALS['TYPO3_DB']->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)
-                               );
-                       }
-                       $GLOBALS['TYPO3_DB']->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 '';
-       }
-
-       /**
-        * Return attribute id name
-        *
-        * @return string The name of the ID attribute
-        */
-       public function getIdAttribute() {
-               return 'tx-sys-action-menu';
-       }
-
-       /**
-        * Returns extra classes
-        *
-        * @return array
-        */
-       public function getExtraClasses() {
-               return array();
-       }
-
-       /**
-        * Get dropdown
-        *
-        * @return bool
-        */
-       public function getDropdown() {
-               return TRUE;
-       }
-
-       /**
-        * Checks if user has access to the sys action menu
-        *
-        * @return bool TRUE if the user has access, FALSE otherwise
-        */
-       public function checkAccess() {
-               // Taskcenter is enabled for everybody
-               return TRUE;
-       }
-
-}
diff --git a/typo3/sysext/sys_action/Classes/Backend/ToolbarItems/ActionToolbarItem.php b/typo3/sysext/sys_action/Classes/Backend/ToolbarItems/ActionToolbarItem.php
new file mode 100644 (file)
index 0000000..eefbe0b
--- /dev/null
@@ -0,0 +1,176 @@
+<?php
+namespace TYPO3\CMS\SysAction\Backend\ToolbarItems;
+
+/**
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface;
+
+/**
+ * Adds action links to the backend's toolbar
+ *
+ * @author Steffen Kamper <info@sk-typo3.de>
+ */
+class ActionToolbarItem implements ToolbarItemInterface {
+
+       /**
+        * @var \TYPO3\CMS\Backend\Controller\BackendController
+        */
+       protected $backendReference;
+
+       /**
+        * @var string
+        */
+       protected $extensionKey = 'sys_action';
+
+       /**
+        * Constructor
+        */
+       public function __construct(\TYPO3\CMS\Backend\Controller\BackendController &$backendReference = NULL) {
+               $GLOBALS['LANG']->includeLLFile('EXT:sys_action/locallang.xlf');
+               $this->backendReference = $backendReference;
+       }
+
+       /**
+        * Sets the backend reference
+        *
+        * @param \TYPO3\CMS\Backend\Controller\BackendController $backendReference Backend object reference
+        * @return void
+        */
+       public function setBackend(\TYPO3\CMS\Backend\Controller\BackendController &$backendReference) {
+               $this->backendReference = $backendReference;
+       }
+
+       /**
+        * Renders the toolbar menu
+        *
+        * @return string The rendered backend menu
+        * @author Ingo Renner <ingo@typo3.org>
+        */
+       public function render() {
+               $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 '';
+               }
+       }
+
+       /**
+        * 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() {
+               $actions = array();
+               if ($GLOBALS['BE_USER']->isAdmin()) {
+                       $queryResource = $GLOBALS['TYPO3_DB']->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;
+                       }
+                       $queryResource = $GLOBALS['TYPO3_DB']->exec_SELECT_mm_query(
+                               'sys_action.*',
+                               'sys_action',
+                               'sys_action_asgr_mm',
+                               'be_groups',
+                               ' AND be_groups.uid IN (' . $groupList . ') AND sys_action.pid = 0 AND sys_action.hidden = 0',
+                               'sys_action.uid',
+                               'sys_action.sorting'
+                       );
+               }
+
+               if ($queryResource) {
+                       while ($actionRow = $GLOBALS['TYPO3_DB']->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)
+                               );
+                       }
+                       $GLOBALS['TYPO3_DB']->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 '';
+       }
+
+       /**
+        * Return attribute id name
+        *
+        * @return string The name of the ID attribute
+        */
+       public function getIdAttribute() {
+               return 'tx-sys-action-menu';
+       }
+
+       /**
+        * Returns extra classes
+        *
+        * @return array
+        */
+       public function getExtraClasses() {
+               return array();
+       }
+
+       /**
+        * Get dropdown
+        *
+        * @return bool
+        */
+       public function getDropdown() {
+               return TRUE;
+       }
+
+       /**
+        * Checks if user has access to the sys action menu
+        *
+        * @return bool TRUE if the user has access, FALSE otherwise
+        */
+       public function checkAccess() {
+               // Taskcenter is enabled for everybody
+               return TRUE;
+       }
+
+       /**
+        * Position relative to others
+        *
+        * @return int
+        */
+       public function getIndex() {
+               return 35;
+       }
+
+}
diff --git a/typo3/sysext/sys_action/Resources/PHP/RegisterToolbarItem.php b/typo3/sysext/sys_action/Resources/PHP/RegisterToolbarItem.php
deleted file mode 100644 (file)
index 9b8a30c..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-<?php
-defined('TYPO3_MODE') or die();
-
-$GLOBALS['TYPO3backend']->addToolbarItem('sys_action', 'TYPO3\\CMS\\SysAction\\ActionToolbarMenu');
\ No newline at end of file
index dce51f3..b2828cc 100644 (file)
@@ -1,6 +1,4 @@
 <?php
-defined('TYPO3_MODE') or die();
-
 if (TYPO3_MODE === 'BE') {
-       $GLOBALS['TYPO3_CONF_VARS']['typo3/backend.php']['additionalBackendItems'][] = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('sys_action') . 'Resources/PHP/RegisterToolbarItem.php';
+       $GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][] = 'TYPO3\\CMS\\SysAction\\Backend\\ToolbarItems\\ActionToolbarItem';
 }
\ No newline at end of file
diff --git a/typo3/sysext/workspaces/Classes/Backend/ToolbarItems/WorkspaceSelectorToolbarItem.php b/typo3/sysext/workspaces/Classes/Backend/ToolbarItems/WorkspaceSelectorToolbarItem.php
new file mode 100644 (file)
index 0000000..877f95e
--- /dev/null
@@ -0,0 +1,168 @@
+<?php
+namespace TYPO3\CMS\Workspaces\Backend\ToolbarItems;
+
+/**
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * 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;
+
+       /**
+        * 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));
+       }
+
+       /**
+        * Checks whether the user has access to this toolbar item
+        *
+        * @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;
+                       }
+               }
+               return $this->checkAccess;
+       }
+
+       /**
+        * Creates the selector for workspaces
+        *
+        * @return string workspace selector as HTML select
+        */
+       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');
+
+               $index = 0;
+               /** @var \TYPO3\CMS\Workspaces\Service\WorkspaceService $wsService */
+               $wsService = GeneralUtility::makeInstance(\TYPO3\CMS\Workspaces\Service\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')
+               ));
+
+               $workspaceSections = array(
+                       'top' => array(),
+                       'items' => array(),
+               );
+
+               foreach ($availableWorkspaces as $workspaceId => $label) {
+                       $workspaceId = (int)$workspaceId;
+                       $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>';
+               }
+
+               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>';
+                       }
+               } else {
+                       // no items on top (= no workspace to work in)
+                       $workspaceSections['top'][] = '<li>' . $stateUncheckedIcon . ' ' . $GLOBALS['LANG']->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">' ,
+                               implode(LF, $workspaceSections['top']),
+                               (!empty($workspaceSections['items']) ? '<li class="divider"></li>' : ''),
+                               implode(LF, $workspaceSections['items']),
+                       '</ul>'
+               );
+
+               return implode(LF, $workspaceMenu);
+       }
+
+       /**
+        * 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 'workspace-selector-menu';
+       }
+
+       /**
+        * Returns extra classes
+        *
+        * @return array
+        */
+       public function getExtraClasses() {
+               return array();
+       }
+
+       /**
+        * Get dropdown
+        *
+        * @return bool
+        */
+       public function getDropdown() {
+               return TRUE;
+       }
+
+       /**
+        * Position relative to others
+        *
+        * @return int
+        */
+       public function getIndex() {
+               return 40;
+       }
+
+}
diff --git a/typo3/sysext/workspaces/Classes/ExtDirect/WorkspaceSelectorToolbarItem.php b/typo3/sysext/workspaces/Classes/ExtDirect/WorkspaceSelectorToolbarItem.php
deleted file mode 100644 (file)
index c55932f..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-<?php
-namespace TYPO3\CMS\Workspaces\ExtDirect;
-
-/**
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-
-/**
- * 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;
-
-       /**
-        * 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));
-       }
-
-       /**
-        * Checks whether the user has access to this toolbar item
-        *
-        * @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;
-                       }
-               }
-               return $this->checkAccess;
-       }
-
-       /**
-        * Creates the selector for workspaces
-        *
-        * @return string workspace selector as HTML select
-        */
-       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');
-
-               $index = 0;
-               /** @var \TYPO3\CMS\Workspaces\Service\WorkspaceService $wsService */
-               $wsService = GeneralUtility::makeInstance(\TYPO3\CMS\Workspaces\Service\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')
-               ));
-
-               $workspaceSections = array(
-                       'top' => array(),
-                       'items' => array(),
-               );
-
-               foreach ($availableWorkspaces as $workspaceId => $label) {
-                       $workspaceId = (int)$workspaceId;
-                       $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>';
-               }
-
-               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>';
-                       }
-               } else {
-                       // no items on top (= no workspace to work in)
-                       $workspaceSections['top'][] = '<li>' . $stateUncheckedIcon . ' ' . $GLOBALS['LANG']->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">' ,
-                               implode(LF, $workspaceSections['top']),
-                               (!empty($workspaceSections['items']) ? '<li class="divider"></li>' : ''),
-                               implode(LF, $workspaceSections['items']),
-                       '</ul>'
-               );
-
-               return implode(LF, $workspaceMenu);
-       }
-
-       /**
-        * 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 'workspace-selector-menu';
-       }
-
-       /**
-        * Returns extra classes
-        *
-        * @return array
-        */
-       public function getExtraClasses() {
-               return array();
-       }
-
-       /**
-        * Get dropdown
-        *
-        * @return bool
-        */
-       public function getDropdown() {
-               return TRUE;
-       }
-
-}
diff --git a/typo3/sysext/workspaces/Resources/PHP/RegisterToolbarItem.php b/typo3/sysext/workspaces/Resources/PHP/RegisterToolbarItem.php
deleted file mode 100644 (file)
index cc86345..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-<?php
-defined('TYPO3_MODE') or die();
-
-$GLOBALS['TYPO3backend']->addToolbarItem('workSpaceSelector', 'TYPO3\\CMS\\Workspaces\\ExtDirect\\WorkspaceSelectorToolbarItem');
\ No newline at end of file
index 7e8a6d2..61166e1 100644 (file)
@@ -28,9 +28,9 @@ if (!is_array($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations
 }
 
 if (TYPO3_MODE === 'BE') {
-       $GLOBALS['TYPO3_CONF_VARS']['typo3/backend.php']['additionalBackendItems'][] = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath($_EXTKEY) . 'Resources/PHP/RegisterToolbarItem.php';
-
        // If publishing/swapping dependent parent-child references, consider all parents and children
        \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addUserTSConfig('options.workspaces.considerReferences = 1');
        $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/tree/pagetree/class.t3lib_tree_pagetree_dataprovider.php']['postProcessCollections'][] = 'TYPO3\\CMS\\Workspaces\\ExtDirect\\PagetreeCollectionsProcessor';
+
+       $GLOBALS['TYPO3_CONF_VARS']['BE']['toolbarItems'][] = 'TYPO3\\CMS\\Workspaces\\Backend\\ToolbarItems\\WorkspaceSelectorToolbarItem';
 }