diff --git a/typo3/sysext/backend/Classes/Routing/UriBuilder.php b/typo3/sysext/backend/Classes/Routing/UriBuilder.php index 6086927ac16a07c5c9a91c7a1af72b33b134a855..10e998d8bff035e060c7e714f3143394ebb79dc3 100644 --- a/typo3/sysext/backend/Classes/Routing/UriBuilder.php +++ b/typo3/sysext/backend/Classes/Routing/UriBuilder.php @@ -121,9 +121,11 @@ class UriBuilder * @param string $referenceType The type of reference to be generated (one of the constants) * * @return Uri The generated Uri + * @deprecated since TYPO3 v9.3, will be removed in TYPO3 v10. Use buildUriFromRoute() instead. */ public function buildUriFromModule($moduleName, $parameters = [], $referenceType = self::ABSOLUTE_PATH) { + trigger_error('UriBuilder->buildUriFromModule() will be removed in TYPO3 v10, use buildUriFromRoute() instead.', E_USER_DEPRECATED); $parameters = [ 'route' => $moduleName, 'token' => FormProtectionFactory::get('backend')->generateToken('route', $moduleName) diff --git a/typo3/sysext/backend/Classes/Utility/BackendUtility.php b/typo3/sysext/backend/Classes/Utility/BackendUtility.php index b6476d9f881925d95c41909e69ba3d8dab11e1e1..5f33c73ab4144443fb6192a3cd6d603a51683f86 100644 --- a/typo3/sysext/backend/Classes/Utility/BackendUtility.php +++ b/typo3/sysext/backend/Classes/Utility/BackendUtility.php @@ -3205,10 +3205,11 @@ class BackendUtility * @param string $moduleName Name of the module * @param array $urlParameters URL parameters that should be added as key value pairs * @return string Calculated URL + * @deprecated since TYPO3 v9, will be removed in TYPO3 v10. Use UriBuilder instead. */ public static function getModuleUrl($moduleName, $urlParameters = []) { - /** @var UriBuilder $uriBuilder */ + trigger_error('BackendUtility::getModuleUrl() will be removed in TYPO3 v10, use UriBuilder->buildUriFromRoute() instead.', E_USER_DEPRECATED); $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); try { $uri = $uriBuilder->buildUriFromRoute($moduleName, $urlParameters); diff --git a/typo3/sysext/core/Classes/Utility/ExtensionManagementUtility.php b/typo3/sysext/core/Classes/Utility/ExtensionManagementUtility.php index f588433d68ce18365459c7c0e52c245f6a77e8a4..7e647b832e3777e48652d4a9a07f985ee7e4196e 100644 --- a/typo3/sysext/core/Classes/Utility/ExtensionManagementUtility.php +++ b/typo3/sysext/core/Classes/Utility/ExtensionManagementUtility.php @@ -15,6 +15,8 @@ namespace TYPO3\CMS\Core\Utility; */ use Symfony\Component\Finder\Finder; +use TYPO3\CMS\Backend\Routing\Route; +use TYPO3\CMS\Backend\Routing\Router; use TYPO3\CMS\Core\Category\CategoryRegistry; use TYPO3\CMS\Core\Core\Environment; use TYPO3\CMS\Core\Imaging\IconRegistry; @@ -904,13 +906,9 @@ class ExtensionManagementUtility } // Also register the module as regular route + $routeName = $moduleConfiguration['id'] ?? $fullModuleSignature; // Build Route objects from the data - $name = $fullModuleSignature; - if (isset($moduleConfiguration['path'])) { - $path = $moduleConfiguration['path']; - } else { - $path = str_replace('_', '/', $name); - } + $path = $moduleConfiguration['path'] ?? str_replace('_', '/', $fullModuleSignature); $path = '/' . trim($path, '/') . '/'; $options = [ @@ -922,12 +920,8 @@ class ExtensionManagementUtility $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) - ); + $router = GeneralUtility::makeInstance(Router::class); + $router->addRoute($routeName, GeneralUtility::makeInstance(Route::class, $path, $options)); } /** diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-85113-LegacyBackendModuleRoutingMethods.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-85113-LegacyBackendModuleRoutingMethods.rst new file mode 100644 index 0000000000000000000000000000000000000000..7bb6cb6e0f9cc1d0fcf6c56532f3025ba1ac23f6 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-85113-LegacyBackendModuleRoutingMethods.rst @@ -0,0 +1,38 @@ +.. include:: ../../Includes.txt + +=========================================================== +Deprecation: #85113 - Legacy Backend Module Routing methods +=========================================================== + +See :issue:`85113` + +Description +=========== + +In TYPO3 v9, Backend routing was unified to be handled via the "route" query string parameter. Backend modules +are now automatically registered to be a backend route. + +The following methods are thus deprecated in favor of using the method above. + +* :php:`BackendUtility::getModuleUrl()` +* :php:`UriBuilder->buildUriFromModule()` + + +Impact +====== + +Calling one of the deprecated methods above will trigger a deprecation message. + + +Affected Installations +====================== + +Any TYPO3 installation with a custom backend-related extension using one of the methods directly in a PHP context. + + +Migration +========= + +Use :php:`UriBuilder->buildUriFromRoute($moduleIdentifier)` instead. + +.. index:: Backend, PHP-API, FullyScanned diff --git a/typo3/sysext/extbase/Classes/Mvc/Web/Routing/UriBuilder.php b/typo3/sysext/extbase/Classes/Mvc/Web/Routing/UriBuilder.php index 9d8dbd1dcbae84ac05af67c626c7aaf28dfb9a58..ea6b929bb5559cd6019d2b14223efec01afcbc47 100644 --- a/typo3/sysext/extbase/Classes/Mvc/Web/Routing/UriBuilder.php +++ b/typo3/sysext/extbase/Classes/Mvc/Web/Routing/UriBuilder.php @@ -15,6 +15,7 @@ namespace TYPO3\CMS\Extbase\Mvc\Web\Routing; */ use TYPO3\CMS\Backend\Routing\Exception\ResourceNotFoundException; +use TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException; use TYPO3\CMS\Core\Utility\ArrayUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Mvc\Request; @@ -667,31 +668,35 @@ class UriBuilder $id = GeneralUtility::_GP('id'); // backwards compatibility: check for M parameter // @deprecated since TYPO3 CMS 9, will be removed in TYPO3 CMS 10. - $module = GeneralUtility::_GP('route') ?: GeneralUtility::_GP('M'); + $route = GeneralUtility::_GP('route') ?: GeneralUtility::_GP('M'); if ($id !== null) { $arguments['id'] = $id; } - if ($module !== null) { - $arguments['route'] = $module; + if ($route !== null) { + $arguments['route'] = $route; } } ArrayUtility::mergeRecursiveWithOverrule($arguments, $this->arguments); $arguments = $this->convertDomainObjectsToIdentityArrays($arguments); $this->lastArguments = $arguments; - $moduleName = $arguments['route'] ?? null; + $routeName = $arguments['route'] ?? null; unset($arguments['route'], $arguments['token']); $backendUriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class); try { if ($this->request instanceof WebRequest && $this->createAbsoluteUri) { - $uri = (string)$backendUriBuilder->buildUriFromRoutePath($moduleName, $arguments, \TYPO3\CMS\Backend\Routing\UriBuilder::ABSOLUTE_URL); + $uri = (string)$backendUriBuilder->buildUriFromRoutePath($routeName, $arguments, \TYPO3\CMS\Backend\Routing\UriBuilder::ABSOLUTE_URL); } else { - $uri = (string)$backendUriBuilder->buildUriFromRoutePath($moduleName, $arguments, \TYPO3\CMS\Backend\Routing\UriBuilder::ABSOLUTE_PATH); + $uri = (string)$backendUriBuilder->buildUriFromRoutePath($routeName, $arguments, \TYPO3\CMS\Backend\Routing\UriBuilder::ABSOLUTE_PATH); } } catch (ResourceNotFoundException $e) { - 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); + try { + if ($this->request instanceof WebRequest && $this->createAbsoluteUri) { + $uri = (string)$backendUriBuilder->buildUriFromRoute($routeName, $arguments, \TYPO3\CMS\Backend\Routing\UriBuilder::ABSOLUTE_URL); + } else { + $uri = (string)$backendUriBuilder->buildUriFromRoute($routeName, $arguments, \TYPO3\CMS\Backend\Routing\UriBuilder::ABSOLUTE_PATH); + } + } catch (RouteNotFoundException $e) { + $uri = ''; } } if ($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 5cf4d0ba5d88fe5212b64de1c70f122394137b02..f84b16007f88ecaa4866f35cda600be16f3fe11a 100644 --- a/typo3/sysext/extbase/Tests/Unit/Mvc/Web/Routing/UriBuilderTest.php +++ b/typo3/sysext/extbase/Tests/Unit/Mvc/Web/Routing/UriBuilderTest.php @@ -83,6 +83,7 @@ class UriBuilderTest extends UnitTestCase $router = GeneralUtility::makeInstance(Router::class); $router->addRoute('module_key', new Route('/test/Path', [])); $router->addRoute('module_key2', new Route('/test/Path2', [])); + $router->addRoute('', new Route('', [])); // 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)); @@ -258,7 +259,7 @@ class UriBuilderTest extends UnitTestCase 'route', 'id' ], - '/typo3/index.php?route=&token=dummyToken&foo=bar&foo2=bar2' + '/typo3/index.php?route=%2F&token=dummyToken&foo=bar&foo2=bar2' ], 'Arguments to be excluded in the end' => [ [ @@ -273,7 +274,7 @@ class UriBuilderTest extends UnitTestCase 'route', 'id' ], - '/typo3/index.php?route=&token=dummyToken&foo=bar&foo2=bar2' + '/typo3/index.php?route=%2F&token=dummyToken&foo=bar&foo2=bar2' ], 'Arguments in nested array to be excluded' => [ [ @@ -428,7 +429,7 @@ class UriBuilderTest extends UnitTestCase ]; $this->uriBuilder->setAddQueryString(true); $this->uriBuilder->setAddQueryStringMethod('POST,GET'); - $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'); + $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('/typo3/index.php?route=%2F&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); } @@ -461,7 +462,7 @@ class UriBuilderTest extends UnitTestCase ]; $this->uriBuilder->setAddQueryString(true); $this->uriBuilder->setAddQueryStringMethod('GET,POST'); - $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'); + $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('/typo3/index.php?route=%2F&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/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php index 3dfd8857984569bcebc0b1aec686ed2a77704204..60cd80afcebc4f625f86809c15a42c84e521e9e3 100644 --- a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php +++ b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php @@ -2317,4 +2317,11 @@ return [ 'Deprecation-85125-UsagesOfCharsetConverterInCore.rst' ], ], + 'TYPO3\CMS\Backend\Routing\UriBuilder->buildUriFromModule' => [ + 'numberOfMandatoryArguments' => 0, + 'maximumNumberOfArguments' => 0, + 'restFiles' => [ + 'Deprecation-85113-LegacyBackendModuleRoutingMethods.rst', + ] + ], ]; diff --git a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallStaticMatcher.php b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallStaticMatcher.php index a47d5faae27d313b065fc14badb5eddc96af5098..08b1ec3608504f404725b1f5f66fc2510baf27b0 100644 --- a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallStaticMatcher.php +++ b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallStaticMatcher.php @@ -596,4 +596,11 @@ return [ 'Deprecation-85102-PhpOptionsUtility.rst', ], ], + 'TYPO3\CMS\Backend\Utility\BackendUtility::getModuleUrl' => [ + 'numberOfMandatoryArguments' => 1, + 'maximumNumberOfArguments' => 2, + 'restFiles' => [ + 'Deprecation-85113-LegacyBackendModuleRoutingMethods.rst', + ], + ], ]; diff --git a/typo3/sysext/recordlist/Classes/RecordList/DatabaseRecordList.php b/typo3/sysext/recordlist/Classes/RecordList/DatabaseRecordList.php index b1d5d64abcd0ae8c15527e0544314388e3ccc348..0acccfe93d1ce720ff1e0c58afba5f8234d38cb7 100644 --- a/typo3/sysext/recordlist/Classes/RecordList/DatabaseRecordList.php +++ b/typo3/sysext/recordlist/Classes/RecordList/DatabaseRecordList.php @@ -2002,7 +2002,7 @@ class DatabaseRecordList if ($this->isEditable($table)) { // "Revert" link (history/undo) if ((bool)\trim($userTsConfig['options.']['showHistory.'][$table] ?? $userTsConfig['options.']['showHistory'] ?? '1')) { - $moduleUrl = BackendUtility::getModuleUrl('record_history', ['element' => $table . ':' . $row['uid']]); + $moduleUrl = (string)$uriBuilder->buildUriFromRoute('record_history', ['element' => $table . ':' . $row['uid']]); $onClick = 'return jumpExt(' . GeneralUtility::quoteJSvalue($moduleUrl) . ',\'#latest\');'; $historyAction = '<a class="btn btn-default" href="#" onclick="' . htmlspecialchars($onClick) . '" title="' . htmlspecialchars($this->getLanguageService()->getLL('history')) . '">'