Commit 5be7b805 authored by Christian Kuhn's avatar Christian Kuhn Committed by Anja Leichsenring
Browse files

[!!!][TASK] Refactor create bookmark handling

The backend shortcut / bookmark handlig API was designed to
hand over relevant get/post arguments as key only (eg. 'id').
The underlying code then pulled values from GET/POST or from
SOBE->MOD_SETTINGS. This is ugly, there shouldn't be such
magic: Only controllers know relevant keys and values, so
it should hand them over directly to the shortcut API.

The patch changes this:
* Old and unused ViewHelper f:be.buttons.shortcut is deprecated.
* ViewHelper be:moduleLayout.button.shortcutButton deprecates
  argument 'getVars' and adds new argument 'arguments'.
* Class ShortcutButton has a new setter 'setArguments' that
  accepts all relevant argument key/value pairs to create a
  shortcut. Existing get/set related methods are deprecated.
* Helper methods 'makeShortcutIcon' and 'makeShortcutUrl' of
  class ModuleTemplate are deprecated and implemented in class
  ShortcutButton directly.
* All core usages are adapted to new API.
* Shortcut handling was the last core usage of SOBE, so last
  $GLOBALS['SOBE'] = $this assignments can be finally removed.

Impact:
* Shortcuts to modules not directly reachable via main menu
  do not work due to limits of the module registration API. An
  example is the 'create multiple pages' controller. This issue
  exists before the patch, affected controllers no longer render
  a shortcut button for now.
* The old code usually added the 'route' argument twice for shortcuts.
  This has been resolved. As a side effect, the comparison if a
  shortcuts exists (yellow shortcut icon) fails currently for existing
  shortcuts when the patch is applied: The comparison relies on
  direct string equality since shortcuts always store the final url in
  the database. This storage strategy should be changed with another
  patch that will solve the 'no yellow icon' issue at the same time.

Change-Id: I3ccd2b8f6adab8e7780c5f9911fdea013ccfa99b
Resolves: #92132
Releases: master
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/65503

Tested-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
parent 81849669
......@@ -115,7 +115,6 @@ class NewContentElementController
public function __construct()
{
$this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
$GLOBALS['SOBE'] = $this;
$this->view = $this->getFluidTemplateObject();
$this->menuItemView = $this->getFluidTemplateObject('MenuItem.html');
$this->uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
......
......@@ -1298,7 +1298,7 @@ class EditDocumentController
}
$this->registerOpenInNewWindowButtonToButtonBar($buttonBar, ButtonBar::BUTTON_POSITION_RIGHT, 2);
$this->registerShortcutButtonToButtonBar($buttonBar, ButtonBar::BUTTON_POSITION_RIGHT, 3);
$this->registerShortcutButtonToButtonBar($buttonBar, ButtonBar::BUTTON_POSITION_RIGHT, 3, $request);
$this->registerCshButtonToButtonBar($buttonBar, ButtonBar::BUTTON_POSITION_RIGHT, 4);
}
......@@ -1794,21 +1794,31 @@ class EditDocumentController
* @param ButtonBar $buttonBar
* @param string $position
* @param int $group
* @param ServerRequestInterface $request
*/
protected function registerShortcutButtonToButtonBar(ButtonBar $buttonBar, string $position, int $group)
protected function registerShortcutButtonToButtonBar(ButtonBar $buttonBar, string $position, int $group, ServerRequestInterface $request)
{
if ($this->returnUrl !== $this->getCloseUrl()) {
$queryParams = $request->getQueryParams();
$potentialArguments = [
'returnUrl',
'edit',
'defVals',
'overrideVals',
'columnsOnly',
'returnNewPageId',
'noView'
];
$arguments = [
'route' => $queryParams['route'],
];
foreach ($potentialArguments as $argument) {
if (!empty($queryParams[$argument])) {
$arguments[$argument] = $queryParams[$argument];
}
}
$shortCutButton = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar()->makeShortcutButton();
$shortCutButton->setModuleName('xMOD_alt_doc.php')
->setGetVariables([
'returnUrl',
'edit',
'defVals',
'overrideVals',
'columnsOnly',
'returnNewPageId',
'noView']);
$shortCutButton->setModuleName('xMOD_alt_doc.php')->setArguments($arguments);
$buttonBar->addButton($shortCutButton, $position, $group);
}
}
......
......@@ -170,14 +170,17 @@ class HelpController
{
$buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
if ($this->getBackendUser()->mayMakeShortcut()) {
$shortcutButton = $buttonBar->makeShortcutButton()
->setModuleName('help_cshmanual')
->setGetVariables(['table', 'field', 'route']);
$buttonBar->addButton($shortcutButton);
}
$action = $request->getQueryParams()['action'] ?? $request->getParsedBody()['action'] ?? 'index';
$shortcutButton = $buttonBar->makeShortcutButton()
->setModuleName('help_cshmanual')
->setArguments([
'route' => $request->getQueryParams()['route'],
'action' => $action,
'table' => $request->getQueryParams()['table'] ?? '',
'field' => $request->getQueryParams()['field'] ?? ''
]);
$buttonBar->addButton($shortcutButton);
if ($action !== 'index') {
$uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
$backButton = $buttonBar->makeLinkButton()
......
......@@ -89,10 +89,7 @@ class NewMultiplePagesController
->setTitle($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage'))
->setIcon($iconFactory->getIcon('actions-view-page', Icon::SIZE_SMALL))
->setHref('#');
$shortcutButton = $buttonBar->makeShortcutButton()
->setModuleName('pages_new')
->setGetVariables(['id']);
$buttonBar->addButton($cshButton)->addButton($viewButton)->addButton($shortcutButton);
$buttonBar->addButton($cshButton)->addButton($viewButton);
// Main view setup
$view = GeneralUtility::makeInstance(StandaloneView::class);
......
......@@ -87,10 +87,7 @@ class SortSubPagesController
->setTitle($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage'))
->setIcon($iconFactory->getIcon('actions-view-page', Icon::SIZE_SMALL))
->setHref('#');
$shortcutButton = $buttonBar->makeShortcutButton()
->setModuleName('pages_sort')
->setGetVariables(['id']);
$buttonBar->addButton($cshButton)->addButton($viewButton)->addButton($shortcutButton);
$buttonBar->addButton($cshButton)->addButton($viewButton);
// Main view setup
$view = GeneralUtility::makeInstance(StandaloneView::class);
......
......@@ -174,7 +174,6 @@ class PageLayoutController
*/
public function mainAction(ServerRequestInterface $request): ResponseInterface
{
$GLOBALS['SOBE'] = $this;
$this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
$this->pageRenderer = $this->moduleTemplate->getPageRenderer();
$this->iconFactory = $this->moduleTemplate->getIconFactory();
......@@ -303,7 +302,7 @@ class PageLayoutController
/**
* This creates the dropdown menu with the different actions this module is able to provide.
* For now they are Columns, Quick Edit and Languages.
* For now they are Columns and Languages.
*
* @param array $actions array with the available actions
*/
......@@ -784,12 +783,15 @@ class PageLayoutController
// Shortcut
$shortcutButton = $this->buttonBar->makeShortcutButton()
->setModuleName($this->moduleName)
->setGetVariables([
'id',
'route',
'edit_record',
])
->setSetVariables(array_keys($this->MOD_MENU));
->setArguments([
'route' => $request->getQueryParams()['route'],
'id' => (int)$this->id,
'SET' => [
'tt_content_showHidden' => (bool)$this->MOD_SETTINGS['tt_content_showHidden'],
'function' => (int)$this->MOD_SETTINGS['function'],
'language' => (int)$this->current_sys_language,
]
]);
$this->buttonBar->addButton($shortcutButton);
// Cache
......
......@@ -107,7 +107,6 @@ class SimpleDataHandlerController
*/
public function mainAction(ServerRequestInterface $request): ResponseInterface
{
$GLOBALS['SOBE'] = $this;
$this->init($request);
$this->initializeClipboard();
......@@ -129,7 +128,6 @@ class SimpleDataHandlerController
*/
public function processAjaxRequest(ServerRequestInterface $request): ResponseInterface
{
$GLOBALS['SOBE'] = $this;
$this->init($request);
// do the regular / main logic
......
......@@ -109,10 +109,12 @@ class SiteConfigurationController
/**
* List pages that have 'is_siteroot' flag set - those that have the globe icon in page tree.
* Link to Add / Edit / Delete for each.
*
* @param ServerRequestInterface $request
*/
protected function overviewAction(): void
protected function overviewAction(ServerRequestInterface $request): void
{
$this->configureOverViewDocHeader();
$this->configureOverViewDocHeader($request->getQueryParams()['route']);
$allSites = $this->siteFinder->getAllSites();
$pages = $this->getAllSitePages();
$unassignedSites = [];
......@@ -607,8 +609,10 @@ class SiteConfigurationController
/**
* Create document header buttons of "overview" action
*
* @param string $route
*/
protected function configureOverViewDocHeader(): void
protected function configureOverViewDocHeader(string $route): void
{
$iconFactory = $this->moduleTemplate->getIconFactory();
$buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
......@@ -617,13 +621,12 @@ class SiteConfigurationController
->setTitle($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.reload'))
->setIcon($iconFactory->getIcon('actions-refresh', Icon::SIZE_SMALL));
$buttonBar->addButton($reloadButton, ButtonBar::BUTTON_POSITION_RIGHT);
if ($this->getBackendUser()->mayMakeShortcut()) {
$getVars = ['id', 'route'];
$shortcutButton = $buttonBar->makeShortcutButton()
->setModuleName('site_configuration')
->setGetVariables($getVars);
$buttonBar->addButton($shortcutButton, ButtonBar::BUTTON_POSITION_RIGHT);
}
$shortcutButton = $buttonBar->makeShortcutButton()
->setModuleName('site_configuration')
->setArguments([
'route' => $route
]);
$buttonBar->addButton($shortcutButton, ButtonBar::BUTTON_POSITION_RIGHT);
}
/**
......
......@@ -15,13 +15,17 @@
namespace TYPO3\CMS\Backend\Template\Components\Buttons\Action;
use TYPO3\CMS\Backend\Backend\Shortcut\ShortcutRepository;
use TYPO3\CMS\Backend\Template\Components\ButtonBar;
use TYPO3\CMS\Backend\Template\Components\Buttons\ButtonInterface;
use TYPO3\CMS\Backend\Template\Components\Buttons\PositionInterface;
use TYPO3\CMS\Backend\Template\ModuleTemplate;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext;
use TYPO3\CMS\Core\Utility\HttpUtility;
/**
* ShortcutButton
......@@ -33,6 +37,9 @@ use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext;
*
* $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
* $myButton = $buttonBar->makeShortcutButton()
* ->setArguments([
* 'route' => $request->getQueryParams()['route']
* ])
* ->setModuleName('my_info');
* $buttonBar->addButton($myButton);
*/
......@@ -41,27 +48,29 @@ class ShortcutButton implements ButtonInterface, PositionInterface
/**
* @var string
*/
protected $moduleName;
protected $moduleName = '';
/**
* @var string
*/
protected $displayName;
protected $displayName = '';
/**
* @var array
* @var array List of parameter/value pairs relevant for this shortcut
*/
protected $setVariables = [];
protected $arguments = [];
/**
* @var array
* @deprecated since v11, will be removed in v12
*/
protected $getVariables = [];
protected $setVariables = [];
/**
* @var ControllerContext
* @var array
* @deprecated since v11, will be removed in v12
*/
protected $controllerContext;
protected $getVariables = [];
/**
* Gets the name of the module.
......@@ -107,13 +116,25 @@ class ShortcutButton implements ButtonInterface, PositionInterface
return $this;
}
/**
* @param array $arguments
* @return $this
*/
public function setArguments(array $arguments): self
{
$this->arguments = $arguments;
return $this;
}
/**
* Gets the SET variables.
*
* @return array
* @deprecated since v11, will be removed in v12
*/
public function getSetVariables()
{
trigger_error('Method getSetVariables() is deprecated and will be removed in v12. Please use ShortcutButton->setArguments() instead.', E_USER_DEPRECATED);
return $this->setVariables;
}
......@@ -122,6 +143,7 @@ class ShortcutButton implements ButtonInterface, PositionInterface
*
* @param array $setVariables
* @return ShortcutButton
* @deprecated since v11, will be removed in v12. Deprecation logged by ModuleTemplate->makeShortcutIcon()
*/
public function setSetVariables(array $setVariables)
{
......@@ -133,9 +155,11 @@ class ShortcutButton implements ButtonInterface, PositionInterface
* Gets the GET variables.
*
* @return array
* @deprecated since v11, will be removed in v12
*/
public function getGetVariables()
{
trigger_error('Method getGetVariables() is deprecated and will be removed in v12. Please use ShortcutButton->setArguments() instead.', E_USER_DEPRECATED);
return $this->getVariables;
}
......@@ -144,6 +168,7 @@ class ShortcutButton implements ButtonInterface, PositionInterface
*
* @param array $getVariables
* @return ShortcutButton
* @deprecated since v11, will be removed in v12. Deprecation logged by ModuleTemplate->makeShortcutIcon()
*/
public function setGetVariables(array $getVariables)
{
......@@ -183,18 +208,12 @@ class ShortcutButton implements ButtonInterface, PositionInterface
/**
* Determines whether the button shall be rendered.
* Depends on the backend user permission to create
* shortcuts and the defined module name.
*
* @return bool
*/
public function isValid()
{
$this->preProcess();
return
!empty($this->moduleName)
;
return !empty($this->moduleName);
}
/**
......@@ -215,52 +234,69 @@ class ShortcutButton implements ButtonInterface, PositionInterface
public function render()
{
if ($this->getBackendUser()->mayMakeShortcut()) {
/** @var ModuleTemplate $moduleTemplate */
$moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
$shortcutMarkup = $moduleTemplate->makeShortcutIcon(
implode(',', $this->getVariables),
implode(',', $this->setVariables),
$this->moduleName,
'',
$this->displayName
);
if (!empty($this->arguments)) {
$shortcutMarkup = $this->createShortcutMarkup();
} else {
// @deprecated since v11, the else branch will be removed in v12. Deprecation thrown by makeShortcutIcon() below
if (empty($this->getVariables)) {
$this->getVariables = ['id', 'route'];
}
$moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
$shortcutMarkup = $moduleTemplate->makeShortcutIcon(
implode(',', $this->getVariables),
implode(',', $this->setVariables),
$this->moduleName,
'',
$this->displayName
);
}
} else {
$shortcutMarkup = '';
}
return $shortcutMarkup;
}
/**
* Pre-processes class member values.
*/
protected function preProcess()
protected function createShortcutMarkup(): string
{
$emptyGetVariables = (count($this->getVariables) === 0);
$moduleName = $this->moduleName;
$storeUrl = HttpUtility::buildQueryString($this->arguments, '&');
// Set default GET parameters
if ($emptyGetVariables) {
$this->getVariables = ['id', 'route'];
}
// Find out if this shortcut exists already. Note this is a hack based on the fact
// that sys_be_shortcuts stores the entire request string and not just needed params as array.
$pathInfo = parse_url(GeneralUtility::getIndpEnv('REQUEST_URI'));
$shortcutUrl = $pathInfo['path'] . '?' . $storeUrl;
$shortcutRepository = GeneralUtility::makeInstance(ShortcutRepository::class);
$shortcutExist = $shortcutRepository->shortcutExists($shortcutUrl);
// Automatically determine module name in Extbase context
if ($this->controllerContext !== null) {
$currentRequest = $this->controllerContext->getRequest();
$extensionName = $currentRequest->getControllerExtensionName();
$this->moduleName = $currentRequest->getPluginName();
// Extend default GET parameters
if ($emptyGetVariables) {
$modulePrefix = strtolower('tx_' . $extensionName . '_' . $this->moduleName);
$this->getVariables[] = $modulePrefix;
}
$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
if ($shortcutExist) {
$shortcutMarkup = '<a class="active btn btn-default btn-sm" title="">'
. $iconFactory->getIcon('actions-system-shortcut-active', Icon::SIZE_SMALL)->render()
. '</a>';
} else {
$languageService = $this->getLanguageService();
$confirmationText = $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.makeBookmark');
$onClick = 'top.TYPO3.ShortcutMenu.createShortcut('
. GeneralUtility::quoteJSvalue(rawurlencode($moduleName))
. ', ' . GeneralUtility::quoteJSvalue(rawurlencode($shortcutUrl))
. ', ' . GeneralUtility::quoteJSvalue($confirmationText)
. ', \'\''
. ', this'
. ', ' . GeneralUtility::quoteJSvalue($this->displayName) . ');return false;';
$shortcutMarkup = '<a href="#" class="btn btn-default btn-sm" onclick="' . htmlspecialchars($onClick) . '" title="'
. htmlspecialchars($languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.makeBookmark')) . '">'
. $iconFactory->getIcon('actions-system-shortcut-new', Icon::SIZE_SMALL)->render() . '</a>';
}
return $shortcutMarkup;
}
/**
* @return BackendUserAuthentication
*/
protected function getBackendUser()
protected function getBackendUser(): BackendUserAuthentication
{
return $GLOBALS['BE_USER'];
}
protected function getLanguageService(): LanguageService
{
return $GLOBALS['LANG'];
}
}
......@@ -522,9 +522,11 @@ class ModuleTemplate
* @return string HTML content
* @todo Make this thing return a button object
* @internal
* @deprecated since v11, will be removed in v12
*/
public function makeShortcutIcon($gvList, $setList, $modName, $motherModName = '', $displayName = '', $classes = 'btn btn-default btn-sm')
{
trigger_error('Method makeShortcutIcon() is deprecated and will be removed in v12. Please use ShortcutButton->setArguments() instead.', E_USER_DEPRECATED);
$gvList = 'route,id,' . $gvList;
$storeUrl = $this->makeShortcutUrl($gvList, $setList);
$pathInfo = parse_url(GeneralUtility::getIndpEnv('REQUEST_URI'));
......@@ -578,6 +580,7 @@ class ModuleTemplate
*
* @return string GET-parameters for the shortcut-url only(!). String starts with '&'
* @internal
* @deprecated since v11, will be removed in v12. Deprecation logged by parent method makeShortcutIcon()
*/
public function makeShortcutUrl($gvList, $setList)
{
......
......@@ -28,13 +28,16 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
* A ViewHelper for adding a shortcut button to the doc header area.
* It must be a child of :ref:`<be:moduleLayout> <typo3-backend-modulelayout>`.
*
* The 'arguments' argument should contain key/value pairs of all arguments
* relevant for the specific view.
*
* Examples
* --------
*
* Default::
*
* <be:moduleLayout>
* <be:moduleLayout.button.shortcutButton displayName="Shortcut label" />
* <be:moduleLayout.button.shortcutButton displayName="Shortcut label" arguments="{route: '{route}'"/>
* </be:moduleLayout>
*/
class ShortcutButtonViewHelper extends AbstractButtonViewHelper
......@@ -48,26 +51,34 @@ class ShortcutButtonViewHelper extends AbstractButtonViewHelper
{
parent::initializeArguments();
$this->registerArgument('displayName', 'string', 'Name for the shortcut');
$this->registerArgument('arguments', 'array', 'List of relevant GET variables as key/values list to store', false, []);
// @deprecated since v11, will be removed in v12. Use 'arguments' instead. Deprecation logged by ModuleTemplate->makeShortcutIcon()
$this->registerArgument('getVars', 'array', 'List of additional GET variables to store. The current id, module and all module arguments will always be stored', false, []);
}
protected static function createButton(ButtonBar $buttonBar, array $arguments, RenderingContextInterface $renderingContext): ButtonInterface
{
$currentRequest = $renderingContext->getControllerContext()->getRequest();
$extensionName = $currentRequest->getControllerExtensionName();
$moduleName = $currentRequest->getPluginName();
$argumentPrefix = GeneralUtility::makeInstance(ObjectManager::class)
->get(ExtensionService::class)
->getPluginNamespace($extensionName, $moduleName);
$getVars = $arguments['getVars'];
$getVars[] = $argumentPrefix;
$displayName = $arguments['displayName'];
$shortcutButton = $buttonBar->makeShortcutButton()
->setDisplayName($arguments['displayName'])
->setGetVariables($getVars)
->setDisplayName($displayName)
->setModuleName($moduleName);
if (!empty($arguments['arguments'])) {
$shortcutButton->setArguments($arguments['arguments']);
} else {
// @deprecated since v11, will be removed in v12. Use 'variables' instead. Deprecation logged by ModuleTemplate->makeShortcutIcon()
$extensionName = $currentRequest->getControllerExtensionName();
$argumentPrefix = GeneralUtility::makeInstance(ObjectManager::class)
->get(ExtensionService::class)
->getPluginNamespace($extensionName, $moduleName);
$getVars = $arguments['getVars'];
$getVars[] = $argumentPrefix;
$shortcutButton->setGetVariables($getVars);
}
return $shortcutButton;
}
}
......@@ -124,6 +124,9 @@ class BackendUserController extends ActionController
{
$view->assignMultiple([
'shortcutLabel' => 'backendUsers',
'route' => GeneralUtility::_GP('route'),
'action' => $this->request->getControllerActionName(),
'controller' => $this->request->getControllerName(),
'dateFormat' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'],
'timeFormat' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'],
]);
......
......@@ -19,6 +19,7 @@ use TYPO3\CMS\Beuser\Domain\Repository\BackendUserGroupRepository;
use TYPO3\CMS\Beuser\Service\UserInformationService;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Pagination\SimplePagination;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
use TYPO3\CMS\Extbase\Pagination\QueryResultPaginator;
......@@ -68,6 +69,9 @@ class BackendUserGroupController extends ActionController
'paginator' => $paginator,
'pagination' => $pagination,
'totalAmountOfBackendUserGroups' => $backendUsers->count(),
'route' => GeneralUtility::_GP('route'),
'action' => $this->request->getControllerActionName(),
'controller' => $this->request->getControllerName(),
'compareGroupUidList' => array_map(static function ($value) { // uid as key and force value to 1
return 1;
}, array_flip($compareGroupUidList)),
......@@ -92,6 +96,9 @@ class BackendUserGroupController extends ActionController
$this->view->assignMultiple([
'shortcutLabel' => 'compareBackendUsersGroups',
'route' => GeneralUtility::_GP('route'),
'action' => $this->request->getControllerActionName(),
'controller' => $this->request->getControllerName(),
'compareGroupList' => $compareData,
]);
}
......