From ae18caad69fee5920adeb82d13ba98ba58cadf24 Mon Sep 17 00:00:00 2001 From: Matthias Vogel <typo3@kanti.de> Date: Sat, 9 Sep 2017 13:04:20 +0200 Subject: [PATCH] [!!!][TASK] Migrate modules to regular backend routing This patch removes the separate request handler for backend modules, which was accessed via "&M=moduleName" GET parameter. This is now migrated into the RouteDispatcher which can dispatch modules as well. Now, modules are called via the "&route" parameter like all other routes. Additionally, the requested URLs for modules were requested with the additional "moduleToken" which is now called "token". This way, special treatment for modules when dispatching is removed, however the security checks are still in place so this is kept as is. All places where URLs are generated can now still be accessed via `BackendUtility::getModuleUrl()` which can deal with routes, module names and routePaths (from the URL) to keep backwards-compatibility. Next Steps: - Migration wizard for bookmarks + Streamline bookmarks code (see todos) - Check what needs to be added in ExtensionManagementUtility - Introduce slugs in routes for BE, e.g. /file-edit/{fileId}/ and /module/page/view/{id} - Document reserved GET parameters "id", "route" and "token" - Cleanup usage of determineScriptId and getModuleUrl to use new API Resolves: #82406 Releases: master Change-Id: If11c3d5289e14bc9ea766468b8e94cce95c23c71 Reviewed-on: https://review.typo3.org/53881 Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch> Tested-by: Christian Kuhn <lolli@schwarzbu.ch> Reviewed-by: Stefan Neufeind <typo3.neufeind@speedpartner.de> Tested-by: Stefan Neufeind <typo3.neufeind@speedpartner.de> Reviewed-by: Matthias Vogel <typo3@kanti.de> Tested-by: Matthias Vogel <typo3@kanti.de> Tested-by: TYPO3com <no-reply@typo3.com> Reviewed-by: Benni Mack <benni@typo3.org> Tested-by: Benni Mack <benni@typo3.org> --- .../ToolbarItems/ShortcutToolbarItem.php | 13 +- .../Controller/EditDocumentController.php | 4 +- .../Controller/PageLayoutController.php | 2 +- .../backend/Classes/Http/Application.php | 13 +- .../Http/BackendModuleRequestHandler.php | 222 ------------------ .../backend/Classes/Http/RequestHandler.php | 10 +- .../backend/Classes/Http/RouteDispatcher.php | 87 +++++++ .../Classes/RecordList/AbstractRecordList.php | 8 +- .../backend/Classes/Routing/UriBuilder.php | 23 +- .../Buttons/Action/ShortcutButton.php | 2 +- .../Classes/Template/DocumentTemplate.php | 2 +- .../Classes/Template/ModuleTemplate.php | 5 +- .../Classes/Tree/View/AbstractTreeView.php | 7 +- .../Classes/Utility/BackendUtility.php | 11 +- .../BackendUserActionController.php | 2 +- .../Controller/PermissionController.php | 2 +- .../Utility/ExtensionManagementUtility.php | 29 ++- ...kendModulesRunThroughRegularDispatcher.rst | 49 ++++ .../Classes/Controller/HelpController.php | 2 +- .../Classes/Mvc/Web/Routing/UriBuilder.php | 22 +- .../Unit/Mvc/Web/Routing/UriBuilderTest.php | 59 ++--- typo3/sysext/filelist/Classes/FileList.php | 7 +- .../Be/Buttons/ShortcutViewHelper.php | 4 +- .../Controller/FormManagerController.php | 2 +- .../Controller/InfoModuleController.php | 2 +- .../ExtensionScanner/Php/ClassNameMatcher.php | 5 + .../lowlevel/Classes/Utility/ArrayBrowser.php | 4 +- .../Browser/AbstractElementBrowser.php | 8 +- .../AbstractLinkBrowserController.php | 7 +- .../RecordList/AbstractDatabaseRecordList.php | 7 +- .../Classes/RecordList/DatabaseRecordList.php | 15 +- .../Controller/RecyclerModuleController.php | 2 +- .../Classes/Controller/ReportController.php | 2 +- .../TypoScriptTemplateModuleController.php | 2 +- .../Controller/ViewModuleController.php | 2 +- .../Classes/Controller/PreviewController.php | 2 +- .../Classes/Controller/ReviewController.php | 2 +- .../Classes/Service/WorkspaceService.php | 6 +- 38 files changed, 293 insertions(+), 360 deletions(-) delete mode 100644 typo3/sysext/backend/Classes/Http/BackendModuleRequestHandler.php create mode 100644 typo3/sysext/core/Documentation/Changelog/master/Breaking-82406-RoutingBackendModulesRunThroughRegularDispatcher.rst diff --git a/typo3/sysext/backend/Classes/Backend/ToolbarItems/ShortcutToolbarItem.php b/typo3/sysext/backend/Classes/Backend/ToolbarItems/ShortcutToolbarItem.php index c7f8b60062cf..8a1d39057406 100644 --- a/typo3/sysext/backend/Classes/Backend/ToolbarItems/ShortcutToolbarItem.php +++ b/typo3/sysext/backend/Classes/Backend/ToolbarItems/ShortcutToolbarItem.php @@ -307,6 +307,7 @@ class ShortcutToolbarItem implements ToolbarItemInterface /** * Adds the correct token, if the url is an index.php script + * @todo: this needs love * * @param string $url * @return string @@ -320,16 +321,20 @@ class ShortcutToolbarItem implements ToolbarItemInterface if (isset($parameters['returnUrl'])) { $parsedReturnUrl = parse_url($parameters['returnUrl']); parse_str($parsedReturnUrl['query'], $returnUrlParameters); - if (strpos($parsedReturnUrl['path'], 'index.php') !== false && isset($returnUrlParameters['M'])) { - $module = $returnUrlParameters['M']; + if (strpos($parsedReturnUrl['path'], 'index.php') !== false && !empty($returnUrlParameters['route'])) { + $module = $returnUrlParameters['route']; $returnUrl = BackendUtility::getModuleUrl($module, $returnUrlParameters); $parameters['returnUrl'] = $returnUrl; $url = $parsedUrl['path'] . '?' . http_build_query($parameters, '', '&', PHP_QUERY_RFC3986); } } + if (isset($parameters['M']) && empty($parameters['route'])) { + $parameters['route'] = $parameters['M']; + unset($parameters['M']); + } - if (strpos($parsedUrl['path'], 'index.php') !== false && isset($parameters['M'])) { - $module = $parameters['M']; + if (strpos($parsedUrl['path'], 'index.php') !== false && isset($parameters['route'])) { + $module = $parameters['route']; $url = BackendUtility::getModuleUrl($module, $parameters); } elseif (strpos($parsedUrl['path'], 'index.php') !== false && isset($parameters['route'])) { $routePath = $parameters['route']; diff --git a/typo3/sysext/backend/Classes/Controller/EditDocumentController.php b/typo3/sysext/backend/Classes/Controller/EditDocumentController.php index 952a8f5bfab9..7b2502c12ea5 100644 --- a/typo3/sysext/backend/Classes/Controller/EditDocumentController.php +++ b/typo3/sysext/backend/Classes/Controller/EditDocumentController.php @@ -1287,13 +1287,13 @@ class EditDocumentController extends AbstractModule $returnUrl = $this->retUrl; if ($this->firstEl['table'] === 'pages') { parse_str((string)parse_url($returnUrl, PHP_URL_QUERY), $queryParams); - if (isset($queryParams['M']) + if (isset($queryParams['route']) && isset($queryParams['id']) && (string)$this->firstEl['uid'] === (string)$queryParams['id'] ) { // TODO: Use the page's pid instead of 0, this requires a clean API to manipulate the page // tree from the outside to be able to mark the pid as active - $returnUrl = BackendUtility::getModuleUrl($queryParams['M'], ['id' => 0]); + $returnUrl = BackendUtility::getModuleUrl($queryParams['route'], ['id' => 0]); } } $deleteButton = $buttonBar->makeLinkButton() diff --git a/typo3/sysext/backend/Classes/Controller/PageLayoutController.php b/typo3/sysext/backend/Classes/Controller/PageLayoutController.php index fdf5f593be83..ddfff72aabc9 100644 --- a/typo3/sysext/backend/Classes/Controller/PageLayoutController.php +++ b/typo3/sysext/backend/Classes/Controller/PageLayoutController.php @@ -975,7 +975,7 @@ class PageLayoutController ->setModuleName($this->moduleName) ->setGetVariables([ 'id', - 'M', + 'route', 'edit_record', 'pointer', 'new_unique_uid', diff --git a/typo3/sysext/backend/Classes/Http/Application.php b/typo3/sysext/backend/Classes/Http/Application.php index 683a1b35f0dd..fe59180c9f23 100644 --- a/typo3/sysext/backend/Classes/Http/Application.php +++ b/typo3/sysext/backend/Classes/Http/Application.php @@ -33,18 +33,12 @@ class Application implements ApplicationInterface */ protected $entryPointLevel = 1; - /** - * @var \Psr\Http\Message\ServerRequestInterface - */ - protected $request; - /** * All available request handlers that can handle backend requests (non-CLI) * @var array */ protected $availableRequestHandlers = [ \TYPO3\CMS\Backend\Http\RequestHandler::class, - \TYPO3\CMS\Backend\Http\BackendModuleRequestHandler::class, \TYPO3\CMS\Backend\Http\AjaxRequestHandler::class ]; @@ -81,12 +75,7 @@ class Application implements ApplicationInterface */ public function run(callable $execute = null) { - $this->request = \TYPO3\CMS\Core\Http\ServerRequestFactory::fromGlobals(); - if (isset($this->request->getQueryParams()['M'])) { - $this->request = $this->request->withAttribute('isModuleRequest', true); - } - - $this->bootstrap->handleRequest($this->request); + $this->bootstrap->handleRequest(\TYPO3\CMS\Core\Http\ServerRequestFactory::fromGlobals()); if ($execute !== null) { call_user_func($execute); diff --git a/typo3/sysext/backend/Classes/Http/BackendModuleRequestHandler.php b/typo3/sysext/backend/Classes/Http/BackendModuleRequestHandler.php deleted file mode 100644 index 38c5d073db07..000000000000 --- a/typo3/sysext/backend/Classes/Http/BackendModuleRequestHandler.php +++ /dev/null @@ -1,222 +0,0 @@ -<?php -namespace TYPO3\CMS\Backend\Http; - -/* - * 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 Psr\Http\Message\ServerRequestInterface; -use TYPO3\CMS\Backend\Utility\BackendUtility; -use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; -use TYPO3\CMS\Core\Core\Bootstrap; -use TYPO3\CMS\Core\Exception; -use TYPO3\CMS\Core\FormProtection\BackendFormProtection; -use TYPO3\CMS\Core\FormProtection\FormProtectionFactory; -use TYPO3\CMS\Core\Http\Dispatcher; -use TYPO3\CMS\Core\Http\RequestHandlerInterface; -use TYPO3\CMS\Core\Http\Response; -use TYPO3\CMS\Core\Type\Bitmask\Permission; -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Core\Utility\MathUtility; - -/** - * Handles the request for backend modules and wizards - * Juggles with $GLOBALS['TBE_MODULES'] - */ -class BackendModuleRequestHandler implements RequestHandlerInterface -{ - /** - * @var Bootstrap - */ - protected $bootstrap; - - /** - * @var array - */ - protected $moduleRegistry = []; - - /** - * @var BackendUserAuthentication - */ - protected $backendUserAuthentication; - - /** - * Instance of the current Http Request - * @var ServerRequestInterface - */ - protected $request; - - /** - * Constructor handing over the bootstrap and the original request - * - * @param Bootstrap $bootstrap - */ - public function __construct(Bootstrap $bootstrap) - { - $this->bootstrap = $bootstrap; - } - - /** - * Handles the request, evaluating the configuration and executes the module accordingly - * - * @param ServerRequestInterface $request - * @return NULL|\Psr\Http\Message\ResponseInterface - * @throws Exception - */ - public function handleRequest(ServerRequestInterface $request) - { - $this->request = $request; - $this->boot(); - - $this->moduleRegistry = $GLOBALS['TBE_MODULES']; - - if (!$this->isValidModuleRequest()) { - throw new Exception('The CSRF protection token for the requested module is missing or invalid', 1417988921); - } - - $this->backendUserAuthentication = $GLOBALS['BE_USER']; - - $moduleName = (string)$this->request->getQueryParams()['M']; - return $this->dispatchModule($moduleName); - } - - /** - * Execute TYPO3 bootstrap - */ - protected function boot() - { - $this->bootstrap->checkLockedBackendAndRedirectOrDie() - ->checkBackendIpOrDie() - ->checkSslBackendAndRedirectIfNeeded() - ->initializeBackendRouter() - ->loadExtTables() - ->initializeBackendUser() - ->initializeBackendAuthentication() - ->initializeLanguageObject() - ->initializeBackendTemplate() - ->endOutputBufferingAndCleanPreviousOutput() - ->initializeOutputCompression() - ->sendHttpHeaders(); - } - - /** - * This request handler can handle any backend request coming from index.php - * - * @param ServerRequestInterface $request - * @return bool - */ - public function canHandleRequest(ServerRequestInterface $request) - { - return $request->getAttribute('isModuleRequest', false); - } - - /** - * Checks if all parameters are met. - * - * @return bool - */ - protected function isValidModuleRequest() - { - return $this->getFormProtection() instanceof BackendFormProtection - && $this->getFormProtection()->validateToken((string)$this->request->getQueryParams()['moduleToken'], 'moduleCall', (string)$this->request->getQueryParams()['M']); - } - - /** - * Executes the modules configured via Extbase - * - * @param string $moduleName - * @return Response A PSR-7 response object - * @throws \RuntimeException - */ - protected function dispatchModule($moduleName) - { - $moduleConfiguration = $this->getModuleConfiguration($moduleName); - - $response = GeneralUtility::makeInstance(Response::class); - - // Check permissions and exit if the user has no permission for entry - $this->backendUserAuthentication->modAccess($moduleConfiguration, true); - $id = isset($this->request->getQueryParams()['id']) ? $this->request->getQueryParams()['id'] : $this->request->getParsedBody()['id']; - if ($id && MathUtility::canBeInterpretedAsInteger($id)) { - $permClause = $this->backendUserAuthentication->getPagePermsClause(Permission::PAGE_SHOW); - // Check page access - $access = is_array(BackendUtility::readPageAccess((int)$id, $permClause)); - if (!$access) { - // Check if page has been deleted - $deleteField = $GLOBALS['TCA']['pages']['ctrl']['delete']; - $pageInfo = BackendUtility::getRecord('pages', (int)$id, $deleteField, $permClause ? ' AND ' . $permClause : '', false); - if (!$pageInfo[$deleteField]) { - throw new \RuntimeException('You don\'t have access to this page', 1289917924); - } - } - } - - // Use Core Dispatching - if (isset($moduleConfiguration['routeTarget'])) { - $dispatcher = GeneralUtility::makeInstance(Dispatcher::class); - $this->request = $this->request->withAttribute('target', $moduleConfiguration['routeTarget']); - $response = $dispatcher->dispatch($this->request, $response); - } else { - // extbase module - $configuration = [ - 'extensionName' => $moduleConfiguration['extensionName'], - 'pluginName' => $moduleName - ]; - if (isset($moduleConfiguration['vendorName'])) { - $configuration['vendorName'] = $moduleConfiguration['vendorName']; - } - - // Run Extbase - $bootstrap = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Core\Bootstrap::class); - $content = $bootstrap->run('', $configuration); - - $response->getBody()->write($content); - } - - return $response; - } - - /** - * Returns the module configuration which is provided during module registration - * - * @param string $moduleName - * @return array - * @throws \RuntimeException - */ - protected function getModuleConfiguration($moduleName) - { - if (!isset($this->moduleRegistry['_configuration'][$moduleName])) { - throw new \RuntimeException('Module ' . $moduleName . ' is not configured.', 1289918325); - } - return $this->moduleRegistry['_configuration'][$moduleName]; - } - - /** - * Returns the priority - how eager the handler is to actually handle the request. - * - * @return int The priority of the request handler. - */ - public function getPriority() - { - return 90; - } - - /** - * Wrapper method for static form protection utility - * - * @return \TYPO3\CMS\Core\FormProtection\AbstractFormProtection - */ - protected function getFormProtection() - { - return FormProtectionFactory::get(); - } -} diff --git a/typo3/sysext/backend/Classes/Http/RequestHandler.php b/typo3/sysext/backend/Classes/Http/RequestHandler.php index 084e891a6e20..a24905f77b2f 100644 --- a/typo3/sysext/backend/Classes/Http/RequestHandler.php +++ b/typo3/sysext/backend/Classes/Http/RequestHandler.php @@ -59,14 +59,22 @@ class RequestHandler implements RequestHandlerInterface */ public function handleRequest(ServerRequestInterface $request) { + // Check if a module URL is requested and deprecate this call + $moduleName = $request->getQueryParams()['M'] ?? $request->getParsedBody()['M'] ?? null; // Allow the login page to be displayed if routing is not used and on index.php - $pathToRoute = (string)$request->getQueryParams()['route'] ?: '/login'; + $pathToRoute = $request->getQueryParams()['route'] ?? $request->getParsedBody()['route'] ?? $moduleName ?? '/login'; $request = $request->withAttribute('routePath', $pathToRoute); // skip the BE user check on the login page // should be handled differently in the future by checking the Bootstrap directly $this->boot($pathToRoute === '/login'); + if ($moduleName !== null) { + trigger_error('Calling the TYPO3 Backend with "M" GET parameter will be removed in TYPO3 v10,' + . ' the calling code calls this script with "&M=' . $moduleName . '" and needs to be adapted' + . ' to use the TYPO3 API.', E_USER_DEPRECATED); + } + // Check if the router has the available route and dispatch. try { return $this->dispatch($request); diff --git a/typo3/sysext/backend/Classes/Http/RouteDispatcher.php b/typo3/sysext/backend/Classes/Http/RouteDispatcher.php index 957f85c785c7..bfd9bc633904 100644 --- a/typo3/sysext/backend/Classes/Http/RouteDispatcher.php +++ b/typo3/sysext/backend/Classes/Http/RouteDispatcher.php @@ -19,9 +19,12 @@ use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Backend\Routing\Exception\InvalidRequestTokenException; use TYPO3\CMS\Backend\Routing\Route; use TYPO3\CMS\Backend\Routing\Router; +use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\FormProtection\FormProtectionFactory; use TYPO3\CMS\Core\Http\Dispatcher; use TYPO3\CMS\Core\Http\DispatcherInterface; +use TYPO3\CMS\Core\Http\Response; +use TYPO3\CMS\Core\Type\Bitmask\Permission; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -45,10 +48,14 @@ class RouteDispatcher extends Dispatcher implements DispatcherInterface /** @var Route $route */ $route = $router->matchRequest($request); $request = $request->withAttribute('route', $route); + $request = $request->withAttribute('target', $route->getOption('target')); if (!$this->isValidRequest($request)) { throw new InvalidRequestTokenException('Invalid request for route "' . $route->getPath() . '"', 1425389455); } + if ($route->getOption('module')) { + return $this->dispatchModule($request, $response); + } $targetIdentifier = $route->getOption('target'); $target = $this->getCallableFromTarget($targetIdentifier); return call_user_func_array($target, [$request, $response]); @@ -82,4 +89,84 @@ class RouteDispatcher extends Dispatcher implements DispatcherInterface $token = (string)(isset($request->getParsedBody()['token']) ? $request->getParsedBody()['token'] : $request->getQueryParams()['token']); return $this->getFormProtection()->validateToken($token, 'route', $route->getOption('_identifier')); } + + /** + * Executes the modules configured via Extbase + * + * @param ServerRequestInterface $request + * @param ResponseInterface $response + * @return ResponseInterface A PSR-7 response object + * @throws \RuntimeException + */ + protected function dispatchModule(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface + { + $route = $request->getAttribute('route'); + $moduleName = $route->getOption('moduleName'); + $moduleConfiguration = $this->getModuleConfiguration($moduleName); + + $backendUserAuthentication = $GLOBALS['BE_USER']; + + // Check permissions and exit if the user has no permission for entry + // @todo please do not use "true" here, what a bad coding paradigm + $backendUserAuthentication->modAccess($moduleConfiguration, true); + $id = (int)$request->getQueryParams()['id'] ?? $request->getParsedBody()['id']; + if ($id) { + $permClause = $backendUserAuthentication->getPagePermsClause(Permission::PAGE_SHOW); + // Check page access + if (!is_array(BackendUtility::readPageAccess($id, $permClause))) { + // Check if page has been deleted + $deleteField = $GLOBALS['TCA']['pages']['ctrl']['delete']; + $pageInfo = BackendUtility::getRecord('pages', $id, $deleteField, $permClause ? ' AND ' . $permClause : '', false); + if (!$pageInfo[$deleteField]) { + throw new \RuntimeException('You don\'t have access to this page', 1289917924); + } + } + } + + // Use regular Dispatching + // @todo: unify with the code above + $targetIdentifier = $route->getOption('target'); + if (!empty($targetIdentifier)) { + // @internal routeParameters are a helper construct for the install tool only. + // @todo: remove this, after sub-actions in install tool can be addressed directly + if (!empty($moduleConfiguration['routeParameters'])) { + $request = $request->withQueryParams(array_merge_recursive( + $request->getQueryParams(), + $moduleConfiguration['routeParameters'] + )); + } + return parent::dispatch($request, $response); + } + // extbase module + $configuration = [ + 'extensionName' => $moduleConfiguration['extensionName'], + 'pluginName' => $moduleName + ]; + if (isset($moduleConfiguration['vendorName'])) { + $configuration['vendorName'] = $moduleConfiguration['vendorName']; + } + + // Run Extbase + $bootstrap = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Core\Bootstrap::class); + $content = $bootstrap->run('', $configuration); + + $response->getBody()->write($content); + + return $response; + } + + /** + * Returns the module configuration which is provided during module registration + * + * @param string $moduleName + * @return array + * @throws \RuntimeException + */ + protected function getModuleConfiguration($moduleName) + { + if (!isset($GLOBALS['TBE_MODULES']['_configuration'][$moduleName])) { + throw new \RuntimeException('Module ' . $moduleName . ' is not configured.', 1289918325); + } + return $GLOBALS['TBE_MODULES']['_configuration'][$moduleName]; + } } diff --git a/typo3/sysext/backend/Classes/RecordList/AbstractRecordList.php b/typo3/sysext/backend/Classes/RecordList/AbstractRecordList.php index 21d9a61b7919..2bb2b17f33d0 100644 --- a/typo3/sysext/backend/Classes/RecordList/AbstractRecordList.php +++ b/typo3/sysext/backend/Classes/RecordList/AbstractRecordList.php @@ -15,9 +15,7 @@ namespace TYPO3\CMS\Backend\RecordList; */ use TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider; -use TYPO3\CMS\Backend\Routing\Router; use TYPO3\CMS\Backend\Routing\UriBuilder; -use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction; use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction; @@ -215,12 +213,8 @@ abstract class AbstractRecordList protected function determineScriptUrl() { if ($routePath = GeneralUtility::_GP('route')) { - $router = GeneralUtility::makeInstance(Router::class); - $route = $router->match($routePath); $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); - $this->thisScript = (string)$uriBuilder->buildUriFromRoute($route->getOption('_identifier')); - } elseif ($moduleName = GeneralUtility::_GP('M')) { - $this->thisScript = BackendUtility::getModuleUrl($moduleName); + $this->thisScript = (string)$uriBuilder->buildUriFromRoutePath($routePath); } else { $this->thisScript = GeneralUtility::getIndpEnv('SCRIPT_NAME'); } diff --git a/typo3/sysext/backend/Classes/Routing/UriBuilder.php b/typo3/sysext/backend/Classes/Routing/UriBuilder.php index 93e5fadabb38..f2a9d313b8c1 100644 --- a/typo3/sysext/backend/Classes/Routing/UriBuilder.php +++ b/typo3/sysext/backend/Classes/Routing/UriBuilder.php @@ -54,6 +54,25 @@ class UriBuilder $this->routes = $router->getRoutes(); } + /** + * Generates a URL or path for a specific route based on the given rout. + * Currently used to link to the current script, it is encouraged to use "buildUriFromRoute" if possible. + * + * If there is no route with the given name, the generator throws the RouteNotFoundException. + * + * @param string $pathInfo The path to the route + * @param array $parameters An array of parameters + * @param string $referenceType The type of reference to be generated (one of the constants) + * @return Uri The generated Uri + * @throws RouteNotFoundException If the named route doesn't exist + */ + public function buildUriFromRoutePath($pathInfo, $parameters = [], $referenceType = self::ABSOLUTE_PATH) + { + $router = GeneralUtility::makeInstance(Router::class); + $route = $router->match($pathInfo); + return $this->buildUriFromRoute($route->getOption('_identifier'), $parameters, $referenceType); + } + /** * Generates a URL or path for a specific route based on the given parameters. * When the route is configured with "access=public" then the token generation is left out. @@ -106,8 +125,8 @@ class UriBuilder public function buildUriFromModule($moduleName, $parameters = [], $referenceType = self::ABSOLUTE_PATH) { $parameters = [ - 'M' => $moduleName, - 'moduleToken' => FormProtectionFactory::get('backend')->generateToken('moduleCall', $moduleName) + 'route' => $moduleName, + 'token' => FormProtectionFactory::get('backend')->generateToken('route', $moduleName) ] + $parameters; return $this->buildUri($parameters, $referenceType); } diff --git a/typo3/sysext/backend/Classes/Template/Components/Buttons/Action/ShortcutButton.php b/typo3/sysext/backend/Classes/Template/Components/Buttons/Action/ShortcutButton.php index 14db2a1d2942..b3b815041ad5 100644 --- a/typo3/sysext/backend/Classes/Template/Components/Buttons/Action/ShortcutButton.php +++ b/typo3/sysext/backend/Classes/Template/Components/Buttons/Action/ShortcutButton.php @@ -239,7 +239,7 @@ class ShortcutButton implements ButtonInterface, PositionInterface // Set default GET parameters if ($emptyGetVariables) { - $this->getVariables = ['id', 'M']; + $this->getVariables = ['id', 'route']; } // Automatically determine module name in Extbase context diff --git a/typo3/sysext/backend/Classes/Template/DocumentTemplate.php b/typo3/sysext/backend/Classes/Template/DocumentTemplate.php index 02365ea0deb4..446bf200151d 100644 --- a/typo3/sysext/backend/Classes/Template/DocumentTemplate.php +++ b/typo3/sysext/backend/Classes/Template/DocumentTemplate.php @@ -251,7 +251,7 @@ function jumpToUrl(URL) { $this->templateService = GeneralUtility::makeInstance(MarkerBasedTemplateService::class); // Setting default scriptID, trim forward slash from route - $this->scriptID = GeneralUtility::_GET('M') !== null ? GeneralUtility::_GET('M') : ltrim(GeneralUtility::_GET('route'), '/'); + $this->scriptID = ltrim(GeneralUtility::_GET('route'), '/'); $this->bodyTagId = preg_replace('/[^A-Za-z0-9-]/', '-', $this->scriptID); // Individual configuration per script? If so, make a recursive merge of the arrays: if (is_array($GLOBALS['TBE_STYLES']['scriptIDindex'][$this->scriptID])) { diff --git a/typo3/sysext/backend/Classes/Template/ModuleTemplate.php b/typo3/sysext/backend/Classes/Template/ModuleTemplate.php index f8b6622b1268..aa55258e0fa6 100644 --- a/typo3/sysext/backend/Classes/Template/ModuleTemplate.php +++ b/typo3/sysext/backend/Classes/Template/ModuleTemplate.php @@ -510,8 +510,9 @@ class ModuleTemplate // since this is used for icons. $moduleName = $modName === 'xMOD_alt_doc.php' ? 'record_edit' : $modName; // Add the module identifier automatically if typo3/index.php is used: - if (GeneralUtility::_GET('M') !== null) { - $storeUrl = '&M=' . $moduleName . $storeUrl; + // @todo: routing + if (GeneralUtility::_GET('route') !== null) { + $storeUrl = '&route=' . $moduleName . $storeUrl; } if ((int)$motherModName === 1) { $motherModule = 'top.currentModuleLoaded'; diff --git a/typo3/sysext/backend/Classes/Tree/View/AbstractTreeView.php b/typo3/sysext/backend/Classes/Tree/View/AbstractTreeView.php index 2564e31bf185..13dab282fae1 100644 --- a/typo3/sysext/backend/Classes/Tree/View/AbstractTreeView.php +++ b/typo3/sysext/backend/Classes/Tree/View/AbstractTreeView.php @@ -14,7 +14,6 @@ namespace TYPO3\CMS\Backend\Tree\View; * The TYPO3 project - inspiring people to share! */ -use TYPO3\CMS\Backend\Routing\Router; use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Backend\Tree\Pagetree\Commands; use TYPO3\CMS\Backend\Utility\BackendUtility; @@ -289,12 +288,8 @@ abstract class AbstractTreeView protected function determineScriptUrl() { if ($routePath = GeneralUtility::_GP('route')) { - $router = GeneralUtility::makeInstance(Router::class); - $route = $router->match($routePath); $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); - $this->thisScript = (string)$uriBuilder->buildUriFromRoute($route->getOption('_identifier')); - } elseif ($moduleName = GeneralUtility::_GP('M')) { - $this->thisScript = BackendUtility::getModuleUrl($moduleName); + $this->thisScript = (string)$uriBuilder->buildUriFromRoutePath($routePath); } else { $this->thisScript = GeneralUtility::getIndpEnv('SCRIPT_NAME'); } diff --git a/typo3/sysext/backend/Classes/Utility/BackendUtility.php b/typo3/sysext/backend/Classes/Utility/BackendUtility.php index 103a2feb361b..46af96a288d9 100644 --- a/typo3/sysext/backend/Classes/Utility/BackendUtility.php +++ b/typo3/sysext/backend/Classes/Utility/BackendUtility.php @@ -2950,14 +2950,10 @@ class BackendUtility $script = basename(PATH_thisScript); } - if (GeneralUtility::_GP('route')) { - $router = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\Router::class); - $route = $router->match(GeneralUtility::_GP('route')); + if ($routePath = GeneralUtility::_GP('route')) { $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class); - $scriptUrl = (string)$uriBuilder->buildUriFromRoute($route->getOption('_identifier')); + $scriptUrl = (string)$uriBuilder->buildUriFromRoutePath($routePath, $mainParams); $scriptUrl .= $addParams; - } elseif ($script === 'index.php' && GeneralUtility::_GET('M')) { - $scriptUrl = self::getModuleUrl(GeneralUtility::_GET('M'), $mainParams) . $addParams; } else { $scriptUrl = $script . '?' . GeneralUtility::implodeArrayForUrl('', $mainParams) . $addParams; } @@ -3169,8 +3165,7 @@ class BackendUtility try { $uri = $uriBuilder->buildUriFromRoute($moduleName, $urlParameters); } catch (\TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException $e) { - // no route registered, use the fallback logic to check for a module - $uri = $uriBuilder->buildUriFromModule($moduleName, $urlParameters); + $uri = $uriBuilder->buildUriFromRoutePath($moduleName, $urlParameters); } return (string)$uri; } diff --git a/typo3/sysext/beuser/Classes/Controller/BackendUserActionController.php b/typo3/sysext/beuser/Classes/Controller/BackendUserActionController.php index fe9bce3f6a9a..61a1a70eb975 100644 --- a/typo3/sysext/beuser/Classes/Controller/BackendUserActionController.php +++ b/typo3/sysext/beuser/Classes/Controller/BackendUserActionController.php @@ -125,7 +125,7 @@ class BackendUserActionController extends ActionController $extensionName = $currentRequest->getControllerExtensionName(); if (count($getVars) === 0) { $modulePrefix = strtolower('tx_' . $extensionName . '_' . $moduleName); - $getVars = ['id', 'M', $modulePrefix]; + $getVars = ['id', 'route', $modulePrefix]; } $shortcutName = $this->getLanguageService()->sL('LLL:EXT:beuser/Resources/Private/Language/locallang.xml:backendUsers'); if ($this->request->getControllerName() === 'BackendUser') { diff --git a/typo3/sysext/beuser/Classes/Controller/PermissionController.php b/typo3/sysext/beuser/Classes/Controller/PermissionController.php index 81155f031aca..072dd3bf481f 100644 --- a/typo3/sysext/beuser/Classes/Controller/PermissionController.php +++ b/typo3/sysext/beuser/Classes/Controller/PermissionController.php @@ -158,7 +158,7 @@ class PermissionController extends ActionController $extensionName = $currentRequest->getControllerExtensionName(); if (empty($getVars)) { $modulePrefix = strtolower('tx_' . $extensionName . '_' . $moduleName); - $getVars = ['id', 'M', $modulePrefix]; + $getVars = ['id', 'route', $modulePrefix]; } if ($currentRequest->getControllerActionName() === 'edit') { diff --git a/typo3/sysext/core/Classes/Utility/ExtensionManagementUtility.php b/typo3/sysext/core/Classes/Utility/ExtensionManagementUtility.php index c0f3b752e46a..292524f2a550 100644 --- a/typo3/sysext/core/Classes/Utility/ExtensionManagementUtility.php +++ b/typo3/sysext/core/Classes/Utility/ExtensionManagementUtility.php @@ -858,9 +858,8 @@ class ExtensionManagementUtility } // add additional configuration + $fullModuleSignature = $main . ($sub ? '_' . $sub : ''); if (is_array($moduleConfiguration) && !empty($moduleConfiguration)) { - $fullModuleSignature = $main . ($sub ? '_' . $sub : ''); - if (!empty($moduleConfiguration['icon'])) { $iconRegistry = GeneralUtility::makeInstance(IconRegistry::class); $iconIdentifier = 'module-' . $fullModuleSignature; @@ -876,6 +875,32 @@ class ExtensionManagementUtility $GLOBALS['TBE_MODULES']['_configuration'][$fullModuleSignature] = $moduleConfiguration; } + + // Also register the module as regular route + // Build Route objects from the data + $name = $fullModuleSignature; + if (isset($moduleConfiguration['path'])) { + $path = $moduleConfiguration['path']; + } else { + $path = str_replace('_', '/', $name); + } + $path = '/' . trim($path, '/') . '/'; + + $options = [ + 'module' => true, + 'moduleName' => $fullModuleSignature, + 'access' => $moduleConfiguration['access'] ?: 'user,group' + ]; + if ($moduleConfiguration['routeTarget']) { + $options['target'] = $moduleConfiguration['routeTarget']; + } + + $router = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\Router::class); + $router->addRoute( + $name, + // @todo: see if we should do a "module route" + GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\Route::class, $path, $options) + ); } /** diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-82406-RoutingBackendModulesRunThroughRegularDispatcher.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-82406-RoutingBackendModulesRunThroughRegularDispatcher.rst new file mode 100644 index 000000000000..fd79b8e5a708 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Breaking-82406-RoutingBackendModulesRunThroughRegularDispatcher.rst @@ -0,0 +1,49 @@ +.. include:: ../../Includes.txt + +========================================================================== +Breaking: #82406 - Routing: Backend Modules run through regular dispatcher +========================================================================== + +See :issue:`82406` + +Description +=========== + +Calling Backend modules was previously handled via a special `BackendModuleRequestHandler` which has +been removed. + +When registering a Backend module, a route with the name of the module is automatically added to the +Backend Router. + +When generating URLs for modules, the module is not added via the GET Parameter `&M=moduleName` +anymore, but built like any other Backend Route (currently with the "route" and "token" parameters) + +All request handling functionality is now done by the regular Backend RequestHandler, +which checks if the Route to be targeted is a module, and does extra module permission checks. + + +Impact +====== + +Handling with the "&M" GET parameter in backend modules won't deliver the correct result anymore. + +Instantiating `BackendModuleRequestHandler` will result in a fatal PHP error. + + +Affected Installations +====================== + +Installations with custom extensions including backend modules which work directly with the GET +parameter "M". + + +Migration +========= + +If extensions use API methods like ``BackendUtility::getModuleUrl()`` are used, nothing needs to be +modified. + +If a backend module is using the GET parameter "M" currently, the code needs to be adjusted to the +GET "route" or use the UriBuilder directly. + +.. index:: Backend, PartiallyScanned diff --git a/typo3/sysext/cshmanual/Classes/Controller/HelpController.php b/typo3/sysext/cshmanual/Classes/Controller/HelpController.php index e623c99fde9d..06e257775608 100644 --- a/typo3/sysext/cshmanual/Classes/Controller/HelpController.php +++ b/typo3/sysext/cshmanual/Classes/Controller/HelpController.php @@ -151,7 +151,7 @@ class HelpController extends ActionController $extensionName = $currentRequest->getControllerExtensionName(); if (count($getVars) === 0) { $modulePrefix = strtolower('tx_' . $extensionName . '_' . $moduleName); - $getVars = ['id', 'M', $modulePrefix]; + $getVars = ['id', 'route', $modulePrefix]; } $shortcutButton = $buttonBar->makeShortcutButton() ->setModuleName($moduleName) diff --git a/typo3/sysext/extbase/Classes/Mvc/Web/Routing/UriBuilder.php b/typo3/sysext/extbase/Classes/Mvc/Web/Routing/UriBuilder.php index f27a50666ee2..169644191b2e 100644 --- a/typo3/sysext/extbase/Classes/Mvc/Web/Routing/UriBuilder.php +++ b/typo3/sysext/extbase/Classes/Mvc/Web/Routing/UriBuilder.php @@ -664,24 +664,32 @@ class UriBuilder } } else { $id = GeneralUtility::_GP('id'); - $module = GeneralUtility::_GP('M'); + $module = GeneralUtility::_GP('route'); if ($id !== null) { $arguments['id'] = $id; } if ($module !== null) { - $arguments['M'] = $module; + $arguments['route'] = $module; } } ArrayUtility::mergeRecursiveWithOverrule($arguments, $this->arguments); $arguments = $this->convertDomainObjectsToIdentityArrays($arguments); $this->lastArguments = $arguments; - $moduleName = $arguments['M']; - unset($arguments['M'], $arguments['moduleToken']); + $moduleName = $arguments['route'] ?? null; + unset($arguments['route'], $arguments['token']); $backendUriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class); - if ($this->request instanceof WebRequest && $this->createAbsoluteUri) { - $uri = (string)$backendUriBuilder->buildUriFromModule($moduleName, $arguments, \TYPO3\CMS\Backend\Routing\UriBuilder::ABSOLUTE_URL); + if (!empty($moduleName)) { + if ($this->request instanceof WebRequest && $this->createAbsoluteUri) { + $uri = (string)$backendUriBuilder->buildUriFromRoutePath($moduleName, $arguments, \TYPO3\CMS\Backend\Routing\UriBuilder::ABSOLUTE_URL); + } else { + $uri = (string)$backendUriBuilder->buildUriFromRoutePath($moduleName, $arguments, \TYPO3\CMS\Backend\Routing\UriBuilder::ABSOLUTE_PATH); + } } else { - $uri = (string)$backendUriBuilder->buildUriFromModule($moduleName, $arguments); + if ($this->request instanceof WebRequest && $this->createAbsoluteUri) { + $uri = (string)$backendUriBuilder->buildUriFromModule($moduleName, $arguments, \TYPO3\CMS\Backend\Routing\UriBuilder::ABSOLUTE_URL); + } else { + $uri = (string)$backendUriBuilder->buildUriFromModule($moduleName, $arguments, \TYPO3\CMS\Backend\Routing\UriBuilder::ABSOLUTE_PATH); + } } if ($this->section !== '') { $uri .= '#' . $this->section; diff --git a/typo3/sysext/extbase/Tests/Unit/Mvc/Web/Routing/UriBuilderTest.php b/typo3/sysext/extbase/Tests/Unit/Mvc/Web/Routing/UriBuilderTest.php index a86b73b6d3cc..063f27200e48 100644 --- a/typo3/sysext/extbase/Tests/Unit/Mvc/Web/Routing/UriBuilderTest.php +++ b/typo3/sysext/extbase/Tests/Unit/Mvc/Web/Routing/UriBuilderTest.php @@ -13,6 +13,8 @@ namespace TYPO3\CMS\Extbase\Tests\Unit\Mvc\Web\Routing; * * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Backend\Routing\Route; +use TYPO3\CMS\Backend\Routing\Router; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Configuration\ConfigurationManager; @@ -76,6 +78,9 @@ class UriBuilderTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase $this->uriBuilder->_set('configurationManager', $this->mockConfigurationManager); $this->uriBuilder->_set('extensionService', $this->mockExtensionService); $this->uriBuilder->_set('environmentService', $this->createMock(EnvironmentService::class)); + $router = GeneralUtility::makeInstance(Router::class); + $router->addRoute('module_key', new Route('/test/Path', [])); + $router->addRoute('module_key2', new Route('/test/Path2', [])); // Mocking backend user is required for backend URI generation as BackendUtility::getModuleUrl() is called $backendUserMock = $this->createMock(BackendUserAuthentication::class); $backendUserMock->expects($this->any())->method('check')->will($this->returnValue(true)); @@ -207,12 +212,12 @@ class UriBuilderTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase */ public function buildBackendUriKeepsQueryParametersIfAddQueryStringIsSet() { - GeneralUtility::_GETset(['M' => 'moduleKey', 'id' => 'pageId', 'foo' => 'bar']); + GeneralUtility::_GETset(['route' => '/test/Path', 'id' => 'pageId', 'foo' => 'bar']); $_POST = []; $_POST['foo2'] = 'bar2'; $this->uriBuilder->setAddQueryString(true); $this->uriBuilder->setAddQueryStringMethod('GET,POST'); - $expectedResult = '/typo3/index.php?M=moduleKey&moduleToken=dummyToken&id=pageId&foo=bar&foo2=bar2'; + $expectedResult = '/typo3/index.php?route=%2Ftest%2FPath&token=dummyToken&id=pageId&foo=bar&foo2=bar2'; $actualResult = $this->uriBuilder->buildBackendUri(); $this->assertEquals($expectedResult, $actualResult); } @@ -222,12 +227,12 @@ class UriBuilderTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase */ public function buildBackendUriKeepsQueryParametersIfAddQueryStringMethodIsNotSet() { - GeneralUtility::_GETset(['M' => 'moduleKey', 'id' => 'pageId', 'foo' => 'bar']); + GeneralUtility::_GETset(['route' => '/test/Path', 'id' => 'pageId', 'foo' => 'bar']); $_POST = []; $_POST['foo2'] = 'bar2'; $this->uriBuilder->setAddQueryString(true); $this->uriBuilder->setAddQueryStringMethod(null); - $expectedResult = '/typo3/index.php?M=moduleKey&moduleToken=dummyToken&id=pageId&foo=bar'; + $expectedResult = '/typo3/index.php?route=%2Ftest%2FPath&token=dummyToken&id=pageId&foo=bar'; $actualResult = $this->uriBuilder->buildBackendUri(); $this->assertEquals($expectedResult, $actualResult); } @@ -240,7 +245,7 @@ class UriBuilderTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase return [ 'Arguments to be excluded in the beginning' => [ [ - 'M' => 'moduleKey', + 'route' => '/test/Path', 'id' => 'pageId', 'foo' => 'bar' ], @@ -248,25 +253,25 @@ class UriBuilderTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase 'foo2' => 'bar2' ], [ - 'M', + 'route', 'id' ], - '/typo3/index.php?M=&moduleToken=dummyToken&foo=bar&foo2=bar2' + '/typo3/index.php?route=&token=dummyToken&foo=bar&foo2=bar2' ], 'Arguments to be excluded in the end' => [ [ 'foo' => 'bar', 'id' => 'pageId', - 'M' => 'moduleKey' + 'route' => '/test/Path' ], [ 'foo2' => 'bar2' ], [ - 'M', + 'route', 'id' ], - '/typo3/index.php?M=&moduleToken=dummyToken&foo=bar&foo2=bar2' + '/typo3/index.php?route=&token=dummyToken&foo=bar&foo2=bar2' ], 'Arguments in nested array to be excluded' => [ [ @@ -274,7 +279,7 @@ class UriBuilderTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase 'bar' => 'baz' ], 'id' => 'pageId', - 'M' => 'moduleKey' + 'route' => '/test/Path' ], [ 'foo2' => 'bar2' @@ -283,7 +288,7 @@ class UriBuilderTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase 'id', 'tx_foo[bar]' ], - '/typo3/index.php?M=moduleKey&moduleToken=dummyToken&foo2=bar2' + '/typo3/index.php?route=%2Ftest%2FPath&token=dummyToken&foo2=bar2' ], 'Arguments in multidimensional array to be excluded' => [ [ @@ -293,7 +298,7 @@ class UriBuilderTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase ] ], 'id' => 'pageId', - 'M' => 'moduleKey' + 'route' => '/test/Path' ], [ 'foo2' => 'bar2' @@ -302,7 +307,7 @@ class UriBuilderTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase 'id', 'tx_foo[bar][baz]' ], - '/typo3/index.php?M=moduleKey&moduleToken=dummyToken&foo2=bar2' + '/typo3/index.php?route=%2Ftest%2FPath&token=dummyToken&foo2=bar2' ], ]; } @@ -331,8 +336,8 @@ class UriBuilderTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase */ public function buildBackendUriKeepsModuleQueryParametersIfAddQueryStringIsNotSet() { - GeneralUtility::_GETset(['M' => 'moduleKey', 'id' => 'pageId', 'foo' => 'bar']); - $expectedResult = '/typo3/index.php?M=moduleKey&moduleToken=dummyToken&id=pageId'; + GeneralUtility::_GETset(['route' => '/test/Path', 'id' => 'pageId', 'foo' => 'bar']); + $expectedResult = '/typo3/index.php?route=%2Ftest%2FPath&token=dummyToken&id=pageId'; $actualResult = $this->uriBuilder->buildBackendUri(); $this->assertEquals($expectedResult, $actualResult); } @@ -342,9 +347,9 @@ class UriBuilderTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase */ public function buildBackendUriMergesAndOverrulesQueryParametersWithArguments() { - GeneralUtility::_GETset(['M' => 'moduleKey', 'id' => 'pageId', 'foo' => 'bar']); - $this->uriBuilder->setArguments(['M' => 'overwrittenModuleKey', 'somePrefix' => ['bar' => 'baz']]); - $expectedResult = '/typo3/index.php?M=overwrittenModuleKey&moduleToken=dummyToken&id=pageId&somePrefix%5Bbar%5D=baz'; + GeneralUtility::_GETset(['route' => '/test/Path', 'id' => 'pageId', 'foo' => 'bar']); + $this->uriBuilder->setArguments(['route' => '/test/Path2', 'somePrefix' => ['bar' => 'baz']]); + $expectedResult = '/typo3/index.php?route=%2Ftest%2FPath2&token=dummyToken&id=pageId&somePrefix%5Bbar%5D=baz'; $actualResult = $this->uriBuilder->buildBackendUri(); $this->assertEquals($expectedResult, $actualResult); } @@ -354,11 +359,11 @@ class UriBuilderTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase */ public function buildBackendUriConvertsDomainObjectsAfterArgumentsHaveBeenMerged() { - GeneralUtility::_GETset(['M' => 'moduleKey']); + GeneralUtility::_GETset(['route' => '/test/Path']); $mockDomainObject = $this->getAccessibleMock(AbstractEntity::class, ['dummy']); $mockDomainObject->_set('uid', '123'); $this->uriBuilder->setArguments(['somePrefix' => ['someDomainObject' => $mockDomainObject]]); - $expectedResult = '/typo3/index.php?M=moduleKey&moduleToken=dummyToken&somePrefix%5BsomeDomainObject%5D=123'; + $expectedResult = '/typo3/index.php?route=%2Ftest%2FPath&token=dummyToken&somePrefix%5BsomeDomainObject%5D=123'; $actualResult = $this->uriBuilder->buildBackendUri(); $this->assertEquals($expectedResult, $actualResult); } @@ -368,9 +373,9 @@ class UriBuilderTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase */ public function buildBackendUriRespectsSection() { - GeneralUtility::_GETset(['M' => 'moduleKey']); + GeneralUtility::_GETset(['route' => '/test/Path']); $this->uriBuilder->setSection('someSection'); - $expectedResult = '/typo3/index.php?M=moduleKey&moduleToken=dummyToken#someSection'; + $expectedResult = '/typo3/index.php?route=%2Ftest%2FPath&token=dummyToken#someSection'; $actualResult = $this->uriBuilder->buildBackendUri(); $this->assertEquals($expectedResult, $actualResult); } @@ -381,12 +386,12 @@ class UriBuilderTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase public function buildBackendUriCreatesAbsoluteUrisIfSpecified() { GeneralUtility::flushInternalRuntimeCaches(); - GeneralUtility::_GETset(['M' => 'moduleKey']); + GeneralUtility::_GETset(['route' => '/test/Path']); $_SERVER['HTTP_HOST'] = 'baseuri'; $_SERVER['SCRIPT_NAME'] = '/typo3/index.php'; $this->mockRequest->expects($this->any())->method('getBaseUri')->will($this->returnValue('http://baseuri')); $this->uriBuilder->setCreateAbsoluteUri(true); - $expectedResult = 'http://baseuri/' . TYPO3_mainDir . 'index.php?M=moduleKey&moduleToken=dummyToken'; + $expectedResult = 'http://baseuri/' . TYPO3_mainDir . 'index.php?route=%2Ftest%2FPath&token=dummyToken'; $actualResult = $this->uriBuilder->buildBackendUri(); $this->assertSame($expectedResult, $actualResult); } @@ -419,7 +424,7 @@ class UriBuilderTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase ]; $this->uriBuilder->setAddQueryString(true); $this->uriBuilder->setAddQueryStringMethod('POST,GET'); - $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('/typo3/index.php?M=&moduleToken=dummyToken&key1=POST1&key2=GET2&key3[key31]=POST31&key3[key32]=GET32&key3[key33][key331]=GET331&key3[key33][key332]=POST332'); + $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('/typo3/index.php?route=&token=dummyToken&key1=POST1&key2=GET2&key3[key31]=POST31&key3[key32]=GET32&key3[key33][key331]=GET331&key3[key33][key332]=POST332'); $actualResult = $this->uriBuilder->buildBackendUri(); $this->assertEquals($expectedResult, $actualResult); } @@ -452,7 +457,7 @@ class UriBuilderTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase ]; $this->uriBuilder->setAddQueryString(true); $this->uriBuilder->setAddQueryStringMethod('GET,POST'); - $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('/typo3/index.php?M=&moduleToken=dummyToken&key1=GET1&key2=POST2&key3[key31]=GET31&key3[key32]=POST32&key3[key33][key331]=POST331&key3[key33][key332]=GET332'); + $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('/typo3/index.php?route=&token=dummyToken&key1=GET1&key2=POST2&key3[key31]=GET31&key3[key32]=POST32&key3[key33][key331]=POST331&key3[key33][key332]=GET332'); $actualResult = $this->uriBuilder->buildBackendUri(); $this->assertEquals($expectedResult, $actualResult); } diff --git a/typo3/sysext/filelist/Classes/FileList.php b/typo3/sysext/filelist/Classes/FileList.php index fe821d987900..207bd6b3be77 100644 --- a/typo3/sysext/filelist/Classes/FileList.php +++ b/typo3/sysext/filelist/Classes/FileList.php @@ -16,7 +16,6 @@ namespace TYPO3\CMS\Filelist; use TYPO3\CMS\Backend\Clipboard\Clipboard; use TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider; -use TYPO3\CMS\Backend\Routing\Router; use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Database\ConnectionPool; @@ -1489,12 +1488,8 @@ class FileList protected function determineScriptUrl() { if ($routePath = GeneralUtility::_GP('route')) { - $router = GeneralUtility::makeInstance(Router::class); - $route = $router->match($routePath); $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); - $this->thisScript = (string)$uriBuilder->buildUriFromRoute($route->getOption('_identifier')); - } elseif ($moduleName = GeneralUtility::_GP('M')) { - $this->thisScript = BackendUtility::getModuleUrl($moduleName); + $this->thisScript = (string)$uriBuilder->buildUriFromRoutePath($routePath); } else { $this->thisScript = GeneralUtility::getIndpEnv('SCRIPT_NAME'); } diff --git a/typo3/sysext/fluid/Classes/ViewHelpers/Be/Buttons/ShortcutViewHelper.php b/typo3/sysext/fluid/Classes/ViewHelpers/Be/Buttons/ShortcutViewHelper.php index 9e838b9c21c3..12ba44799249 100644 --- a/typo3/sysext/fluid/Classes/ViewHelpers/Be/Buttons/ShortcutViewHelper.php +++ b/typo3/sysext/fluid/Classes/ViewHelpers/Be/Buttons/ShortcutViewHelper.php @@ -34,7 +34,7 @@ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; * </output> * * <code title="Explicitly set parameters to be stored in the shortcut"> - * <f:be.buttons.shortcut getVars="{0: 'M', 1: 'myOwnPrefix'}" setVars="{0: 'function'}" /> + * <f:be.buttons.shortcut getVars="{0: 'route', 1: 'myOwnPrefix'}" setVars="{0: 'function'}" /> * </code> * <output> * Shortcut button as known from the TYPO3 backend. @@ -99,7 +99,7 @@ class ShortcutViewHelper extends AbstractBackendViewHelper $moduleName = $currentRequest->getPluginName(); if (count($getVars) === 0) { $modulePrefix = strtolower('tx_' . $extensionName . '_' . $moduleName); - $getVars = ['id', 'M', $modulePrefix]; + $getVars = ['id', 'route', $modulePrefix]; } $getList = implode(',', $getVars); $setList = implode(',', $setVars); diff --git a/typo3/sysext/form/Classes/Controller/FormManagerController.php b/typo3/sysext/form/Classes/Controller/FormManagerController.php index 353eb05a6b72..80b473f97689 100644 --- a/typo3/sysext/form/Classes/Controller/FormManagerController.php +++ b/typo3/sysext/form/Classes/Controller/FormManagerController.php @@ -427,7 +427,7 @@ class FormManagerController extends AbstractBackendController $extensionName = $currentRequest->getControllerExtensionName(); if (count($getVars) === 0) { $modulePrefix = strtolower('tx_' . $extensionName . '_' . $moduleName); - $getVars = ['id', 'M', $modulePrefix]; + $getVars = ['id', 'route', $modulePrefix]; } $shortcutButton = $buttonBar->makeShortcutButton() diff --git a/typo3/sysext/info/Classes/Controller/InfoModuleController.php b/typo3/sysext/info/Classes/Controller/InfoModuleController.php index 309fe694305d..24426a349ed4 100644 --- a/typo3/sysext/info/Classes/Controller/InfoModuleController.php +++ b/typo3/sysext/info/Classes/Controller/InfoModuleController.php @@ -172,7 +172,7 @@ class InfoModuleController extends BaseScriptClass ->setModuleName($this->moduleName) ->setDisplayName($this->MOD_MENU['function'][$this->MOD_SETTINGS['function']]) ->setGetVariables([ - 'M', + 'route', 'id', 'edit_record', 'pointer', diff --git a/typo3/sysext/install/Configuration/ExtensionScanner/Php/ClassNameMatcher.php b/typo3/sysext/install/Configuration/ExtensionScanner/Php/ClassNameMatcher.php index ba0746a6be33..3f2af70a4755 100644 --- a/typo3/sysext/install/Configuration/ExtensionScanner/Php/ClassNameMatcher.php +++ b/typo3/sysext/install/Configuration/ExtensionScanner/Php/ClassNameMatcher.php @@ -379,6 +379,11 @@ return [ 'Breaking-55298-DecoupledHistoryFunctionality.rst', ], ], + 'TYPO3\CMS\Backend\Http\BackendModuleRequestHandler' => [ + 'restFiles' => [ + 'Breaking-82406-RoutingBackendModulesRunThroughRegularDispatcher.rst', + ], + ], // Removed interfaces 'TYPO3\CMS\Backend\Form\DatabaseFileIconsHookInterface' => [ diff --git a/typo3/sysext/lowlevel/Classes/Utility/ArrayBrowser.php b/typo3/sysext/lowlevel/Classes/Utility/ArrayBrowser.php index 01700abf698c..a7051053c318 100644 --- a/typo3/sysext/lowlevel/Classes/Utility/ArrayBrowser.php +++ b/typo3/sysext/lowlevel/Classes/Utility/ArrayBrowser.php @@ -109,7 +109,7 @@ class ArrayBrowser $output .= '<li' . ($isResult ? ' class="active"' : '') . '>'; if ($isArray && !$this->expAll) { $goto = 'a' . substr(md5($depth), 0, 6); - $output .= '<a class="list-tree-control' . ($isExpanded ? ' list-tree-control-open' : ' list-tree-control-closed') . '" id="' . $goto . '" href="' . htmlspecialchars((BackendUtility::getModuleUrl(GeneralUtility::_GP('M')) . '&node[' . $depth . ']=' . ($isExpanded ? 0 : 1) . '#' . $goto)) . '"><i class="fa"></i></a> '; + $output .= '<a class="list-tree-control' . ($isExpanded ? ' list-tree-control-open' : ' list-tree-control-closed') . '" id="' . $goto . '" href="' . htmlspecialchars((BackendUtility::getModuleUrl(GeneralUtility::_GP('route')) . '&node[' . $depth . ']=' . ($isExpanded ? 0 : 1) . '#' . $goto)) . '"><i class="fa"></i></a> '; } $output .= '<span class="list-tree-group">'; $output .= $this->wrapArrayKey($key, $depth, !$isArray ? $value : ''); @@ -149,7 +149,7 @@ class ArrayBrowser . (!MathUtility::canBeInterpretedAsInteger($theValue) ? '\'' . addslashes($theValue) . '\'' : $theValue) . '; '; $label = '<a class="list-tree-label" href="' - . htmlspecialchars((BackendUtility::getModuleUrl(GeneralUtility::_GP('M')) + . htmlspecialchars((BackendUtility::getModuleUrl(GeneralUtility::_GP('route')) . '&varname=' . urlencode($variableName))) . '#varname">' . $label . '</a>'; } diff --git a/typo3/sysext/recordlist/Classes/Browser/AbstractElementBrowser.php b/typo3/sysext/recordlist/Classes/Browser/AbstractElementBrowser.php index f1b277fd86a0..2e819dad6fd0 100644 --- a/typo3/sysext/recordlist/Classes/Browser/AbstractElementBrowser.php +++ b/typo3/sysext/recordlist/Classes/Browser/AbstractElementBrowser.php @@ -14,10 +14,8 @@ namespace TYPO3\CMS\Recordlist\Browser; * The TYPO3 project - inspiring people to share! */ -use TYPO3\CMS\Backend\Routing\Router; use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Backend\Template\DocumentTemplate; -use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; use TYPO3\CMS\Core\Imaging\IconFactory; use TYPO3\CMS\Core\Localization\LanguageService; @@ -106,12 +104,8 @@ abstract class AbstractElementBrowser protected function determineScriptUrl() { if ($routePath = GeneralUtility::_GP('route')) { - $router = GeneralUtility::makeInstance(Router::class); - $route = $router->match($routePath); $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); - $this->thisScript = (string)$uriBuilder->buildUriFromRoute($route->getOption('_identifier')); - } elseif ($moduleName = GeneralUtility::_GP('M')) { - $this->thisScript = BackendUtility::getModuleUrl($moduleName); + $this->thisScript = (string)$uriBuilder->buildUriFromRoutePath($routePath); } else { $this->thisScript = GeneralUtility::getIndpEnv('SCRIPT_NAME'); } diff --git a/typo3/sysext/recordlist/Classes/Controller/AbstractLinkBrowserController.php b/typo3/sysext/recordlist/Classes/Controller/AbstractLinkBrowserController.php index c1dbc264a8dd..fe40625bb78f 100644 --- a/typo3/sysext/recordlist/Classes/Controller/AbstractLinkBrowserController.php +++ b/typo3/sysext/recordlist/Classes/Controller/AbstractLinkBrowserController.php @@ -16,7 +16,6 @@ namespace TYPO3\CMS\Recordlist\Controller; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use TYPO3\CMS\Backend\Routing\Router; use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Backend\Template\DocumentTemplate; use TYPO3\CMS\Backend\Utility\BackendUtility; @@ -209,12 +208,8 @@ abstract class AbstractLinkBrowserController protected function determineScriptUrl(ServerRequestInterface $request) { if ($routePath = $request->getQueryParams()['route']) { - $router = GeneralUtility::makeInstance(Router::class); - $route = $router->match($routePath); $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); - $this->thisScript = (string)$uriBuilder->buildUriFromRoute($route->getOption('_identifier')); - } elseif ($moduleName = $request->getQueryParams()['M']) { - $this->thisScript = BackendUtility::getModuleUrl($moduleName); + $this->thisScript = (string)$uriBuilder->buildUriFromRoutePath($routePath); } else { $this->thisScript = GeneralUtility::getIndpEnv('SCRIPT_NAME'); } diff --git a/typo3/sysext/recordlist/Classes/RecordList/AbstractDatabaseRecordList.php b/typo3/sysext/recordlist/Classes/RecordList/AbstractDatabaseRecordList.php index 1b3b1dde87cf..672ff22b063b 100644 --- a/typo3/sysext/recordlist/Classes/RecordList/AbstractDatabaseRecordList.php +++ b/typo3/sysext/recordlist/Classes/RecordList/AbstractDatabaseRecordList.php @@ -15,7 +15,6 @@ namespace TYPO3\CMS\Recordlist\RecordList; */ use TYPO3\CMS\Backend\RecordList\AbstractRecordList; -use TYPO3\CMS\Backend\Routing\Router; use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Backend\Tree\View\PageTreeView; use TYPO3\CMS\Backend\Utility\BackendUtility; @@ -1189,12 +1188,8 @@ class AbstractDatabaseRecordList extends AbstractRecordList $urlParameters = array_merge_recursive($urlParameters, $this->overrideUrlParameters); if ($routePath = GeneralUtility::_GP('route')) { - $router = GeneralUtility::makeInstance(Router::class); - $route = $router->match($routePath); $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); - $url = (string)$uriBuilder->buildUriFromRoute($route->getOption('_identifier'), $urlParameters); - } elseif ($moduleName = GeneralUtility::_GP('M')) { - $url = BackendUtility::getModuleUrl($moduleName, $urlParameters); + $url = (string)$uriBuilder->buildUriFromRoutePath($routePath, $urlParameters); } else { $url = GeneralUtility::getIndpEnv('SCRIPT_NAME') . '?' . ltrim(GeneralUtility::implodeArrayForUrl('', $urlParameters), '&'); } diff --git a/typo3/sysext/recordlist/Classes/RecordList/DatabaseRecordList.php b/typo3/sysext/recordlist/Classes/RecordList/DatabaseRecordList.php index 4da1c9e42d07..bd6d78f10e3c 100644 --- a/typo3/sysext/recordlist/Classes/RecordList/DatabaseRecordList.php +++ b/typo3/sysext/recordlist/Classes/RecordList/DatabaseRecordList.php @@ -17,7 +17,6 @@ namespace TYPO3\CMS\Recordlist\RecordList; use TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider; use TYPO3\CMS\Backend\Module\BaseScriptClass; use TYPO3\CMS\Backend\RecordList\RecordListGetTableHookInterface; -use TYPO3\CMS\Backend\Routing\Router; use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Backend\Template\Components\ButtonBar; use TYPO3\CMS\Backend\Template\DocumentTemplate; @@ -869,7 +868,7 @@ class DatabaseRecordList ->setModuleName('web_list') ->setGetVariables([ 'id', - 'M', + 'route', 'imagemode', 'pointer', 'table', @@ -3580,12 +3579,8 @@ class DatabaseRecordList $urlParameters = array_merge_recursive($urlParameters, $this->overrideUrlParameters); if ($routePath = GeneralUtility::_GP('route')) { - $router = GeneralUtility::makeInstance(Router::class); - $route = $router->match($routePath); $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); - $url = (string)$uriBuilder->buildUriFromRoute($route->getOption('_identifier'), $urlParameters); - } elseif ($moduleName = GeneralUtility::_GP('M')) { - $url = BackendUtility::getModuleUrl($moduleName, $urlParameters); + $url = (string)$uriBuilder->buildUriFromRoutePath($routePath, $urlParameters); } else { $url = GeneralUtility::getIndpEnv('SCRIPT_NAME') . '?' . ltrim( GeneralUtility::implodeArrayForUrl('', $urlParameters), @@ -4152,12 +4147,8 @@ class DatabaseRecordList protected function determineScriptUrl() { if ($routePath = GeneralUtility::_GP('route')) { - $router = GeneralUtility::makeInstance(Router::class); - $route = $router->match($routePath); $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); - $this->thisScript = (string)$uriBuilder->buildUriFromRoute($route->getOption('_identifier')); - } elseif ($moduleName = GeneralUtility::_GP('M')) { - $this->thisScript = BackendUtility::getModuleUrl($moduleName); + $this->thisScript = (string)$uriBuilder->buildUriFromRoutePath($routePath); } else { $this->thisScript = GeneralUtility::getIndpEnv('SCRIPT_NAME'); } diff --git a/typo3/sysext/recycler/Classes/Controller/RecyclerModuleController.php b/typo3/sysext/recycler/Classes/Controller/RecyclerModuleController.php index f6e98fc21527..a60914e29ece 100644 --- a/typo3/sysext/recycler/Classes/Controller/RecyclerModuleController.php +++ b/typo3/sysext/recycler/Classes/Controller/RecyclerModuleController.php @@ -148,7 +148,7 @@ class RecyclerModuleController extends ActionController $extensionName = $currentRequest->getControllerExtensionName(); if (count($getVars) === 0) { $modulePrefix = strtolower('tx_' . $extensionName . '_' . $moduleName); - $getVars = ['id', 'M', $modulePrefix]; + $getVars = ['id', 'route', $modulePrefix]; } $shortcutButton = $buttonBar->makeShortcutButton() ->setModuleName($moduleName) diff --git a/typo3/sysext/reports/Classes/Controller/ReportController.php b/typo3/sysext/reports/Classes/Controller/ReportController.php index 36f1cf864cb4..6a2054231b5b 100644 --- a/typo3/sysext/reports/Classes/Controller/ReportController.php +++ b/typo3/sysext/reports/Classes/Controller/ReportController.php @@ -172,7 +172,7 @@ class ReportController extends ActionController $setVars = $this->request->hasArgument('setVars') ? $this->request->getArgument('setVars') : []; if (count($getVars) === 0) { $modulePrefix = strtolower('tx_' . $this->request->getControllerExtensionName() . '_' . $moduleName); - $getVars = ['id', 'M', $modulePrefix]; + $getVars = ['id', 'route', $modulePrefix]; } $shortcutButton = $buttonBar->makeShortcutButton() ->setModuleName($moduleName) diff --git a/typo3/sysext/tstemplate/Classes/Controller/TypoScriptTemplateModuleController.php b/typo3/sysext/tstemplate/Classes/Controller/TypoScriptTemplateModuleController.php index 7b669e00204d..d3532ba7b161 100644 --- a/typo3/sysext/tstemplate/Classes/Controller/TypoScriptTemplateModuleController.php +++ b/typo3/sysext/tstemplate/Classes/Controller/TypoScriptTemplateModuleController.php @@ -362,7 +362,7 @@ class TypoScriptTemplateModuleController extends BaseScriptClass // Shortcut $shortcutButton = $buttonBar->makeShortcutButton() ->setModuleName($this->MCONF['name']) - ->setGetVariables(['id', 'M']); + ->setGetVariables(['id', 'route']); $buttonBar->addButton($shortcutButton); } diff --git a/typo3/sysext/viewpage/Classes/Controller/ViewModuleController.php b/typo3/sysext/viewpage/Classes/Controller/ViewModuleController.php index 8c2725e1bc6a..de87dd2f468c 100644 --- a/typo3/sysext/viewpage/Classes/Controller/ViewModuleController.php +++ b/typo3/sysext/viewpage/Classes/Controller/ViewModuleController.php @@ -103,7 +103,7 @@ class ViewModuleController extends ActionController $extensionName = $currentRequest->getControllerExtensionName(); if (count($getVars) === 0) { $modulePrefix = strtolower('tx_' . $extensionName . '_' . $moduleName); - $getVars = ['id', 'M', $modulePrefix]; + $getVars = ['id', 'route', $modulePrefix]; } $shortcutButton = $buttonBar->makeShortcutButton() ->setModuleName($moduleName) diff --git a/typo3/sysext/workspaces/Classes/Controller/PreviewController.php b/typo3/sysext/workspaces/Classes/Controller/PreviewController.php index 079b4a81625e..7945dcc6d0bb 100644 --- a/typo3/sysext/workspaces/Classes/Controller/PreviewController.php +++ b/typo3/sysext/workspaces/Classes/Controller/PreviewController.php @@ -87,7 +87,7 @@ class PreviewController extends AbstractController // Remove the GET parameters related to the workspaces module and the page id unset($queryParameters['tx_workspaces_web_workspacesworkspaces']); - unset($queryParameters['M']); + unset($queryParameters['route']); unset($queryParameters['id']); // Assemble a query string from the retrieved parameters diff --git a/typo3/sysext/workspaces/Classes/Controller/ReviewController.php b/typo3/sysext/workspaces/Classes/Controller/ReviewController.php index 22279a17ad41..6c21f5a0dd2a 100644 --- a/typo3/sysext/workspaces/Classes/Controller/ReviewController.php +++ b/typo3/sysext/workspaces/Classes/Controller/ReviewController.php @@ -50,7 +50,7 @@ class ReviewController extends AbstractController $extensionName = $currentRequest->getControllerExtensionName(); if (count($getVars) === 0) { $modulePrefix = strtolower('tx_' . $extensionName . '_' . $moduleName); - $getVars = ['id', 'M', $modulePrefix]; + $getVars = ['id', 'route', $modulePrefix]; } $shortcutButton = $buttonBar->makeShortcutButton() ->setModuleName($moduleName) diff --git a/typo3/sysext/workspaces/Classes/Service/WorkspaceService.php b/typo3/sysext/workspaces/Classes/Service/WorkspaceService.php index f03a1c48d539..ba257964be14 100644 --- a/typo3/sysext/workspaces/Classes/Service/WorkspaceService.php +++ b/typo3/sysext/workspaces/Classes/Service/WorkspaceService.php @@ -863,10 +863,10 @@ class WorkspaceService implements SingletonInterface $uriBuilder = $this->getObjectManager()->get(\TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder::class); $redirect = 'index.php?redirect_url='; // @todo this should maybe be changed so that the extbase URI Builder can deal with module names directly - $originalM = GeneralUtility::_GET('M'); - GeneralUtility::_GETset('web_WorkspacesWorkspaces', 'M'); + $originalM = GeneralUtility::_GET('route'); + GeneralUtility::_GETset('web_WorkspacesWorkspaces', 'route'); $viewScript = $uriBuilder->uriFor('index', [], 'Preview', 'workspaces', 'web_workspacesworkspaces') . '&id='; - GeneralUtility::_GETset($originalM, 'M'); + GeneralUtility::_GETset($originalM, 'route'); if ($addDomain === true) { return BackendUtility::getViewDomain($uid) . $redirect . urlencode($viewScript) . $uid; } -- GitLab