[!!!][BUGFIX] Avoid to call stdWrap twice 66/32466/6
authorMarkus Klein <klein.t3@reelworx.at>
Thu, 28 Aug 2014 00:10:55 +0000 (02:10 +0200)
committerMarkus Klein <klein.t3@reelworx.at>
Wed, 3 Sep 2014 10:34:34 +0000 (12:34 +0200)
Using the recursive stdWrap will work on the stdWrap twice, although the
output is created only once.

Fix this by preventing the recursive call to stdWrap() if the
current function name is "stdWrap" as this will trigger a call to
stdWrap_stdWrap() later on anyway.

This will change rendering if LOAD_REGISTER or something similar
is used in a recursive stdWrap context.

Resolves: #60135
Releases: 6.3
Change-Id: I728f637b4e34f26b9cf6951f04667c8195638b3d
Reviewed-on: http://review.typo3.org/32466
Reviewed-by: Helmut Hummel <helmut.hummel@typo3.org>
Tested-by: Helmut Hummel <helmut.hummel@typo3.org>
Reviewed-by: Stefan Froemken <froemken@gmail.com>
Tested-by: Stefan Froemken <froemken@gmail.com>
Tested-by: Markus Klein <klein.t3@reelworx.at>
typo3/sysext/core/Documentation/Changelog/master/Breaking-60135-RecursiveStdWrapChange.rst [new file with mode: 0644]
typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php
typo3/sysext/frontend/Tests/Unit/ContentObject/ContentObjectRendererTest.php

diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-60135-RecursiveStdWrapChange.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-60135-RecursiveStdWrapChange.rst
new file mode 100644 (file)
index 0000000..2413f94
--- /dev/null
@@ -0,0 +1,47 @@
+============================================================
+Breaking: #60135 - Recursive stdWrap is now only called once
+============================================================
+
+Description
+===========
+
+If recursive stdWrap configuration was used, the stdWrap method was called twice, although the content
+was only rendered once. This performance overhead is now removed.
+
+
+Impact
+======
+
+If a recursive stdWrap configuration is used, which sets or acts on a global state like registers,
+the resulting rendering can now be different because the global state is now modified only once.
+
+
+Affected installations
+======================
+
+A TYPO3 instance is affected if there is TypoScript code like:
+
+::
+
+  page.1 = TEXT
+  page.1 {
+    value = Counter:
+    append = TEXT
+    append.data = register:Counter
+    stdWrap.append = LOAD_REGISTER
+    stdWrap.append {
+      Counter.cObject = TEXT
+      Counter.cObject.data = register:Counter
+      Counter.cObject.wrap = |+1
+      Counter.prioriCalc = 1
+    }
+  }
+
+..
+
+This now correctly outputs `Counter:1` instead of `Counter:2`
+
+Migration
+=========
+
+The usage of recursive stdWrap TypoScript configuration needs to be checked and probably adapted to fit the fixed behavior.
index 28c99e2..0a6196b 100644 (file)
@@ -2071,11 +2071,11 @@ class ContentObjectRenderer {
                        if (!$isExecuted[$stdWrapName] && !$this->stopRendering[$this->stdWrapRecursionLevel]) {
                                $functionName = rtrim($stdWrapName, '.');
                                $functionProperties = $functionName . '.';
-                               // If there is any code one the next level, check if it contains "official" stdWrap functions
+                               // If there is any code on the next level, check if it contains "official" stdWrap functions
                                // if yes, execute them first - will make each function stdWrap aware
                                // so additional stdWrap calls within the functions can be removed, since the result will be the same
                                // exception: the recursive stdWrap function and cObject will still be using their own stdWrap call, since it modifies the content and not a property
-                               if (count($conf[$functionProperties]) && !GeneralUtility::inList($stdWrapDisabledFunctionTypes, $functionType)) {
+                               if ($functionName !== 'stdWrap' && !empty($conf[$functionProperties]) && !GeneralUtility::inList($stdWrapDisabledFunctionTypes, $functionType)) {
                                        if (array_intersect_key($this->stdWrapOrder, $conf[$functionProperties])) {
                                                $conf[$functionName] = $this->stdWrap($conf[$functionName], $conf[$functionProperties]);
                                        }
index 96c190a..0565d2b 100644 (file)
@@ -1037,6 +1037,51 @@ class ContentObjectRendererTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
        }
 
        /**
+        * @test
+        */
+       public function recursiveStdWrapProperlyRendersBasicString() {
+               $stdWrapConfiguration = array(
+                       'noTrimWrap' => '|| 123|',
+                       'stdWrap.' => array(
+                               'wrap' => '<b>|</b>'
+                       )
+               );
+               $this->assertSame(
+                       '<b>Test</b> 123',
+                       $this->cObj->stdWrap('Test', $stdWrapConfiguration)
+               );
+       }
+
+       /**
+        * @test
+        */
+       public function recursiveStdWrapIsOnlyCalledOnce() {
+               $stdWrapConfiguration = array(
+                       'append' => 'TEXT',
+                       'append.' => array(
+                               'data' => 'register:Counter'
+                       ),
+                       'stdWrap.' => array(
+                               'append' => 'LOAD_REGISTER',
+                               'append.' => array(
+                                       'Counter.' => array(
+                                               'prioriCalc' => 'intval',
+                                               'cObject' => 'TEXT',
+                                               'cObject.' => array(
+                                                       'data' => 'register:Counter',
+                                                       'wrap' => '|+1',
+                                               )
+                                       )
+                               )
+                       )
+               );
+               $this->assertSame(
+                       'Counter:1',
+                       $this->cObj->stdWrap('Counter:', $stdWrapConfiguration)
+               );
+       }
+
+       /**
         * Data provider for the numberFormat test
         *
         * @return array multi-dimensional array with the second level like this: