diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-60272-SkipCacheHashForUrisToNonCacheableActions.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-60272-SkipCacheHashForUrisToNonCacheableActions.rst new file mode 100644 index 0000000000000000000000000000000000000000..f78286be7c8f92679f968350a0068fe92f40cc53 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Breaking-60272-SkipCacheHashForUrisToNonCacheableActions.rst @@ -0,0 +1,22 @@ +==================================================================== +Breaking: #60272 - Skip cache hash for URIs to non-cacheable actions +==================================================================== + +Description +=========== + +The cache hash (cHash) parameter is not added to action URIs if the current +request is not cached and the target action is not cacheable. + +Impact +====== + +Less cache entries are generated per page and not every action URI will have +a cHash argument any more. It might be necessary to clear caches of extensions +generating human readable URLs like RealURL. + +Affected installations +====================== + +Extbase extensions that generate links from uncached actions/pages to not +cacheable actions. diff --git a/typo3/sysext/extbase/Classes/Mvc/Web/Routing/UriBuilder.php b/typo3/sysext/extbase/Classes/Mvc/Web/Routing/UriBuilder.php index aecdecdb3055c5c0c90a4eecf5633e0eed476e48..c67bc983b6b9670f0e8ceac3965a4b3f5b5e17d6 100644 --- a/typo3/sysext/extbase/Classes/Mvc/Web/Routing/UriBuilder.php +++ b/typo3/sysext/extbase/Classes/Mvc/Web/Routing/UriBuilder.php @@ -510,6 +510,9 @@ class UriBuilder { if ($pluginName === NULL) { $pluginName = $this->request->getPluginName(); } + + $this->disableCacheHashForNonCacheableAction($controllerArguments); + if ($this->environmentService->isEnvironmentInFrontendMode() && $this->configurationManager->isFeatureEnabled('skipDefaultArguments')) { $controllerArguments = $this->removeDefaultControllerAndAction($controllerArguments, $extensionName, $pluginName); } @@ -529,6 +532,25 @@ class UriBuilder { return $this->build(); } + /** + * Disable cache hash if the action is not cacheable + * and pointed to from an already uncached request + * + * @param array $controllerArguments the current controller arguments + * @return void + */ + protected function disableCacheHashForNonCacheableAction(array $controllerArguments) { + if (isset($controllerArguments['action']) && $this->getUseCacheHash()) { + $actionIsCacheable = $this->extensionService->isActionCacheable( + NULL, + NULL, + $controllerArguments['controller'], + $controllerArguments['action'] + ); + $this->setUseCacheHash($this->request->isCached() || $actionIsCacheable); + } + } + /** * This removes controller and/or action arguments from given controllerArguments * if they are equal to the default controller/action of the target plugin. 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 d3fa9aaf63fd93c6b957a238a47679cb7f2151bf..5fd52211ad310bfb7f9d7dacd621de1ed312dde1 100644 --- a/typo3/sysext/extbase/Tests/Unit/Mvc/Web/Routing/UriBuilderTest.php +++ b/typo3/sysext/extbase/Tests/Unit/Mvc/Web/Routing/UriBuilderTest.php @@ -151,12 +151,45 @@ class UriBuilderTest extends \TYPO3\CMS\Core\Tests\UnitTestCase { } /** + * @param bool $isActionCacheable + * @param bool $requestIsCached + * @param bool $expectedUseCacheHash * @test + * @dataProvider uriForDisablesCacheHashIfPossibleDataProvider */ - public function uriForDoesNotDisableCacheHashForNonCacheableActions() { - $this->mockExtensionService->expects($this->any())->method('isActionCacheable')->will($this->returnValue(FALSE)); + public function uriForDisablesCacheHashIfPossible($isActionCacheable, $requestIsCached, $expectedUseCacheHash) { + $this->mockExtensionService->expects($this->once())->method('isActionCacheable')->will($this->returnValue($isActionCacheable)); + $this->mockRequest->expects($this->once())->method('isCached')->will($this->returnValue($requestIsCached)); $this->uriBuilder->uriFor('someNonCacheableAction', array(), 'SomeController', 'SomeExtension'); - $this->assertTrue($this->uriBuilder->getUseCacheHash()); + $this->assertEquals($expectedUseCacheHash, $this->uriBuilder->getUseCacheHash()); + } + + /** + * @return array + */ + public function uriForDisablesCacheHashIfPossibleDataProvider() { + return array( + 'request cached, action cacheable' => array( + TRUE, + TRUE, + TRUE, + ), + 'request cached, action not cacheable' => array( + TRUE, + FALSE, + TRUE, + ), + 'request not cached, action cacheable' => array( + FALSE, + TRUE, + TRUE, + ), + 'request not cached, action not cacheable' => array( + FALSE, + FALSE, + FALSE, + ), + ); } /**