When building an URI for a non-cacheable action, while the current
request also is uncached, we can skip the cache hash for the target URI
to avoid unnecessary page cache entries.
Since this is a change in behavior during link generation, which other
code may rely upon, this is marked as breaking change.
Resolves: #60272
Releases: master
Change-Id: I448c33d23b790de1064eff95d0a940878b0299ac
Reviewed-on: http://review.typo3.org/31594
Reviewed-by: Markus Klein <klein.t3@reelworx.at>
Tested-by: Markus Klein <klein.t3@reelworx.at>
Reviewed-by: Stefan Neufeind <typo3.neufeind@speedpartner.de>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Helmut Hummel <helmut.hummel@typo3.org>
Tested-by: Helmut Hummel <helmut.hummel@typo3.org>
--- /dev/null
+====================================================================
+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.
if ($pluginName === NULL) {
$pluginName = $this->request->getPluginName();
}
if ($pluginName === NULL) {
$pluginName = $this->request->getPluginName();
}
+
+ $this->disableCacheHashForNonCacheableAction($controllerArguments);
+
if ($this->environmentService->isEnvironmentInFrontendMode() && $this->configurationManager->isFeatureEnabled('skipDefaultArguments')) {
$controllerArguments = $this->removeDefaultControllerAndAction($controllerArguments, $extensionName, $pluginName);
}
if ($this->environmentService->isEnvironmentInFrontendMode() && $this->configurationManager->isFeatureEnabled('skipDefaultArguments')) {
$controllerArguments = $this->removeDefaultControllerAndAction($controllerArguments, $extensionName, $pluginName);
}
+ /**
+ * 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.
/**
* This removes controller and/or action arguments from given controllerArguments
* if they are equal to the default controller/action of the target plugin.
+ * @param bool $isActionCacheable
+ * @param bool $requestIsCached
+ * @param bool $expectedUseCacheHash
+ * @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->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,
+ ),
+ );