[BUGFIX] Let CObjectViewHelper render top level objects again 86/58686/3
authorHelmut Hummel <typo3@helhum.io>
Wed, 24 Oct 2018 16:46:19 +0000 (18:46 +0200)
committerBenni Mack <benni@typo3.org>
Thu, 25 Oct 2018 05:23:05 +0000 (07:23 +0200)
Making the CObjectViewHelper had the unfortunate side effect,
that top level object paths are not working any more.

Adapt the tests to show the mistake and make the rendering
work in this case.

Additionally now an exception is also thrown, if the given
object path does not resolve to a TypoScript object.

Releases: master
Resolves: #86729
Related: #84345
Change-Id: I686119b480c6fae88be7d704b82094e35789c0d7
Reviewed-on: https://review.typo3.org/58686
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Nicole Cordes <typo3@cordes.co>
Tested-by: Nicole Cordes <typo3@cordes.co>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
typo3/sysext/fluid/Classes/ViewHelpers/CObjectViewHelper.php
typo3/sysext/fluid/Tests/Unit/ViewHelpers/CObjectViewHelperTest.php

index f04a1a3..e2332ff 100644 (file)
@@ -121,18 +121,22 @@ class CObjectViewHelper extends AbstractViewHelper
         $pathSegments = GeneralUtility::trimExplode('.', $typoscriptObjectPath);
         $lastSegment = array_pop($pathSegments);
         $setup = static::getConfigurationManager()->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT);
-        if (!empty($pathSegments) && \is_array($pathSegments)) {
-            foreach ($pathSegments as $segment) {
-                if (!array_key_exists($segment . '.', $setup)) {
-                    throw new \TYPO3\CMS\Fluid\Core\ViewHelper\Exception(
-                        'TypoScript object path "' . htmlspecialchars($typoscriptObjectPath) . '" does not exist',
-                        1253191023
-                    );
-                }
-                $setup = $setup[$segment . '.'];
+        foreach ($pathSegments as $segment) {
+            if (!array_key_exists($segment . '.', $setup)) {
+                throw new \TYPO3\CMS\Fluid\Core\ViewHelper\Exception(
+                    'TypoScript object path "' . $typoscriptObjectPath . '" does not exist',
+                    1253191023
+                );
             }
-            $content = $contentObjectRenderer->cObjGetSingle($setup[$lastSegment], $setup[$lastSegment . '.']);
+            $setup = $setup[$segment . '.'];
         }
+        if (!isset($setup[$lastSegment])) {
+            throw new \TYPO3\CMS\Fluid\Core\ViewHelper\Exception(
+                'No Content Object definition found at TypoScript object path "' . $typoscriptObjectPath . '"',
+                1540246570
+            );
+        }
+        $content = $contentObjectRenderer->cObjGetSingle($setup[$lastSegment], $setup[$lastSegment . '.'] ?? []);
         if (TYPO3_MODE === 'BE') {
             static::resetFrontendEnvironment();
         }
index ef9d5be..a411c24 100644 (file)
@@ -71,12 +71,18 @@ class CObjectViewHelperTest extends ViewHelperBaseTestcase
         $this->setArgumentsUnderTest(
             $this->viewHelper,
             [
+                'typoscriptObjectPath' => 'test',
                 'data' => 'foo',
             ]
         );
+        $configArray = [
+            'test' => 'TEXT',
+            'test.' => [],
+        ];
+        $this->configurationManager->getConfiguration(Argument::any())->willReturn($configArray);
+
         $this->contentObjectRenderer->start(['foo'], '')->willReturn();
-        $actualResult = $this->viewHelper->initializeArgumentsAndRender();
-        $this->assertSame('', $actualResult);
+        $this->viewHelper->initializeArgumentsAndRender();
     }
 
     /**
@@ -93,17 +99,39 @@ class CObjectViewHelperTest extends ViewHelperBaseTestcase
         );
         $this->setArgumentsUnderTest(
             $this->viewHelper,
-            []
+            [
+                'typoscriptObjectPath' => 'test',
+            ]
         );
+        $configArray = [
+            'test' => 'TEXT',
+            'test.' => [],
+        ];
+        $this->configurationManager->getConfiguration(Argument::any())->willReturn($configArray);
+
         $this->contentObjectRenderer->start(['foo'], '')->willReturn();
-        $actualResult = $this->viewHelper->initializeArgumentsAndRender();
-        $this->assertSame('', $actualResult);
+        $this->viewHelper->initializeArgumentsAndRender();
+    }
+
+    public function renderThrowsExceptionIfTypoScriptObjectPathDoesNotExistDataProvider(): array
+    {
+        return [
+            'Single path' => [
+                'test',
+                1540246570
+            ],
+            'Multi path' => [
+                'test.path',
+                1253191023
+            ],
+        ];
     }
 
     /**
      * @test
+     * @dataProvider renderThrowsExceptionIfTypoScriptObjectPathDoesNotExistDataProvider
      */
-    public function renderThrowsExceptionIfTyposcriptObjectPathDoesNotExist()
+    public function renderThrowsExceptionIfTypoScriptObjectPathDoesNotExist(string $objectPath, int $exceptionCode)
     {
         $this->stubBaseDependencies();
         $this->contentObjectRenderer->start(Argument::cetera())->willReturn();
@@ -112,43 +140,77 @@ class CObjectViewHelperTest extends ViewHelperBaseTestcase
             $this->viewHelper,
             [
                 'data' => 'foo',
-                'typoscriptObjectPath' => 'test.path',
+                'typoscriptObjectPath' => $objectPath,
             ]
         );
 
         $this->expectException(\TYPO3\CMS\Fluid\Core\ViewHelper\Exception::class);
-        $this->expectExceptionCode(1253191023);
+        $this->expectExceptionCode($exceptionCode);
         $this->viewHelper->initializeArgumentsAndRender();
     }
 
+    public function renderReturnsSimpleTypoScriptValueDataProvider(): array
+    {
+        $subConfigArray = [
+            'value' => 'Hello World',
+            'wrap' => 'ab | cd',
+        ];
+        return [
+            'Single path' => [
+                'test',
+                [
+                    'test' => 'TEXT',
+                    'test.' => $subConfigArray,
+                ],
+                $subConfigArray
+            ],
+            'Single path no config' => [
+                'test',
+                [
+                    'test' => 'TEXT',
+                ],
+                []
+            ],
+            'Multi path' => [
+                'plugin.test',
+                [
+                    'plugin.' => [
+                        'test' => 'TEXT',
+                        'test.' => $subConfigArray,
+                    ]
+                ],
+                $subConfigArray
+            ],
+            'Multi path no config' => [
+                'plugin.test',
+                [
+                    'plugin.' => [
+                        'test' => 'TEXT',
+                    ]
+                ],
+                []
+            ],
+        ];
+    }
+
     /**
      * @test
+     * @dataProvider renderReturnsSimpleTypoScriptValueDataProvider
+     * @param string $objectPath
+     * @param array $configArray
+     * @param array $subConfigArray
      */
-    public function renderReturnsSimpleTyposcriptValue()
+    public function renderReturnsSimpleTypoScriptValue(string $objectPath, array $configArray, array $subConfigArray)
     {
         $this->setArgumentsUnderTest(
             $this->viewHelper,
             [
-                'typoscriptObjectPath' => 'plugin.test',
+                'typoscriptObjectPath' => $objectPath,
                 'data' => 'foo',
                 'table' => 'table',
             ]
         );
 
-        $subConfigArray = [
-            'value' => 'Hello World',
-            'wrap' => 'ab | cd',
-        ];
-
-        $configArray = [
-            'olugin' => 'COA',
-            'plugin.' => [
-                'test' => 'TEXT',
-                'test.' => $subConfigArray,
-
-            ]
-        ];
-
         $this->configurationManager->getConfiguration(Argument::any())->willReturn($configArray);
 
         $this->contentObjectRenderer->start(['foo'], 'table')->willReturn();