[!!!][BUGFIX] Evaluate "boolean /stdWrap" properties correctly 08/48008/19
authorOlaf Schmidt-Wischhöfer <osw@eadi.org>
Mon, 9 May 2016 08:29:51 +0000 (10:29 +0200)
committerFrank Naegler <frank.naegler@typo3.org>
Tue, 7 Jun 2016 08:00:20 +0000 (10:00 +0200)
stdWrap sub-properties on boolean properties have to be evaluated
correctly.

Resolves: #75493
Related: #60135
Releases: master
Change-Id: I7ab418a97228beb49458fa43e5d0ce50aef83877
Reviewed-on: https://review.typo3.org/48008
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Tested-by: Markus Klein <markus.klein@typo3.org>
Reviewed-by: Nicole Cordes <typo3@cordes.co>
Tested-by: Nicole Cordes <typo3@cordes.co>
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
Reviewed-by: Frank Naegler <frank.naegler@typo3.org>
Tested-by: Frank Naegler <frank.naegler@typo3.org>
typo3/sysext/core/Documentation/Changelog/master/Breaking-75493-EvaluateBooleanStdWrapPropertiesCorrectly.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-75493-EvaluateBooleanStdWrapPropertiesCorrectly.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-75493-EvaluateBooleanStdWrapPropertiesCorrectly.rst
new file mode 100644 (file)
index 0000000..a0f2944
--- /dev/null
@@ -0,0 +1,52 @@
+===================================================================
+Breaking: #75493 - Evaluate "boolean /stdWrap" properties correctly
+===================================================================
+
+Description
+===========
+
+stdWrap sub-properties on boolean properties were not evaluated correctly unless the property itself was explicitly set.
+
+Example: ``page.10.value.prioriCalc.wrap = `` without ``page.10.value.prioriCalc = ``
+
+
+Impact
+======
+
+It is now possible to reliably use stdWrap sub-properties on boolean properties.
+
+
+Affected Installations
+======================
+
+Earlier installations can be affected if they contain TypoScript that triggers the bug.
+
+Test case:
+
+.. code-block:: typoscript
+
+       page = PAGE
+       page.10 = TEXT
+       page.10.value = 1+1
+       page.10.value.prioriCalc.wrap =
+
+Result was: 2
+Correct result: 1+1
+
+For some installations, the bug fix will make the TypoScript work as intended.
+Other installations might accidentally rely on the broken code.
+
+In the latter case, the TypoScript can be changed to:
+
+.. code-block:: typoscript
+
+       page = PAGE
+       page.10 = TEXT
+       page.10.value = 1+1
+       page.10.value.prioriCalc = 1
+
+
+Migration
+=========
+
+The usage of stdWrap sub-properties on boolean properties needs to be checked and possibly adapted to fit the fixed behavior.
index 7316af8..b9ce50d 100644 (file)
@@ -32,7 +32,6 @@ use TYPO3\CMS\Core\Service\DependencyOrderingService;
 use TYPO3\CMS\Core\Service\MarkerBasedTemplateService;
 use TYPO3\CMS\Core\TimeTracker\TimeTracker;
 use TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser;
-use TYPO3\CMS\Core\TypoScript\TemplateService;
 use TYPO3\CMS\Core\Utility\ArrayUtility;
 use TYPO3\CMS\Core\Utility\DebugUtility;
 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
@@ -2004,7 +2003,7 @@ class ContentObjectRenderer
             $conf['cacheStore'] = 1;
         }
         // The configuration is sorted and filtered by intersection with the defined stdWrapOrder.
-        $sortedConf = array_intersect_key($this->stdWrapOrder, $conf);
+        $sortedConf = array_keys(array_intersect_key($this->stdWrapOrder, $conf));
         // Functions types that should not make use of nested stdWrap function calls to avoid conflicts with internal TypoScript used by these functions
         $stdWrapDisabledFunctionTypes = 'cObject,functionName,stdWrap';
         // Additional Array to check whether a function has already been executed
@@ -2014,16 +2013,16 @@ class ContentObjectRenderer
         $this->stdWrapRecursionLevel++;
         $this->stopRendering[$this->stdWrapRecursionLevel] = false;
         // execute each function in the predefined order
-        foreach ($sortedConf as $stdWrapName => $functionType) {
+        foreach ($sortedConf as $stdWrapName) {
             // eliminate the second key of a pair 'key'|'key.' to make sure functions get called only once and check if rendering has been stopped
             if (!$isExecuted[$stdWrapName] && !$this->stopRendering[$this->stdWrapRecursionLevel]) {
                 $functionName = rtrim($stdWrapName, '.');
                 $functionProperties = $functionName . '.';
+                $functionType = $this->stdWrapOrder[$functionName];
                 // 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 ($functionName !== 'stdWrap' && !empty($conf[$functionProperties]) && !GeneralUtility::inList($stdWrapDisabledFunctionTypes, $functionType)) {
+                if (!empty($conf[$functionProperties]) && !GeneralUtility::inList($stdWrapDisabledFunctionTypes, $functionType)) {
                     if (array_intersect_key($this->stdWrapOrder, $conf[$functionProperties])) {
                         $conf[$functionName] = $this->stdWrap($conf[$functionName], $conf[$functionProperties]);
                     }
index a3fc0ba..b4c70fc 100755 (executable)
@@ -1981,6 +1981,36 @@ class ContentObjectRendererTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
     }
 
     /**
+     * @return array
+     */
+    public function stdWrapReturnsExpectationDataProvider()
+    {
+        return [
+            'Prevent silent bool conversion' => [
+                '1+1',
+                [
+                    'prioriCalc.' => [
+                        'wrap' => '|',
+                    ],
+                ],
+                '1+1',
+            ],
+        ];
+    }
+
+    /**
+     * @param string $content
+     * @param array $configuration
+     * @param string $expectation
+     * @dataProvider stdWrapReturnsExpectationDataProvider
+     * @test
+     */
+    public function stdWrapReturnsExpectation($content, array $configuration, $expectation)
+    {
+        $this->assertSame($expectation, $this->subject->stdWrap($content, $configuration));
+    }
+
+    /**
      * Data provider for stdWrap_case test
      *
      * @return array