[TASK] Initialize TSFE language at an earlier stage 83/62183/3
authorBenni Mack <benni@typo3.org>
Mon, 4 Nov 2019 09:12:22 +0000 (10:12 +0100)
committerDaniel Goerz <daniel.goerz@posteo.de>
Tue, 5 Nov 2019 15:50:23 +0000 (16:50 +0100)
The languageService and pageRenderer instantiate their
language / locale information at a very late point, allowing
to only use TSFE's language features when TypoScript was loaded.

However, since TYPO3 v10, the SiteLanguage information is always
present in an earlier stage, so the initialization can happen earlier.

Resolves: #89575
Releases: master
Change-Id: Id9dc8268946041353430cb02e12631b048364acf
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/62183
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
Tested-by: Daniel Goerz <daniel.goerz@posteo.de>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Reviewed-by: Oliver Bartsch <bo@cedev.de>
Reviewed-by: Daniel Goerz <daniel.goerz@posteo.de>
typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php
typo3/sysext/frontend/Tests/Unit/Controller/TypoScriptFrontendControllerTest.php

index b7e9ee8..66ed2fb 100644 (file)
@@ -701,6 +701,8 @@ class TypoScriptFrontendController implements LoggerAwareInterface
         $this->uniqueString = md5(microtime());
         $this->initPageRenderer();
         $this->initCaches();
+        // Initialize LLL behaviour
+        $this->setOutputLanguage($this->language->getTypo3Language());
     }
 
     /**
@@ -863,6 +865,11 @@ class TypoScriptFrontendController implements LoggerAwareInterface
         }
         $this->pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
         $this->pageRenderer->setTemplateFile('EXT:frontend/Resources/Private/Templates/MainPage.html');
+        // As initPageRenderer could be called in constructor and for USER_INTs, this information is only set
+        // once - in order to not override any previous settings of PageRenderer.
+        if ($this->language instanceof SiteLanguage) {
+            $this->pageRenderer->setLanguage($this->language->getTypo3Language());
+        }
     }
 
     /**
@@ -2129,9 +2136,6 @@ class TypoScriptFrontendController implements LoggerAwareInterface
             GeneralUtility::callUserFunction($_funcRef, $_params, $this);
         }
 
-        // Initialize charset settings etc.
-        $this->setOutputLanguage($this->language->getTypo3Language());
-
         // Rendering charset of HTML page.
         if (isset($this->config['config']['metaCharset']) && $this->config['config']['metaCharset'] !== 'utf-8') {
             $this->metaCharset = $this->config['config']['metaCharset'];
@@ -3565,7 +3569,6 @@ class TypoScriptFrontendController implements LoggerAwareInterface
      */
     protected function setOutputLanguage($language = 'default')
     {
-        $this->pageRenderer->setLanguage($language);
         $this->languageService = GeneralUtility::makeInstance(LanguageService::class);
         // Always disable debugging for TSFE
         $this->languageService->debugKey = false;
index 20c40a4..d78c4a9 100644 (file)
@@ -19,9 +19,14 @@ use TYPO3\CMS\Core\Cache\Backend\NullBackend;
 use TYPO3\CMS\Core\Cache\CacheManager;
 use TYPO3\CMS\Core\Context\Context;
 use TYPO3\CMS\Core\Domain\Repository\PageRepository;
+use TYPO3\CMS\Core\Http\ServerRequest;
 use TYPO3\CMS\Core\Http\ServerRequestFactory;
+use TYPO3\CMS\Core\Http\Uri;
 use TYPO3\CMS\Core\Page\PageRenderer;
 use TYPO3\CMS\Core\PageTitle\PageTitleProviderManager;
+use TYPO3\CMS\Core\Routing\PageArguments;
+use TYPO3\CMS\Core\Site\Entity\Site;
+use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
@@ -496,4 +501,55 @@ class TypoScriptFrontendControllerTest extends UnitTestCase
         $this->subject->generatePageTitle();
         self::assertSame($pageTitle, $this->subject->indexedDocTitle);
     }
+
+    /**
+     * @test
+     */
+    public function pageRendererLanguageIsSetToSiteLanguageTypo3LanguageInConstructor(): void
+    {
+        $nullCacheBackend = new NullBackend('');
+        $cacheManager = $this->prophesize(CacheManager::class);
+        $cacheManager->getCache('pages')->willReturn($nullCacheBackend);
+        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManager->reveal());
+        $GLOBALS['TYPO3_REQUEST'] = new ServerRequest('https://www.example.com/');
+        $site = new Site('test', 13, ['base' => 'https://www.example.com/']);
+        $language = new SiteLanguage(0, 'fr', new Uri('/'), ['typo3Language' => 'fr-test']);
+        // Constructor calling initPageRenderer()
+        new TypoScriptFrontendController(
+            new Context(),
+            $site,
+            $language,
+            new PageArguments(13, '0', [])
+        );
+        // since PageRenderer is a singleton, this can be queried via the makeInstance call
+        self::assertEquals('fr-test', GeneralUtility::makeInstance(PageRenderer::class)->getLanguage());
+    }
+
+    /**
+     * @test
+     */
+    public function languageServiceIsSetUpWithSiteLanguageTypo3LanguageInConstructor(): void
+    {
+        $nullCacheBackend = new NullBackend('');
+        $cacheManager = $this->prophesize(CacheManager::class);
+        $cacheManager->getCache('pages')->willReturn($nullCacheBackend);
+        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManager->reveal());
+        $GLOBALS['TYPO3_REQUEST'] = new ServerRequest('https://www.example.com/');
+        $site = new Site('test', 13, ['base' => 'https://www.example.com/']);
+        $language = new SiteLanguage(0, 'fr', new Uri('/'), ['typo3Language' => 'fr']);
+        // Constructor calling setOutputLanguage()
+        $subject = $this->getAccessibleMock(
+            TypoScriptFrontendController::class,
+            ['dummy'],
+            [
+                new Context(),
+                $site,
+                $language,
+                new PageArguments(13, '0', [])
+            ]
+        );
+        $languageService = $subject->_get('languageService');
+        // since PageRenderer is a singleton, this can be queried via the makeInstance call
+        self::assertEquals('fr', $languageService->lang);
+    }
 }