From 5c048a4c8017e4d50ab5f2343970a0fd33e4aaed Mon Sep 17 00:00:00 2001
From: Benjamin Franzke <bfr@qbus.de>
Date: Tue, 17 Oct 2017 16:53:28 +0200
Subject: [PATCH] [BUGFIX] Fix recursive FLUIDTEMPLATE cObj's that use
 layoutRootPaths

FLUIDTEMPLATE variables may contain content elements (e.g. recursive
FLUIDTEMPLATE's) which may instantiate own TemplateViews
(e.g. StandaloneView).
A recursive StandaloneView will statically(!!) cache used TemplatesPaths
in \TYPO3Fluid\Fluid\View\Templates::resolvedFiles.

If StandaloneView is instantiated before, but the fluid layout path is
calculated after inner content objects are being rendering,
the altered statically cached `resolvedFiles` cache is used
and contains invalid layoutRootPaths.

Short term solution:
Defer the initialization of the StandaloneView (which flushes those
buggy caches) until all variables have been processed.

Change-Id: Idf053b3d0f0835a352790e0ed971344d67844bbc
Releases: master, 8.7
Resolves: #79760
Resolves: #82745
Reviewed-on: https://review.typo3.org/54416
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Sebastian Hofer <sebastian.hofer@marit.ag>
Tested-by: Sebastian Hofer <sebastian.hofer@marit.ag>
Reviewed-by: Susanne Moog <susanne.moog@typo3.org>
Tested-by: Susanne Moog <susanne.moog@typo3.org>
---
 .../FluidTemplateContentObject.php            | 10 +--
 .../FluidTemplateContentObjectTest.php        | 62 ++++++++++++++++++-
 2 files changed, 66 insertions(+), 6 deletions(-)

diff --git a/typo3/sysext/frontend/Classes/ContentObject/FluidTemplateContentObject.php b/typo3/sysext/frontend/Classes/ContentObject/FluidTemplateContentObject.php
index 85cae47c41e9..93cec153a85e 100644
--- a/typo3/sysext/frontend/Classes/ContentObject/FluidTemplateContentObject.php
+++ b/typo3/sysext/frontend/Classes/ContentObject/FluidTemplateContentObject.php
@@ -85,12 +85,14 @@ class FluidTemplateContentObject extends AbstractContentObject
      */
     public function render($conf = [])
     {
-        $parentView = $this->view;
-        $this->initializeStandaloneViewInstance();
-
         if (!is_array($conf)) {
             $conf = [];
         }
+        $variables = $this->getContentObjectVariables($conf);
+        $variables = $this->contentDataProcessor->process($this->cObj, $conf, $variables);
+
+        $parentView = $this->view;
+        $this->initializeStandaloneViewInstance();
 
         $this->setFormat($conf);
         $this->setTemplate($conf);
@@ -98,8 +100,6 @@ class FluidTemplateContentObject extends AbstractContentObject
         $this->setPartialRootPath($conf);
         $this->setExtbaseVariables($conf);
         $this->assignSettings($conf);
-        $variables = $this->getContentObjectVariables($conf);
-        $variables = $this->contentDataProcessor->process($this->cObj, $conf, $variables);
 
         $this->view->assignMultiple($variables);
 
diff --git a/typo3/sysext/frontend/Tests/Functional/ContentObject/FluidTemplateContentObjectTest.php b/typo3/sysext/frontend/Tests/Functional/ContentObject/FluidTemplateContentObjectTest.php
index 01d83a88aa15..8edd8e3d21fa 100644
--- a/typo3/sysext/frontend/Tests/Functional/ContentObject/FluidTemplateContentObjectTest.php
+++ b/typo3/sysext/frontend/Tests/Functional/ContentObject/FluidTemplateContentObjectTest.php
@@ -21,7 +21,19 @@ use TYPO3\CMS\Frontend\ContentObject\TextContentObject;
  */
 class FluidTemplateContentObjectTest extends \TYPO3\TestingFramework\Core\Functional\FunctionalTestCase
 {
-    protected $coreExtensionsToLoad = ['fluid'];
+    /**
+     * @var array
+     */
+    protected $coreExtensionsToLoad = [
+        'fluid'
+    ];
+
+    /**
+     * @var array
+     */
+    protected $testExtensionsToLoad = [
+        'typo3/sysext/fluid/Tests/Functional/Fixtures/Extensions/fluid_test',
+    ];
 
     /**
      * @test
@@ -64,4 +76,52 @@ class FluidTemplateContentObjectTest extends \TYPO3\TestingFramework\Core\Functi
 
         $this->assertEquals($expectedResult, $result);
     }
+
+    /**
+     * @test
+     */
+    public function renderWorksWithNestedFluidtemplateWithLayouts()
+    {
+        /** @var $tsfe \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController */
+        $tsfe = $this->createMock(\TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::class);
+        $GLOBALS['TSFE'] = $tsfe;
+
+        $configuration = [
+            '10' => 'FLUIDTEMPLATE',
+            '10.' => [
+                'template' => 'TEXT',
+                'template.' => [
+                    'value' => '<f:layout name="BaseLayout"/><f:section name="main"><f:format.raw>{anotherFluidTemplate}</f:format.raw></f:section>'
+                ],
+                'layoutRootPaths.' => [
+                    '0' => 'EXT:fluid_test/Resources/Private/Layouts'
+                ],
+                'variables.' => [
+                    'anotherFluidTemplate' => 'FLUIDTEMPLATE',
+                    'anotherFluidTemplate.' => [
+                        'template' => 'TEXT',
+                        'template.' => [
+                            'value' => '<f:layout name="BaseLayout"/><f:section name="main"></f:section>'
+                        ],
+                        'layoutRootPaths.' => [
+                            '0' => 'EXT:fluid_test/Resources/Private/LayoutOverride/Layouts'
+                        ],
+                    ],
+                ],
+            ],
+        ];
+        $expectedResult = 'DefaultLayoutLayoutOverride';
+
+        $contentObjectRenderer = new \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
+        $contentObjectRenderer->setContentObjectClassMap([
+            'FLUIDTEMPLATE' => FluidTemplateContentObject::class,
+            'TEXT' => TextContentObject::class,
+        ]);
+        $fluidTemplateContentObject = new \TYPO3\CMS\Frontend\ContentObject\ContentObjectArrayContentObject(
+            $contentObjectRenderer
+        );
+        $result = preg_replace('/\s+/', '', strip_tags($fluidTemplateContentObject->render($configuration)));
+
+        $this->assertEquals($expectedResult, $result);
+    }
 }
-- 
GitLab