[BUGFIX] Allow sys_file_metadata to be translatable 19/61419/6
authorVolker Kemeter <volker@kemeter.de>
Fri, 2 Aug 2019 21:30:37 +0000 (23:30 +0200)
committerSusanne Moog <look@susi.dev>
Sun, 12 Jan 2020 14:54:41 +0000 (15:54 +0100)
Since sys_file_metadata records are stored on pid=0,
there is no site configuration available. This situation is
similar to be_users.limitToLanguage feature, where
all languages of all sites need to be visible (depending
on the backend user rights).

This patch adds an option for the TranslationConfigurationProvider
to render all languages of all sites as a combined list
if the given pageId is 0 (based on the current user rights).

Resolves: #88897
Releases: master
Change-Id: I14b1bb6ae5c8577571cf5fa7bc2da1c1824c0f58
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/61419
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Daniel Goerz <daniel.goerz@posteo.de>
Tested-by: Susanne Moog <look@susi.dev>
Reviewed-by: Daniel Goerz <daniel.goerz@posteo.de>
Reviewed-by: Susanne Moog <look@susi.dev>
typo3/sysext/backend/Classes/Configuration/TranslationConfigurationProvider.php
typo3/sysext/backend/Tests/Unit/Configuration/TranslationConfigurationProviderTest.php

index 84dc23a..317da7a 100644 (file)
@@ -22,6 +22,7 @@ use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
 use TYPO3\CMS\Core\Exception\SiteNotFoundException;
 use TYPO3\CMS\Core\Site\Entity\NullSite;
+use TYPO3\CMS\Core\Site\Entity\SiteInterface;
 use TYPO3\CMS\Core\Site\SiteFinder;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
@@ -41,27 +42,56 @@ class TranslationConfigurationProvider
      */
     public function getSystemLanguages($pageId = 0)
     {
-        try {
-            $site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId((int)$pageId);
-        } catch (SiteNotFoundException $e) {
-            $site = new NullSite();
-        }
-        $siteLanguages = $site->getAvailableLanguages($this->getBackendUserAuthentication(), true);
-        if (!isset($siteLanguages[0])) {
-            $siteLanguages[0] = $site->getDefaultLanguage();
-            ksort($siteLanguages);
+        $allSystemLanguages = [];
+        $siteFinder = GeneralUtility::makeInstance(SiteFinder::class);
+        if ($pageId === 0) {
+            // Used for e.g. filelist, where there is no site selected
+            // This also means that there is no "-1" (All Languages) selectable.
+            $sites = $siteFinder->getAllSites();
+            foreach ($sites as $site) {
+                $allSystemLanguages = $this->addSiteLanguagesToConsolidatedList(
+                    $allSystemLanguages,
+                    $site->getAvailableLanguages($this->getBackendUserAuthentication()),
+                    $site
+                );
+            }
+        } else {
+            try {
+                $site = $siteFinder->getSiteByPageId((int)$pageId);
+            } catch (SiteNotFoundException $e) {
+                $site = new NullSite();
+            }
+            $siteLanguages = $site->getAvailableLanguages($this->getBackendUserAuthentication(), true);
+            if (!isset($siteLanguages[0])) {
+                $siteLanguages[0] = $site->getDefaultLanguage();
+            }
+            $allSystemLanguages = $this->addSiteLanguagesToConsolidatedList(
+                $allSystemLanguages,
+                $siteLanguages,
+                $site
+            );
         }
+        ksort($allSystemLanguages);
+        return $allSystemLanguages;
+    }
 
-        $languages = [];
-        foreach ($siteLanguages as $id => $siteLanguage) {
-            $languages[$id] = [
-                'uid' => $id,
-                'title' => $siteLanguage->getTitle(),
-                'ISOcode' => $siteLanguage->getTwoLetterIsoCode(),
-                'flagIcon' => $siteLanguage->getFlagIdentifier(),
-            ];
+    protected function addSiteLanguagesToConsolidatedList(array $allSystemLanguages, array $languagesOfSpecificSite, SiteInterface $site): array
+    {
+        foreach ($languagesOfSpecificSite as $language) {
+            $languageId = $language->getLanguageId();
+            if (isset($allSystemLanguages[$languageId])) {
+                // Language already provided by another site, just add the label separately
+                $allSystemLanguages[$languageId]['title'] .= ', ' . $language->getTitle() . ' [Site: ' . $site->getIdentifier() . ']';
+            } else {
+                $allSystemLanguages[$languageId] = [
+                    'uid' => $languageId,
+                    'title' => $language->getTitle() . ' [Site: ' . $site->getIdentifier() . ']',
+                    'ISOcode' => $language->getTwoLetterIsoCode(),
+                    'flagIcon' => $language->getFlagIdentifier(),
+                ];
+            }
         }
-        return $languages;
+        return $allSystemLanguages;
     }
 
     /**
index 646b9a9..ed13f0e 100644 (file)
@@ -15,8 +15,10 @@ namespace TYPO3\CMS\Backend\Tests\Unit\Configuration;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Prophecy\Argument;
 use TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Localization\LanguageService;
 use TYPO3\CMS\Core\Site\Entity\Site;
 use TYPO3\CMS\Core\Site\SiteFinder;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -34,6 +36,11 @@ class TranslationConfigurationProviderTest extends UnitTestCase
         parent::setUp();
 
         $this->subject = new TranslationConfigurationProvider();
+        $backendUserAuthentication = $this->prophesize(BackendUserAuthentication::class);
+        $backendUserAuthentication->checkLanguageAccess(Argument::any())->willReturn(true);
+        $GLOBALS['BE_USER'] = $backendUserAuthentication->reveal();
+        $languageService = $this->prophesize(LanguageService::class);
+        $GLOBALS['LANG'] = $languageService->reveal();
     }
 
     /**
@@ -46,11 +53,80 @@ class TranslationConfigurationProviderTest extends UnitTestCase
         $siteFinderProphecy = $this->prophesize(SiteFinder::class);
         $siteFinderProphecy->getSiteByPageId($pageId)->willReturn($site);
         GeneralUtility::addInstance(SiteFinder::class, $siteFinderProphecy->reveal());
-
-        $backendUserAuthentication = $this->prophesize(BackendUserAuthentication::class);
-        $GLOBALS['BE_USER'] = $backendUserAuthentication->reveal();
-
         $languages = $this->subject->getSystemLanguages($pageId);
         self::assertArrayHasKey(0, $languages);
     }
+
+    /**
+     * @test
+     */
+    public function getSystemLanguagesAggregatesLanguagesOfAllSitesForRootLevel(): void
+    {
+        $siteFinderProphecy = $this->prophesize(SiteFinder::class);
+        $siteFinderProphecy->getAllSites()->willReturn($this->getDummySites());
+        GeneralUtility::addInstance(SiteFinder::class, $siteFinderProphecy->reveal());
+        $languages = $this->subject->getSystemLanguages(0);
+        self::assertCount(3, $languages);
+    }
+
+    /**
+     * @test
+     */
+    public function getSystemLanguagesConcatenatesTitlesOfLanguagesForRootLevel(): void
+    {
+        $siteFinderProphecy = $this->prophesize(SiteFinder::class);
+        $siteFinderProphecy->getAllSites()->willReturn($this->getDummySites());
+        GeneralUtility::addInstance(SiteFinder::class, $siteFinderProphecy->reveal());
+        $languages = $this->subject->getSystemLanguages(0);
+        self::assertEquals('Deutsch [Site: dummy1], German [Site: dummy2]', $languages[1]['title']);
+    }
+
+    protected function getDummySites(): array
+    {
+        return [
+            new Site(
+                'dummy1',
+                1,
+                [
+                    'base' => 'https://domain.tld/',
+                    'languages' => [
+                        [
+                            'languageId' => 0,
+                            'locale' => 'en_US.UTF-8',
+                            'title' => 'English',
+                        ],
+                        [
+                            'languageId' => 1,
+                            'locale' => 'de_DE.UTF-8',
+                            'title' => 'Deutsch'
+                        ]
+                    ]
+                ]
+            ),
+            new Site(
+                'dummy2',
+                2,
+                [
+                    'base' => 'https://domain.tld/',
+                    'languages' => [
+                        [
+                            'languageId' => 0,
+                            'locale' => 'en_US.UTF-8',
+                            'title' => 'English'
+                        ],
+                        [
+                            'languageId' => 1,
+                            'locale' => 'de_DE.UTF-8',
+                            'title' => 'German'
+                        ],
+                        [
+                            'languageId' => 2,
+                            'locale' => 'da_DK.UTF-8',
+                            'title' => 'Danish'
+                        ],
+                    ]
+                ]
+            )
+        ];
+    }
 }