From 3977280b74332dcc31fef00efdd06b00f8f97560 Mon Sep 17 00:00:00 2001
From: Xavier Perseguers <xavier@typo3.org>
Date: Thu, 22 Jun 2017 16:53:24 +0200
Subject: [PATCH] [BUGFIX] Add missing frontend context check when fetching
 view configuration

Check for Frontend context has been omitted during refactoring and will
have side effects in Backend in view configuration is overridden in
Frontend context.

Change-Id: I752baed15f0be6be59fcc37f12103f0a70caa427
Resolves: #81677
Related: #81340
Releases: master, 8.7
Reviewed-on: https://review.typo3.org/53309
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Alexander Grein <alexander.grein@gmail.com>
Tested-by: Alexander Grein <alexander.grein@gmail.com>
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Tested-by: Markus Klein <markus.klein@typo3.org>
---
 .../fluid/Classes/View/TemplatePaths.php      |  10 +-
 .../Tests/Unit/View/TemplatePathsTest.php     | 118 +++++++++++++++++-
 2 files changed, 125 insertions(+), 3 deletions(-)

diff --git a/typo3/sysext/fluid/Classes/View/TemplatePaths.php b/typo3/sysext/fluid/Classes/View/TemplatePaths.php
index 3dd19a12cd77..274bf4726b4b 100644
--- a/typo3/sysext/fluid/Classes/View/TemplatePaths.php
+++ b/typo3/sysext/fluid/Classes/View/TemplatePaths.php
@@ -110,7 +110,7 @@ class TemplatePaths extends \TYPO3Fluid\Fluid\View\TemplatePaths
             $signature = str_replace('_', '', $extensionKey);
             if ($this->isBackendMode() && isset($this->typoScript['module']['tx_' . $signature]['view'])) {
                 $configuredPaths = (array)$this->typoScript['module']['tx_' . $signature]['view'];
-            } elseif (isset($this->typoScript['plugin']['tx_' . $signature]['view'])) {
+            } elseif ($this->isFrontendMode() && isset($this->typoScript['plugin']['tx_' . $signature]['view'])) {
                 $configuredPaths = (array)$this->typoScript['plugin']['tx_' . $signature]['view'];
             }
         }
@@ -228,6 +228,14 @@ class TemplatePaths extends \TYPO3Fluid\Fluid\View\TemplatePaths
         return TYPO3_MODE === 'BE';
     }
 
+    /**
+     * @return bool
+     */
+    protected function isFrontendMode()
+    {
+        return TYPO3_MODE === 'FE';
+    }
+
     /**
      * @return VariableFrontend
      */
diff --git a/typo3/sysext/fluid/Tests/Unit/View/TemplatePathsTest.php b/typo3/sysext/fluid/Tests/Unit/View/TemplatePathsTest.php
index 5c110460ed4a..bfb3c2c3f8b2 100644
--- a/typo3/sysext/fluid/Tests/Unit/View/TemplatePathsTest.php
+++ b/typo3/sysext/fluid/Tests/Unit/View/TemplatePathsTest.php
@@ -104,7 +104,7 @@ class TemplatePathsTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
     /**
      * @test
      */
-    public function getContextSpecificViewConfigurationSortsTypoScriptConfiguredPathsCorrectly()
+    public function getContextSpecificViewConfigurationSortsTypoScriptConfiguredPathsCorrectlyInFrontendMode()
     {
         $configurationManager = $this->getMockBuilder(ConfigurationManagerInterface::class)->getMockForAbstractClass();
         $configurationManager->expects($this->once())->method('getConfiguration')->willReturn([
@@ -133,11 +133,12 @@ class TemplatePathsTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
         $cache = $this->getMockBuilder(VariableFrontend::class)->setMethods(['get', 'set'])->disableOriginalConstructor()->getMock();
         $cache->expects($this->once())->method('get')->willReturn(false);
         $cache->expects($this->once())->method('set');
-        $subject = $this->getMockBuilder(TemplatePaths::class)->setMethods(['getConfigurationManager', 'getExtensionPrivateResourcesPath', 'getRuntimeCache', 'isBackendMode'])->getMock();
+        $subject = $this->getMockBuilder(TemplatePaths::class)->setMethods(['getConfigurationManager', 'getExtensionPrivateResourcesPath', 'getRuntimeCache', 'isBackendMode', 'isFrontendMode'])->getMock();
         $subject->expects($this->once())->method('getExtensionPrivateResourcesPath')->with('test')->willReturn('test/');
         $subject->expects($this->once())->method('getConfigurationManager')->willReturn($configurationManager);
         $subject->expects($this->once())->method('getRuntimeCache')->willReturn($cache);
         $subject->expects($this->once())->method('isBackendMode')->willReturn(false);
+        $subject->expects($this->once())->method('isFrontendMode')->willReturn(true);
         $result = $this->callInaccessibleMethod($subject, 'getContextSpecificViewConfiguration', 'test');
         $this->assertSame([
             'templateRootPaths' => [
@@ -160,4 +161,117 @@ class TemplatePathsTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
             ]
         ], $result);
     }
+
+    /**
+     * @test
+     */
+    public function getContextSpecificViewConfigurationSortsTypoScriptConfiguredPathsCorrectlyInBackendMode()
+    {
+        $configurationManager = $this->getMockBuilder(ConfigurationManagerInterface::class)->getMockForAbstractClass();
+        $configurationManager->expects($this->once())->method('getConfiguration')->willReturn([
+            'module.' => [
+                'tx_test.' => [
+                    'view.' => [
+                        'templateRootPaths.' => [
+                            '30' => 'third',
+                            '10' => 'first',
+                            '20' => 'second'
+                        ],
+                        'partialRootPaths.' => [
+                            '20' => '2',
+                            '30' => '3',
+                            '10' => '1'
+                        ],
+                        'layoutRootPaths.' => [
+                            '130' => '3.',
+                            '10' => '1.',
+                            '120' => '2.'
+                        ],
+                    ]
+                ]
+            ]
+        ]);
+        $cache = $this->getMockBuilder(VariableFrontend::class)->setMethods(['get', 'set'])->disableOriginalConstructor()->getMock();
+        $cache->expects($this->once())->method('get')->willReturn(false);
+        $cache->expects($this->once())->method('set');
+        $subject = $this->getMockBuilder(TemplatePaths::class)->setMethods(['getConfigurationManager', 'getExtensionPrivateResourcesPath', 'getRuntimeCache', 'isBackendMode', 'isFrontendMode'])->getMock();
+        $subject->expects($this->once())->method('getExtensionPrivateResourcesPath')->with('test')->willReturn('test/');
+        $subject->expects($this->once())->method('getConfigurationManager')->willReturn($configurationManager);
+        $subject->expects($this->once())->method('getRuntimeCache')->willReturn($cache);
+        $subject->expects($this->once())->method('isBackendMode')->willReturn(true);
+        $subject->expects($this->never())->method('isFrontendMode');
+        $result = $this->callInaccessibleMethod($subject, 'getContextSpecificViewConfiguration', 'test');
+        $this->assertSame([
+            'templateRootPaths' => [
+                'test/Templates/',
+                'first',
+                'second',
+                'third'
+            ],
+            'partialRootPaths' => [
+                'test/Partials/',
+                '1',
+                '2',
+                '3'
+            ],
+            'layoutRootPaths' => [
+                'test/Layouts/',
+                '1.',
+                '2.',
+                '3.'
+            ]
+        ], $result);
+    }
+
+    /**
+     * @test
+     */
+    public function getContextSpecificViewConfigurationDoesNotResolveFromTypoScriptAndDoesNotSortInUnspecifiedMode()
+    {
+        $configurationManager = $this->getMockBuilder(ConfigurationManagerInterface::class)->getMockForAbstractClass();
+        $configurationManager->expects($this->once())->method('getConfiguration')->willReturn([
+            'plugin.' => [
+                'tx_test.' => [
+                    'view.' => [
+                        'templateRootPaths.' => [
+                            '30' => 'third',
+                            '10' => 'first',
+                            '20' => 'second'
+                        ],
+                        'partialRootPaths.' => [
+                            '20' => '2',
+                            '30' => '3',
+                            '10' => '1'
+                        ],
+                        'layoutRootPaths.' => [
+                            '130' => '3.',
+                            '10' => '1.',
+                            '120' => '2.'
+                        ],
+                    ]
+                ]
+            ]
+        ]);
+        $cache = $this->getMockBuilder(VariableFrontend::class)->setMethods(['get', 'set'])->disableOriginalConstructor()->getMock();
+        $cache->expects($this->once())->method('get')->willReturn(false);
+        $cache->expects($this->never())->method('set');
+        $subject = $this->getMockBuilder(TemplatePaths::class)->setMethods(['getConfigurationManager', 'getExtensionPrivateResourcesPath', 'getRuntimeCache', 'isBackendMode', 'isFrontendMode'])->getMock();
+        $subject->expects($this->once())->method('getExtensionPrivateResourcesPath')->with('test')->willReturn('test/');
+        $subject->expects($this->once())->method('getConfigurationManager')->willReturn($configurationManager);
+        $subject->expects($this->once())->method('getRuntimeCache')->willReturn($cache);
+        $subject->expects($this->once())->method('isBackendMode')->willReturn(false);
+        $subject->expects($this->once())->method('isFrontendMode')->willReturn(false);
+        $result = $this->callInaccessibleMethod($subject, 'getContextSpecificViewConfiguration', 'test');
+        $this->assertSame([
+            'templateRootPaths' => [
+                'test/Templates/'
+            ],
+            'partialRootPaths' => [
+                'test/Partials/'
+            ],
+            'layoutRootPaths' => [
+                'test/Layouts/'
+            ]
+        ], $result);
+    }
 }
-- 
GitLab