[!!!][BUGFIX] Skip cache hash for URIs to non-cacheable actions 94/31594/13
authorMathias Brodala <mbrodala@pagemachine.de>
Fri, 11 Jul 2014 11:51:47 +0000 (13:51 +0200)
committerHelmut Hummel <helmut.hummel@typo3.org>
Mon, 2 Mar 2015 18:07:06 +0000 (19:07 +0100)
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>
typo3/sysext/core/Documentation/Changelog/master/Breaking-60272-SkipCacheHashForUrisToNonCacheableActions.rst [new file with mode: 0644]
typo3/sysext/extbase/Classes/Mvc/Web/Routing/UriBuilder.php
typo3/sysext/extbase/Tests/Unit/Mvc/Web/Routing/UriBuilderTest.php

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 (file)
index 0000000..f78286b
--- /dev/null
@@ -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.
index aecdecd..c67bc98 100644 (file)
@@ -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);
                }
@@ -530,6 +533,25 @@ class UriBuilder {
        }
 
        /**
+        * 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.
         * Note: This is only active in FE mode and if feature "skipDefaultArguments" is enabled
index d3fa9aa..5fd5221 100644 (file)
@@ -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,
+                       ),
+               );
        }
 
        /**