[!!!][TASK] Remove Pseudo-Site Handling 66/59366/47
authorBenni Mack <benni@typo3.org>
Mon, 7 Jan 2019 20:37:20 +0000 (21:37 +0100)
committerAndreas Fernandez <a.fernandez@scripting-base.de>
Wed, 15 May 2019 19:42:46 +0000 (21:42 +0200)
This change removes the compatibility layer of Site Handling,
called "PseudoSite" handling.

Any TypoScript-related Language properties are removed.
- config.sys_language_uid
- config.sys_language_mode
- config.sys_language_overlay
- config.locale_all
- config.language
- config.typolinkEnableLinksAcrossDomains
- typolink.useCacheHash

The hook
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tstemplate.php']['linkData-PostProc']
is removed.

In addition, all tests related to PseudoSite and linking
without SiteHandling are removed, linking to pages without
a site will not be linked anymore.

Adding `useCacheHash` to typolink triggers a
"this does not do anything anymore" deprecation message.

Further related removals (old "pageNotFound" handling
and "useCacheHash" in all viewhelpers), are removed
separately.

Resolves: #88363
Releases: master
Change-Id: I14f2f854e69c98df7fab8b14f92f1ec2440a15a0
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/59366
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de>
40 files changed:
typo3/sysext/backend/Classes/Controller/Page/TreeController.php
typo3/sysext/backend/Classes/Form/Element/InputSlugElement.php
typo3/sysext/backend/Classes/Tree/View/BrowseTreeView.php
typo3/sysext/backend/Classes/Utility/BackendUtility.php
typo3/sysext/backend/Tests/Unit/Form/Element/InputSlugElementTest.php
typo3/sysext/core/Classes/Compatibility/PseudoSiteTcaDisplayCondition.php
typo3/sysext/core/Classes/Context/LanguageAspectFactory.php
typo3/sysext/core/Classes/Routing/PageRouter.php
typo3/sysext/core/Classes/Routing/SiteMatcher.php
typo3/sysext/core/Classes/Site/Entity/NullSite.php
typo3/sysext/core/Classes/Site/Entity/PseudoSite.php [deleted file]
typo3/sysext/core/Classes/Site/PseudoSiteFinder.php [deleted file]
typo3/sysext/core/Documentation/Changelog/master/Breaking-87193-DeprecatedFunctionalityRemoved.rst
typo3/sysext/core/Tests/Functional/Fixtures/Frontend/JsonRenderer.typoscript
typo3/sysext/core/Tests/Unit/Site/Entity/PseudoSiteTest.php [deleted file]
typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/Frontend/ContentJsonRenderer.typoscript
typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/Frontend/JsonRenderer.typoscript
typo3/sysext/extbase/Tests/Functional/Persistence/TranslatedContentTest.php [deleted file]
typo3/sysext/fluid/Tests/Functional/Fixtures/Extensions/fluid_test/Configuration/TypoScript/Basic.ts
typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php
typo3/sysext/frontend/Classes/ContentObject/Menu/AbstractMenuContentObject.php
typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php
typo3/sysext/frontend/Classes/Middleware/PageResolver.php
typo3/sysext/frontend/Classes/Typolink/PageLinkBuilder.php
typo3/sysext/frontend/Tests/Functional/Rendering/Fixtures/UriPrefixRenderingTest.typoscript
typo3/sysext/frontend/Tests/Functional/Rendering/LocalizedContentRenderingTest.php [deleted file]
typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/LinkGenerator.typoscript
typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/LinkRequest.typoscript
typo3/sysext/frontend/Tests/Functional/SiteHandling/LinkGeneratorTest.php [deleted file]
typo3/sysext/frontend/Tests/Functional/SiteHandling/PlainRequestTest.php [deleted file]
typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugLinkGeneratorTest.php
typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugSiteRequestTest.php
typo3/sysext/frontend/Tests/Unit/Controller/TypoScriptFrontendControllerTest.php
typo3/sysext/indexed_search/Classes/Controller/SearchController.php
typo3/sysext/info/Classes/Controller/PageInformationController.php
typo3/sysext/install/Configuration/ExtensionScanner/Php/ArrayDimensionMatcher.php
typo3/sysext/install/Configuration/ExtensionScanner/Php/ClassNameMatcher.php
typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallStaticMatcher.php
typo3/sysext/t3editor/Resources/Private/tsref.xml
typo3/sysext/t3editor/Resources/Public/JavaScript/Mode/typoscript/typoscript.js

index d4b7162..d333f76 100644 (file)
@@ -28,7 +28,6 @@ use TYPO3\CMS\Core\Http\JsonResponse;
 use TYPO3\CMS\Core\Imaging\Icon;
 use TYPO3\CMS\Core\Imaging\IconFactory;
 use TYPO3\CMS\Core\Localization\LanguageService;
-use TYPO3\CMS\Core\Site\PseudoSiteFinder;
 use TYPO3\CMS\Core\Site\SiteFinder;
 use TYPO3\CMS\Core\Type\Bitmask\JsConfirmation;
 use TYPO3\CMS\Core\Type\Bitmask\Permission;
@@ -400,14 +399,7 @@ class TreeController
             $site = $siteFinder->getSiteByRootPageId($pageId);
             $domain = (string)$site->getBase();
         } catch (SiteNotFoundException $e) {
-            // No site found, let's see if it is a legacy-pseudo-site
-            $pseudoSiteFinder = GeneralUtility::makeInstance(PseudoSiteFinder::class);
-            try {
-                $site = $pseudoSiteFinder->getSiteByRootPageId($pageId);
-                $domain = trim((string)$site->getBase(), '/');
-            } catch (SiteNotFoundException $e) {
-                // No pseudo-site found either
-            }
+            // No site found
         }
 
         return $domain;
index 5cf0930..865678f 100644 (file)
@@ -220,12 +220,17 @@ class InputSlugElement extends AbstractFormElement
      */
     protected function getPrefix(SiteInterface $site, int $requestLanguageId = 0): string
     {
-        $language = ($requestLanguageId < 0) ? $site->getDefaultLanguage() : $site->getLanguageById($requestLanguageId);
-        $base = $language->getBase();
-        $baseUrl = (string)$base;
-        $baseUrl = rtrim($baseUrl, '/');
-        if (!empty($baseUrl) && empty($base->getScheme()) && $base->getHost() !== '') {
-            $baseUrl = 'http:' . $baseUrl;
+        try {
+            $language = ($requestLanguageId < 0) ? $site->getDefaultLanguage() : $site->getLanguageById($requestLanguageId);
+            $base = $language->getBase();
+            $baseUrl = (string)$base;
+            $baseUrl = rtrim($baseUrl, '/');
+            if (!empty($baseUrl) && empty($base->getScheme()) && $base->getHost() !== '') {
+                $baseUrl = 'http:' . $baseUrl;
+            }
+        } catch (\InvalidArgumentException $e) {
+            // No site found
+            $baseUrl = '';
         }
         return $baseUrl;
     }
index 90fcfc4..bbe1ced 100644 (file)
@@ -16,7 +16,6 @@ namespace TYPO3\CMS\Backend\Tree\View;
 
 use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Core\Exception\SiteNotFoundException;
-use TYPO3\CMS\Core\Site\PseudoSiteFinder;
 use TYPO3\CMS\Core\Site\SiteFinder;
 use TYPO3\CMS\Core\Type\Bitmask\Permission;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -160,15 +159,7 @@ class BrowseTreeView extends AbstractTreeView
                 $site = $siteFinder->getSiteByRootPageId($pageId);
                 $title .= ' [' . (string)$site->getBase() . ']';
             } catch (SiteNotFoundException $e) {
-                // No site found, let's see if it is a legacy-pseudo-site
-                $pseudoSiteFinder = GeneralUtility::makeInstance(PseudoSiteFinder::class);
-
-                try {
-                    $site = $pseudoSiteFinder->getSiteByRootPageId($pageId);
-                    $title .= ' [' . trim((string)$site->getBase(), '/') . ']';
-                } catch (SiteNotFoundException $e) {
-                    // No pseudo-site found either
-                }
+                // No site found
             }
         }
         return $title;
index bcd9d82..78e4007 100644 (file)
@@ -30,7 +30,6 @@ use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
 use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
 use TYPO3\CMS\Core\Database\RelationHandler;
 use TYPO3\CMS\Core\Exception\SiteNotFoundException;
-use TYPO3\CMS\Core\Http\ServerRequest;
 use TYPO3\CMS\Core\Imaging\Icon;
 use TYPO3\CMS\Core\Imaging\IconFactory;
 use TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection;
@@ -40,8 +39,6 @@ use TYPO3\CMS\Core\Resource\ProcessedFile;
 use TYPO3\CMS\Core\Resource\ResourceFactory;
 use TYPO3\CMS\Core\Routing\InvalidRouteArgumentsException;
 use TYPO3\CMS\Core\Routing\RouterInterface;
-use TYPO3\CMS\Core\Routing\SiteMatcher;
-use TYPO3\CMS\Core\Site\Entity\PseudoSite;
 use TYPO3\CMS\Core\Site\SiteFinder;
 use TYPO3\CMS\Core\Type\Bitmask\Permission;
 use TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser;
@@ -2564,19 +2561,6 @@ class BackendUtility
                     $domainName = $previewDomainConfig;
                 }
             }
-            if ($domainName === null) {
-                // Fetch the "sys_domain" record: First, check for the given domain,
-                // and find the "root page" = PseudoSite to that domain, then fetch the first
-                // available sys_domain record.
-                $siteMatcher = GeneralUtility::makeInstance(SiteMatcher::class);
-                $result = $siteMatcher->matchRequest(new ServerRequest($domain));
-                $site = $result->getSite();
-                if ($site instanceof PseudoSite) {
-                    $domainName = (string)$site->getBase();
-                    $domainName = ltrim($domainName, '/');
-                }
-            }
-
             if ($domainName) {
                 $domain = $protocol . '://' . $domainName;
             }
index 08b7d59..a88317b 100644 (file)
@@ -58,25 +58,4 @@ class InputSlugElementTest extends UnitTestCase
         static::assertSame('/en', $subject->_call('getPrefix', $site, 0));
         static::assertSame('/de', $subject->_call('getPrefix', $site, 1));
     }
-
-    /**
-     * @test
-     */
-    public function getPrefixThrowsInvalidArgumentExceptionForUndefinedLanguages(): void
-    {
-        $this->expectException(\InvalidArgumentException::class);
-        $this->expectExceptionCode(1522960188);
-
-        $site = new Site('www.foo.de', 0, []);
-
-        $subject = $this->getAccessibleMock(
-            InputSlugElement::class,
-            ['dummy'],
-            [],
-            '',
-            false
-        );
-
-        $subject->_call('getPrefix', $site, 99);
-    }
 }
index 1d7a273..e5c49d5 100644 (file)
@@ -16,7 +16,8 @@ namespace TYPO3\CMS\Core\Compatibility;
  */
 
 use TYPO3\CMS\Core\Routing\SiteMatcher;
-use TYPO3\CMS\Core\Site\Entity\PseudoSite;
+use TYPO3\CMS\Core\Site\Entity\NullSite;
+use TYPO3\CMS\Core\Site\Entity\Site;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -77,7 +78,7 @@ class PseudoSiteTcaDisplayCondition
         // If not a Site or a NullSite object, it must be a PseudoSite. We show the slug for
         // NullSites (new pages below root) to simplify the editing workflow a bit.
         $site = GeneralUtility::makeInstance(SiteMatcher::class)->matchByPageId($defaultLanguagePageId);
-        $isInPseudoSite = ($site instanceof PseudoSite);
+        $isInPseudoSite = !($site instanceof Site || $site instanceof NullSite);
 
         if ($parameters['conditionParameters'][1] === 'false') {
             // Negate if requested
index 5d231ea..0f794c8 100644 (file)
@@ -24,76 +24,6 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 class LanguageAspectFactory
 {
     /**
-     * Create a language aspect based on TypoScript settings, which we know:
-     *
-     * config.sys_language_uid
-     * config.sys_language_mode
-     * config.sys_language_overlay
-     *
-     * @param array $config
-     * @return LanguageAspect
-     */
-    public static function createFromTypoScript(array $config): LanguageAspect
-    {
-        // Get values from TypoScript, if not set before
-        $languageId = (int)($config['sys_language_uid'] ?? 0);
-        $fallbacks = GeneralUtility::trimExplode(';', $config['sys_language_mode'] ?? '');
-        $fallbackMode = null;
-        if (isset($fallbacks[0])) {
-            $fallbackMode = $fallbacks[0];
-        }
-        $fallbackOrder = null;
-        if (isset($fallbacks[1])) {
-            $fallbackOrder = $fallbacks[1];
-        }
-
-        // Page resolving
-        switch ($fallbackMode) {
-            case 'strict':
-                $fallBackOrder = [];
-                break;
-                // Ignore anything if a page cannot be found, and resolve pageId=0 instead.
-            case 'ignore':
-                $fallBackOrder = [-1];
-                break;
-            case 'fallback':
-            case 'content_fallback':
-                if (!empty($fallbackOrder)) {
-                    $fallBackOrder = GeneralUtility::trimExplode(',', $fallbackOrder);
-                    // no strict typing explictly done here
-                    if (!in_array(0, $fallBackOrder) && !in_array('pageNotFound', $fallBackOrder)) {
-                        $fallBackOrder[] = 'pageNotFound';
-                    }
-                } else {
-                    $fallBackOrder = [0];
-                }
-                break;
-            case '':
-                $fallBackOrder = ['off'];
-                break;
-            default:
-                $fallBackOrder = [0];
-        }
-
-        // Content fetching
-        switch ((string)($config['sys_language_overlay'] ?? '')) {
-            case '1':
-                $overlayType = LanguageAspect::OVERLAYS_MIXED;
-                break;
-            case '0':
-                $overlayType = LanguageAspect::OVERLAYS_OFF;
-                break;
-            case 'hideNonTranslated':
-                $overlayType = LanguageAspect::OVERLAYS_ON;
-                break;
-            default:
-                $overlayType = LanguageAspect::OVERLAYS_ON_WITH_FLOATING;
-        }
-
-        return GeneralUtility::makeInstance(LanguageAspect::class, $languageId, $languageId, $overlayType, $fallBackOrder);
-    }
-
-    /**
      * Site Languages always run with overlays + floating records.
      *
      * @param SiteLanguage $language
index ecc1278..c247df9 100644 (file)
@@ -117,6 +117,20 @@ class PageRouter implements RouterInterface
         if (!($previousResult instanceof RouteResultInterface)) {
             throw new RouteNotFoundException('No previous result given. Cannot find a page for an empty route part', 1555303496);
         }
+        // Legacy URIs (?id=12345) takes precedence, no matter if a route is given
+        $requestId = (string)($request->getQueryParams()['id'] ?? '');
+        if (!empty($requestId)) {
+            if (!empty($page = $this->resolvePageId($requestId))) {
+                return new PageArguments(
+                    (int)($page['l10n_parent'] ?: $page['uid']),
+                    (string)($request->getQueryParams()['type'] ?? '0'),
+                    [],
+                    [],
+                    $request->getQueryParams()
+                );
+            }
+            throw new RouteNotFoundException('The requested page does not exist.', 1557839801);
+        }
         $urlPath = $previousResult->getTail();
         // Remove the script name (e.g. index.php), if given
         if (!empty($urlPath)) {
@@ -388,6 +402,38 @@ class PageRouter implements RouterInterface
     }
 
     /**
+     * @param string $pageId
+     * @return array|null
+     */
+    protected function resolvePageId(string $pageId): ?array
+    {
+        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+            ->getQueryBuilderForTable('pages');
+        $queryBuilder
+            ->getRestrictions()
+            ->removeAll()
+            ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
+            ->add(GeneralUtility::makeInstance(FrontendWorkspaceRestriction::class));
+
+        $statement = $queryBuilder
+            ->select('uid', 'l10n_parent', 'pid')
+            ->from('pages')
+            ->where(
+                $queryBuilder->expr()->eq(
+                    'uid',
+                    $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT)
+                )
+            )
+            ->execute();
+
+        $page = $statement->fetch();
+        if (empty($page)) {
+            return null;
+        }
+        return $page;
+    }
+
+    /**
      * Fetch possible enhancers + aspects based on the current page configuration and the site configuration put
      * into "routeEnhancers"
      *
index 332488d..1b52cc5 100644 (file)
@@ -24,17 +24,16 @@ use Symfony\Component\Routing\RequestContext;
 use TYPO3\CMS\Core\Cache\CacheManager;
 use TYPO3\CMS\Core\Exception\SiteNotFoundException;
 use TYPO3\CMS\Core\SingletonInterface;
-use TYPO3\CMS\Core\Site\Entity\PseudoSite;
+use TYPO3\CMS\Core\Site\Entity\NullSite;
 use TYPO3\CMS\Core\Site\Entity\SiteInterface;
 use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
-use TYPO3\CMS\Core\Site\PseudoSiteFinder;
 use TYPO3\CMS\Core\Site\SiteFinder;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\HttpUtility;
 use TYPO3\CMS\Core\Utility\RootlineUtility;
 
 /**
- * Returns a site or pseudo-site (with sys_domain records) based on a given request.
+ * Returns a site based on a given request.
  *
  * The main usage is the ->matchRequest() functionality, which receives a request object and boots up
  * Symfony Routing to find the proper route with its defaults / attributes.
@@ -55,19 +54,13 @@ class SiteMatcher implements SingletonInterface
     protected $finder;
 
     /**
-     * @var PseudoSiteFinder
-     */
-    protected $pseudoSiteFinder;
-
-    /**
-     * Injects necessary objects. PseudoSiteFinder is not injectable as this will be become obsolete in the future.
+     * Injects necessary objects.
      *
      * @param SiteFinder|null $finder
      */
     public function __construct(SiteFinder $finder = null)
     {
         $this->finder = $finder ?? GeneralUtility::makeInstance(SiteFinder::class);
-        $this->pseudoSiteFinder = GeneralUtility::makeInstance(PseudoSiteFinder::class);
     }
 
     /**
@@ -82,8 +75,6 @@ class SiteMatcher implements SingletonInterface
         /** Ensure root line caches are flushed */
         RootlineUtility::purgeCaches();
         GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_rootline')->flush();
-        $this->pseudoSiteFinder = GeneralUtility::makeInstance(PseudoSiteFinder::class);
-        $this->pseudoSiteFinder->refresh();
     }
 
     /**
@@ -156,41 +147,19 @@ class SiteMatcher implements SingletonInterface
                     $result['tail']
                 );
             } catch (NoConfigurationException | ResourceNotFoundException $e) {
-                // No site+language combination found so far
+                // At this point we discard a possible found site via ?id=123
+                // Because ?id=123 _can_ only work if the actual domain/site base works
+                // so www.domain-without-site-configuration/index.php?id=123 (where 123 is a page referring
+                // to a page within a site configuration will never be resolved here) properly
+                $site = new NullSite();
             }
-            // At this point we discard a possible found site via ?id=123
-            // Because ?id=123 _can_ only work if the actual domain/site base works
-            // so www.domain-without-site-configuration/index.php?id=123 (where 123 is a page referring
-            // to a page within a site configuration will never be resolved here) properly
-            $site = null;
         }
 
-        // Check against any sys_domain records
-        $collection = $this->getRouteCollectionForVisibleSysDomains();
-        $context = new RequestContext('/', $request->getMethod(), $request->getUri()->getHost());
-        $matcher = new UrlMatcher($collection, $context);
-        try {
-            $result = $matcher->match($request->getUri()->getPath());
-            return new SiteRouteResult($request->getUri(), $result['site'], $result['language'], $result['tail']);
-        } catch (NoConfigurationException | ResourceNotFoundException $e) {
-            // No domain record found
-        }
-        // No domain record found, try resolving "pseudo-site" again
-        if ($site == null) {
-            try {
-                // use the matching "pseudo-site" for $pageId
-                $site = $this->pseudoSiteFinder->getSiteByPageId((int)$pageId);
-            } catch (SiteNotFoundException $exception) {
-                // use the first "pseudo-site" found
-                $allPseudoSites = $this->pseudoSiteFinder->findAll();
-                $site = reset($allPseudoSites);
-            }
-        }
         return new SiteRouteResult($request->getUri(), $site, $language);
     }
 
     /**
-     * If a given page ID is handed in, a Site/PseudoSite/NullSite is returned.
+     * If a given page ID is handed in, a Site/NullSite is returned.
      *
      * @param int $pageId uid of a page in default language
      * @param array|null $rootLine an alternative root line, if already at and.
@@ -202,8 +171,7 @@ class SiteMatcher implements SingletonInterface
         try {
             return $this->finder->getSiteByPageId($pageId, $rootLine);
         } catch (SiteNotFoundException $e) {
-            // Check for a pseudo / null site
-            return $this->pseudoSiteFinder->getSiteByPageId($pageId, $rootLine);
+            return new NullSite();
         }
     }
 
@@ -247,42 +215,6 @@ class SiteMatcher implements SingletonInterface
     }
 
     /**
-     * Return the page ID (pid) of a sys_domain record, based on a request object, does the infamous
-     * "recursive domain search", to also detect if the domain is like "abc.def.example.com" even if the
-     * sys_domain entry is "example.com".
-     *
-     * @return RouteCollection
-     */
-    protected function getRouteCollectionForVisibleSysDomains(): RouteCollection
-    {
-        $sites = $this->pseudoSiteFinder->findAll();
-        $groupedRoutes = [];
-        foreach ($sites as $site) {
-            if (!$site instanceof PseudoSite) {
-                continue;
-            }
-            foreach ($site->getEntryPoints() as $uri) {
-                // Site has no sys_domain record, it is not valid for a routing entrypoint, but only available
-                // via "id" GET parameter which is handled separately
-                if (!$uri->getHost()) {
-                    continue;
-                }
-                $route = new Route(
-                    ($uri->getPath() ?: '/') . '{tail}',
-                    ['site' => $site, 'language' => null, 'tail' => ''],
-                    array_filter(['tail' => '.*', 'port' => (string)$uri->getPort()]),
-                    ['utf8' => true],
-                    $uri->getHost(),
-                    $uri->getScheme()
-                );
-                $identifier = 'site_' . $site->getIdentifier() . '_' . (string)$uri;
-                $groupedRoutes[($uri->getScheme() ?: '-') . ($uri->getHost() ?: '-')][$uri->getPath() ?: '/'][$identifier] = $route;
-            }
-        }
-        return $this->createRouteCollectionFromGroupedRoutes($groupedRoutes);
-    }
-
-    /**
      * As the {tail} parameter is greedy, it needs to be ensured that the one with the
      * most specific part matches first.
      *
index 6d90944..23265a1 100644 (file)
@@ -47,16 +47,26 @@ class NullSite implements SiteInterface
      */
     public function __construct(array $languages = null, Uri $baseEntryPoint = null)
     {
-        foreach ($languages ?? [] as $languageConfiguration) {
-            $languageUid = (int)$languageConfiguration['languageId'];
-            // Language configuration does not have a base defined
-            // So the main site base is used (usually done for default languages)
-            $this->languages[$languageUid] = new SiteLanguage(
-                $languageUid,
-                $languageConfiguration['locale'] ?? '',
-                $baseEntryPoint ?: new Uri('/'),
-                $languageConfiguration
+        if (empty($languages)) {
+            // Create the default language if no language configuration is given
+            $this->languages[0] = new SiteLanguage(
+                0,
+                '',
+                new Uri('/'),
+                ['enabled' => true]
             );
+        } else {
+            foreach ($languages ?? [] as $languageConfiguration) {
+                $languageUid = (int)$languageConfiguration['languageId'];
+                // Language configuration does not have a base defined
+                // So the main site base is used (usually done for default languages)
+                $this->languages[$languageUid] = new SiteLanguage(
+                    $languageUid,
+                    $languageConfiguration['locale'] ?? '',
+                    $baseEntryPoint ?: new Uri('/'),
+                    $languageConfiguration
+                );
+            }
         }
     }
 
diff --git a/typo3/sysext/core/Classes/Site/Entity/PseudoSite.php b/typo3/sysext/core/Classes/Site/Entity/PseudoSite.php
deleted file mode 100644 (file)
index a275175..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-<?php
-declare(strict_types = 1);
-
-namespace TYPO3\CMS\Core\Site\Entity;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use Psr\Http\Message\UriInterface;
-use TYPO3\CMS\Core\Http\Uri;
-
-/**
- * Entity representing a site with legacy configuration (sys_domain) and all available
- * languages in the system (sys_language)
- * @internal this class will likely be removed in TYPO3 v10.0. Please use SiteMatcher and SiteInterface to work with Sites in your own code.
- */
-class PseudoSite extends NullSite implements SiteInterface
-{
-    /**
-     * @var string[]
-     */
-    protected $entryPoints;
-
-    /**
-     * attached sys_domain records
-     * @var array
-     */
-    protected $domainRecords = [];
-
-    /**
-     * Sets up a pseudo site object, and its languages and error handlers
-     *
-     * @param int $rootPageId
-     * @param array $configuration
-     */
-    public function __construct(int $rootPageId, array $configuration)
-    {
-        $this->rootPageId = $rootPageId;
-        foreach ($configuration['domains'] ?? [] as $domain) {
-            if (empty($domain['domainName'] ?? false)) {
-                continue;
-            }
-            $this->domainRecords[] = $domain;
-            $this->entryPoints[] = new Uri($this->sanitizeBaseUrl($domain['domainName'] ?: ''));
-        }
-        if (empty($this->entryPoints)) {
-            $this->entryPoints = [new Uri('/')];
-        }
-        $baseEntryPoint = reset($this->entryPoints);
-
-        parent::__construct($configuration['languages'], $baseEntryPoint);
-    }
-
-    /**
-     * Returns a generic identifier
-     *
-     * @return string
-     */
-    public function getIdentifier(): string
-    {
-        return '#PSEUDO_' . $this->rootPageId;
-    }
-
-    /**
-     * Returns the first base URL of this site, falls back to "/"
-     */
-    public function getBase(): UriInterface
-    {
-        return $this->entryPoints[0] ?? new Uri('/');
-    }
-
-    /**
-     * Returns the base URLs of this site, if none given, it's always "/"
-     *
-     * @return UriInterface[]
-     */
-    public function getEntryPoints(): array
-    {
-        return $this->entryPoints;
-    }
-
-    /**
-     * Returns the root page ID of this site
-     *
-     * @return int
-     */
-    public function getRootPageId(): int
-    {
-        return $this->rootPageId;
-    }
-
-    /**
-     * If a site base contains "/" or "www.domain.com", it is ensured that
-     * parse_url() can handle this kind of configuration properly.
-     *
-     * @param string $base
-     * @return string
-     */
-    protected function sanitizeBaseUrl(string $base): string
-    {
-        // no protocol ("//") and the first part is no "/" (path), means that this is a domain like
-        // "www.domain.com/blabla", and we want to ensure that this one then gets a "no-scheme agnostic" part
-        if (!empty($base) && strpos($base, '//') === false && $base{0} !== '/') {
-            // either a scheme is added, or no scheme but with domain, or a path which is not absolute
-            // make the base prefixed with a slash, so it is recognized as path, not as domain
-            // treat as path
-            if (strpos($base, '.') === false) {
-                $base = '/' . $base;
-            } else {
-                // treat as domain name
-                $base = '//' . $base;
-            }
-        }
-        return $base;
-    }
-}
diff --git a/typo3/sysext/core/Classes/Site/PseudoSiteFinder.php b/typo3/sysext/core/Classes/Site/PseudoSiteFinder.php
deleted file mode 100644 (file)
index 66c7274..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-<?php
-declare(strict_types = 1);
-
-namespace TYPO3\CMS\Core\Site;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\CMS\Core\Cache\CacheManager;
-use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
-use TYPO3\CMS\Core\Database\ConnectionPool;
-use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
-use TYPO3\CMS\Core\Database\Query\Restriction\FrontendWorkspaceRestriction;
-use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
-use TYPO3\CMS\Core\Exception\Page\PageNotFoundException;
-use TYPO3\CMS\Core\Exception\SiteNotFoundException;
-use TYPO3\CMS\Core\Site\Entity\NullSite;
-use TYPO3\CMS\Core\Site\Entity\PseudoSite;
-use TYPO3\CMS\Core\Site\Entity\SiteInterface;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Core\Utility\RootlineUtility;
-
-/**
- * Methods related to "pseudo-sites" = sites that do not have a configuration yet.
- * @internal this class will likely be removed in TYPO3 v10.0. Please use SiteMatcher and not the PseudoSiteFinder directly to make use of caching etc.
- */
-class PseudoSiteFinder
-{
-    /**
-     * @var string
-     */
-    protected $cacheIdentifier = 'pseudo-sites';
-
-    /**
-     * @var FrontendInterface
-     */
-    protected $cache;
-
-    /**
-     * @var PseudoSite[]
-     */
-    protected $pseudoSites = [];
-
-    public function __construct()
-    {
-        $this->cache = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_core');
-    }
-
-    /**
-     * Fetches all site root pages, all sys_language records and forms pseudo-sites,
-     * but only for the pagetree's that do not have a site configuration available.
-     */
-    protected function populate(bool $allowCaching = true)
-    {
-        $data = $this->cache->get($this->cacheIdentifier);
-        if (empty($data) || $allowCaching === false) {
-            $allLanguages = $this->getAllLanguageRecords();
-            $availablePages = $this->getAllRootPagesWithoutSiteConfiguration();
-            $this->cache->set($this->cacheIdentifier, json_encode([$allLanguages, $availablePages]));
-        } else {
-            // Due to the nature of PhpFrontend, the `<?php` and `#` wraps have to be removed
-            $data = preg_replace('/^<\?php\s*|\s*#$/', '', $data);
-            list($allLanguages, $availablePages) = json_decode($data, true);
-        }
-
-        $this->pseudoSites = [];
-        foreach ($availablePages as $row) {
-            $rootPageId = (int)$row['uid'];
-            $site = new PseudoSite($rootPageId, [
-                'domains' => [],
-                'languages' => $allLanguages
-            ]);
-            $this->pseudoSites[$rootPageId] = $site;
-        }
-
-        // Now lets an empty Pseudo-Site for visiting things on pid=0
-        $this->pseudoSites[0] = new NullSite($allLanguages);
-    }
-
-    /**
-     * Returns all pseudo sites, including one for "pid=0".
-     *
-     * @return PseudoSite[]
-     */
-    public function findAll(): array
-    {
-        if (empty($this->pseudoSites)) {
-            $this->populate();
-        }
-        return $this->pseudoSites;
-    }
-
-    /**
-     * Rebuild the cache information from the database information.
-     *
-     * @internal
-     */
-    public function refresh()
-    {
-        $this->populate(false);
-    }
-
-    /**
-     * Fetches all "sys_language" records.
-     *
-     * @return array
-     */
-    protected function getAllLanguageRecords(): array
-    {
-        $languageRecords = [
-            0 => [
-                'languageId' => 0,
-                'title' => 'Default',
-                'flag' => '',
-            ],
-        ];
-
-        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_language');
-        $queryBuilder->getRestrictions()->removeByType(HiddenRestriction::class);
-        $statement = $queryBuilder
-            ->select('*')
-            ->from('sys_language')
-            ->orderBy('sorting')
-            ->execute();
-        while ($row = $statement->fetch()) {
-            $uid = (int)$row['uid'];
-            $languageRecords[$uid] = [
-                'languageId' => $uid,
-                'title' => $row['title'],
-                'iso-639-1' => $row['language_isocode'] ?? '',
-                'flag' => 'flags-' . $row['flag'],
-                'enabled' => !$row['hidden'],
-            ];
-        }
-
-        return $languageRecords;
-    }
-
-    /**
-     * Traverses the rootline of a page up until a PseudoSite was found.
-     * The main use-case here is in the TYPO3 Backend when the middleware tries to detect
-     * a PseudoSite
-     *
-     * @param int $pageId
-     * @param array $rootLine
-     * @return SiteInterface
-     * @throws SiteNotFoundException
-     */
-    public function getSiteByPageId(int $pageId, array $rootLine = null): SiteInterface
-    {
-        $this->findAll();
-        if (isset($this->pseudoSites[$pageId])) {
-            return $this->pseudoSites[$pageId];
-        }
-        if (!is_array($rootLine)) {
-            try {
-                $rootLine = GeneralUtility::makeInstance(RootlineUtility::class, $pageId)->get();
-            } catch (PageNotFoundException $e) {
-                $rootLine = [];
-            }
-        }
-        foreach ($rootLine as $pageInRootLine) {
-            if (isset($this->pseudoSites[(int)$pageInRootLine['uid']])) {
-                return $this->pseudoSites[(int)$pageInRootLine['uid']];
-            }
-        }
-        throw new SiteNotFoundException('No pseudo-site found in root line of page ' . $pageId, 1534710048);
-    }
-
-    /**
-     * Find a site by given root page id
-     *
-     * @param int $rootPageId the page ID (default language)
-     * @return SiteInterface
-     * @throws SiteNotFoundException
-     */
-    public function getSiteByRootPageId(int $rootPageId): SiteInterface
-    {
-        if (empty($this->pseudoSites)) {
-            $this->populate();
-        }
-        if (isset($this->pseudoSites[$rootPageId])) {
-            return $this->pseudoSites[$rootPageId];
-        }
-        throw new SiteNotFoundException('No pseudo-site found for root page id ' . $rootPageId, 1521668982);
-    }
-
-    /**
-     * Loads all sites with a configuration, and takes their rootPageId.
-     *
-     * @return array
-     */
-    protected function getExistingSiteConfigurationRootPageIds(): array
-    {
-        $usedPageIds = [];
-        $finder = GeneralUtility::makeInstance(SiteFinder::class);
-        $sites = $finder->getAllSites();
-        foreach ($sites as $site) {
-            $usedPageIds[] = $site->getRootPageId();
-        }
-        return $usedPageIds;
-    }
-
-    /**
-     * Do a SQL query for root pages (pid=0 or is_siteroot=1) that do not have a site configuration
-     * @return array
-     */
-    protected function getAllRootPagesWithoutSiteConfiguration(): array
-    {
-        $usedPageIds = $this->getExistingSiteConfigurationRootPageIds();
-        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
-        $queryBuilder->getRestrictions()->removeAll()
-            ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
-            ->add(GeneralUtility::makeInstance(FrontendWorkspaceRestriction::class, 0, false));
-        $queryBuilder
-            ->select('uid')
-            ->from('pages')
-            ->where(
-                $queryBuilder->expr()->eq('sys_language_uid', 0),
-                $queryBuilder->expr()->orX(
-                    $queryBuilder->expr()->eq('pid', 0),
-                    $queryBuilder->expr()->eq('is_siteroot', 1)
-                )
-            )
-            ->orderBy('pid')
-            ->addOrderBy('sorting');
-
-        if (!empty($usedPageIds)) {
-            $queryBuilder->andWhere($queryBuilder->expr()->notIn('uid', $usedPageIds));
-        }
-        $availablePages = $queryBuilder->execute()->fetchAll();
-        return is_array($availablePages) ? $availablePages : [];
-    }
-}
index 40c416c..eab0b17 100644 (file)
@@ -34,6 +34,8 @@ The following PHP classes that have been previously deprecated for v9 have been
 * :php:`TYPO3\CMS\Core\PageTitle\AltPageTitleProvider`
 * :php:`TYPO3\CMS\Core\Resource\Service\UserStorageCapabilityService`
 * :php:`TYPO3\CMS\Core\Resource\Utility\BackendUtility`
+* :php:`TYPO3\CMS\Core\Site\Entity\PseudoSite`
+* :php:`TYPO3\CMS\Core\Site\PseudoSiteFinder`
 * :php:`TYPO3\CMS\Core\TypoScript\ConfigurationForm`
 * :php:`TYPO3\CMS\Core\Utility\ClientUtility`
 * :php:`TYPO3\CMS\Core\Utility\PhpOptionsUtility`
@@ -529,6 +531,7 @@ The following PHP static class methods that have been previously deprecated for
 * :php:`TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory::determineSaltingHashingMethod()`
 * :php:`TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory::getSaltingInstance()`
 * :php:`TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory::setPreferredHashingMethod()`
+* :php:`TYPO3\CMS\Core\Context\LanguageAspectFactory::createFromTypoScript()`
 * :php:`TYPO3\CMS\Core\Utility\ExtensionManagementUtility::configureModule()`
 * :php:`TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getExtensionKeyByPrefix()`
 * :php:`TYPO3\CMS\Core\Utility\ExtensionManagementUtility::removeCacheFiles()`
@@ -1239,6 +1242,14 @@ The following user TSconfig options have been dropped:
 The following TypoScript options have been dropped:
 
 * `config.concatenateJsAndCss`
+* `config.typolinkEnableLinksAcrossDomains`
+* `config.language`
+* `config.locale_all`
+* `config.sys_language_isocode`
+* `config.sys_language_isocode_default`
+* `config.sys_language_mode`
+* `config.sys_language_overlay`
+* `config.sys_language_uid`
 * `config.titleTagFunction`
 * `config.typolinkCheckRootline`
 * `config.tx_extbase.objects`
@@ -1253,6 +1264,7 @@ The following TypoScript options have been dropped:
 * `stdWrap.filelist`
 * `SVG.noscript`
 * `SVG.value`
+* `typolink.useCacheHash`
 * `TMENU.beforeImg`
 * `TMENU.afterImg`
 * `GMENU`
@@ -1370,6 +1382,7 @@ The following global variables have been removed:
 The following hooks have been removed:
 
 * :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processUpload']`
+* :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tstemplate.php']['linkData-PostProc']`
 * :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/index_ts.php']['preBeUser']`
 * :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/index_ts.php']['postBeUser']`
 * :php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/index_ts.php']['preprocessRequest']`
index 4ea1fed..d6da61b 100644 (file)
@@ -1,13 +1,9 @@
 config {
        no_cache = 1
        debug = 0
-       xhtml_cleaning = 0
        admPanel = 0
        disableAllHeaderCode = 1
        sendCacheHeaders = 0
-       sys_language_uid = 0
-       sys_language_mode = ignore
-       sys_language_overlay = 1
        additionalHeaders.10.header = Content-Type: application/json; charset=utf-8
        additionalHeaders.10.replace = 1
 
@@ -261,12 +257,6 @@ page {
                                pid.data = page:pid
                                title.data = page:title
                        }
-                       tsfe.children {
-                               sys_language_uid.data = context:language:id
-                               sys_language_mode.data = context:language:legacyLanguageMode
-                               sys_language_content.data = context:language:contentId
-                               sys_language_contentOL.data = context:language:legacyOverlayType
-                       }
                        languageInfo.children {
                                id.data = context:language:id
                                contentId.data = context:language:contentId
@@ -279,13 +269,3 @@ page {
        }
        stdWrap.postUserFunc = TYPO3\TestingFramework\Core\Functional\Framework\Frontend\Renderer->renderSections
 }
-
-[request.getQueryParams()['L'] == 1 || request.getParsedBody()['L'] == 1]
-config.sys_language_uid = 1
-[end]
-[request.getQueryParams()['L'] == 2 || request.getParsedBody()['L'] == 2]
-config.sys_language_uid = 2
-[end]
-[request.getQueryParams()['L'] == 3 || request.getParsedBody()['L'] == 3]
-config.sys_language_uid = 3
-[end]
diff --git a/typo3/sysext/core/Tests/Unit/Site/Entity/PseudoSiteTest.php b/typo3/sysext/core/Tests/Unit/Site/Entity/PseudoSiteTest.php
deleted file mode 100644 (file)
index bea711a..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-<?php
-declare(strict_types = 1);
-
-namespace TYPO3\CMS\Core\Tests\Unit\Site\Entity;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\CMS\Core\Http\Uri;
-use TYPO3\CMS\Core\Site\Entity\PseudoSite;
-use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
-
-class PseudoSiteTest extends UnitTestCase
-{
-    /**
-     * @return array
-     */
-    public function pseudoSiteReturnsProperEntryPointsDataProvider()
-    {
-        return [
-            'no domain' => [
-                [],
-                [
-                    new Uri('/')
-                ],
-                new Uri('/')
-            ],
-            'invalid domain argument' => [
-                [
-                    ['domain_name' => 'not.recognized.com']
-                ],
-                [
-                    new Uri('/')
-                ],
-                new Uri('/')
-            ],
-            'regular domain given' => [
-                [
-                    ['domainName' => 'blog.example.com/download']
-                ],
-                [
-                    new Uri('//blog.example.com/download')
-                ],
-                new Uri('//blog.example.com/download')
-            ],
-            'multiple domains given' => [
-                [
-                    ['domainName' => 'www.example.com'],
-                    ['domainName' => 'blog.example.com'],
-                    ['domainName' => 'blog.example.com/food-koma'],
-                ],
-                [
-                    new Uri('//www.example.com'),
-                    new Uri('//blog.example.com'),
-                    new Uri('//blog.example.com/food-koma'),
-                ],
-                new Uri('//www.example.com')
-            ]
-        ];
-    }
-
-    /**
-     * @test
-     * @dataProvider pseudoSiteReturnsProperEntryPointsDataProvider
-     */
-    public function pseudoSiteReturnsProperEntryPoints($sysDomainRecords, $expectedResolvedEntryPoints, $expectedFirstEntryPoint)
-    {
-        $subject = new PseudoSite(13, ['domains' => $sysDomainRecords, 'languages' => []]);
-        $this->assertEquals($expectedResolvedEntryPoints, $subject->getEntryPoints());
-        $this->assertEquals($expectedFirstEntryPoint, $subject->getBase());
-    }
-}
index 313af76..54f35ff 100644 (file)
@@ -1,11 +1,9 @@
 config {
        no_cache = 1
        debug = 0
-       xhtml_cleaning = 0
        admPanel = 0
        disableAllHeaderCode = 1
        sendCacheHeaders = 0
-       sys_language_uid = 0
        additionalHeaders.10.header = Content-Type: application/json; charset=utf-8
        additionalHeaders.10.replace = 1
 }
@@ -32,13 +30,3 @@ page {
 
        stdWrap.postUserFunc = TYPO3\TestingFramework\Core\Functional\Framework\Frontend\Renderer->renderSections
 }
-
-[request.getQueryParams()['L'] == 1 || request.getParsedBody()['L'] == 1]
-       config.sys_language_uid = 1
-[end]
-[request.getQueryParams()['L'] == 2 || request.getParsedBody()['L'] == 2]
-       config.sys_language_uid = 2
-[end]
-[request.getQueryParams()['L'] == 3 || request.getParsedBody()['L'] == 3]
-       config.sys_language_uid = 3
-[end]
index abd22f7..d7fc01b 100644 (file)
@@ -1,13 +1,9 @@
 config {
        no_cache = 1
        debug = 0
-       xhtml_cleaning = 0
        admPanel = 0
        disableAllHeaderCode = 1
        sendCacheHeaders = 0
-       sys_language_uid = 0
-       sys_language_mode = ignore
-       sys_language_overlay = 1
        additionalHeaders.10.header = Content-Type: application/json; charset=utf-8
        additionalHeaders.10.replace = 1
 }
@@ -34,7 +30,3 @@ page {
 
        stdWrap.postUserFunc = TYPO3\TestingFramework\Core\Functional\Framework\Frontend\Renderer->renderSections
 }
-
-[request.getQueryParams()['L'] == 1 || request.getParsedBody()['L'] == 1]
-       config.sys_language_uid = 1
-[end]
diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/TranslatedContentTest.php b/typo3/sysext/extbase/Tests/Functional/Persistence/TranslatedContentTest.php
deleted file mode 100644 (file)
index d5a8b09..0000000
+++ /dev/null
@@ -1,1073 +0,0 @@
-<?php
-declare(strict_types = 1);
-
-namespace TYPO3\CMS\Extbase\Tests\Functional\Persistence;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\CMS\Core\Tests\Functional\DataHandling\AbstractDataHandlerActionTestCase;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
-use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\ResponseContent;
-
-/**
- * Test case documenting an Extbase translation handling of tt_content consistent with TypoScript.
- *
- * The old inconsistent handling is tested here:
- * @see \TYPO3\CMS\Extbase\Tests\Functional\Persistence\TranslatedContentLegacyTest
- *
- * This test has the same scenarios as in the TypoScript version:
- * @see \TYPO3\CMS\Frontend\Tests\Functional\Rendering\LocalizedContentRenderingTest
- */
-class TranslatedContentTest extends AbstractDataHandlerActionTestCase
-{
-    const VALUE_PageId = 89;
-    const TABLE_Content = 'tt_content';
-    const TABLE_Pages = 'pages';
-
-    /**
-     * @var string
-     */
-    protected $scenarioDataSetDirectory = 'typo3/sysext/frontend/Tests/Functional/Rendering/DataSet/';
-
-    /**
-     * @var array
-     */
-    protected $testExtensionsToLoad = ['typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example'];
-
-    /**
-     * @var array
-     */
-    protected $coreExtensionsToLoad = ['extbase', 'fluid'];
-
-    /**
-     * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface The object manager
-     */
-    protected $objectManager;
-
-    /**
-     * @var \ExtbaseTeam\BlogExample\Domain\Repository\TtContentRepository
-     */
-    protected $contentRepository;
-
-    /**
-     * Custom 404 handler returning valid json is registered so the $this->getFrontendResponse()
-     * does not fail on 404 pages
-     *
-     * @var array
-     */
-    protected $configurationToUseInTestInstance = [
-        'FE' => [
-            'pageNotFound_handling' => 'READFILE:typo3/sysext/frontend/Tests/Functional/Rendering/DataSet/404Template.html'
-        ]
-    ];
-
-    /**
-     * @var array
-     */
-    protected $pathsToLinkInTestInstance = [
-        'typo3/sysext/core/Tests/Functional/Fixtures/Frontend/AdditionalConfiguration.php' => 'typo3conf/AdditionalConfiguration.php',
-        'typo3/sysext/frontend/Tests/Functional/Fixtures/Images' => 'fileadmin/user_upload'
-    ];
-
-    protected function setUp(): void
-    {
-        parent::setUp();
-        $this->importScenarioDataSet('LiveDefaultPages');
-        $this->importScenarioDataSet('LiveDefaultElements');
-
-        $this->objectManager = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
-        $this->contentRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\TtContentRepository::class);
-        $this->setUpFrontendRootPage(1, [
-            'typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Configuration/TypoScript/setup.typoscript',
-            'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/Frontend/ContentJsonRenderer.typoscript'
-
-        ]);
-    }
-
-    protected function tearDown(): void
-    {
-        unset($this->objectManager);
-        unset($this->contentRepository);
-        parent::tearDown();
-    }
-
-    public function defaultLanguageConfigurationDataProvider(): array
-    {
-        return [
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode =',
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = content_fallback',
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = content_fallback;1,0',
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = strict',
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = ignore',
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode =',
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = content_fallback',
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = content_fallback;1,0',
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = strict',
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = ignore',
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode =',
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = content_fallback',
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = content_fallback;1,0',
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = strict',
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = ignore',
-            ],
-        ];
-    }
-
-    /**
-     * For the default language all combination of language settings should give the same result,
-     * regardless of TypoScript settings, if the requested language is "0" then no TypoScript settings apply.
-     *
-     * @test
-     * @dataProvider defaultLanguageConfigurationDataProvider
-     *
-     * @param string $typoScript
-     */
-    public function onlyEnglishContentIsRenderedForDefaultLanguage(string $typoScript)
-    {
-        $this->addTypoScriptToTemplateRecord(1, $typoScript);
-
-        $frontendResponse = $this->getFrontendResponse(self::VALUE_PageId, 0);
-        $responseSections = $frontendResponse->getResponseSections('Extbase:list()');
-        $visibleHeaders = ['Regular Element #1', 'Regular Element #2', 'Regular Element #3'];
-        $this->assertThat(
-            $responseSections,
-            $this->getRequestSectionHasRecordConstraint()
-                ->setTable(self::TABLE_Content)
-                ->setField('header')
-                ->setValues(...$visibleHeaders)
-        );
-        $this->assertThat(
-            $responseSections,
-            $this->getRequestSectionDoesNotHaveRecordConstraint()
-                ->setTable(self::TABLE_Content)
-                ->setField('header')
-                ->setValues(...$this->getNonVisibleHeaders($visibleHeaders))
-        );
-
-        //assert FAL relations
-        $visibleFiles = ['T3BOARD'];
-        $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
-            ->setRecordIdentifier(self::TABLE_Content . ':297')->setRecordField('image')
-            ->setTable('sys_file_reference')->setField('title')->setValues(...$visibleFiles));
-
-        $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
-            ->setRecordIdentifier(self::TABLE_Content . ':297')->setRecordField('image')
-            ->setTable('sys_file_reference')->setField('title')->setValues(...$this->getNonVisibleFileTitles($visibleFiles)));
-
-        $visibleFiles = ['Kasper2'];
-        $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
-            ->setRecordIdentifier(self::TABLE_Content . ':298')->setRecordField('image')
-            ->setTable('sys_file_reference')->setField('title')->setValues(...$visibleFiles));
-
-        $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
-            ->setRecordIdentifier(self::TABLE_Content . ':298')->setRecordField('image')
-            ->setTable('sys_file_reference')->setField('title')->setValues(...$this->getNonVisibleFileTitles($visibleFiles)));
-
-        //assert Categories
-        $visibleCategories = ['Category 1', 'Category 3 - not translated'];
-        $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
-            ->setRecordIdentifier(self::TABLE_Content . ':297')->setRecordField('categories')
-            ->setTable('sys_category')->setField('title')->setValues(...$visibleCategories));
-
-        $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
-            ->setRecordIdentifier(self::TABLE_Content . ':297')->setRecordField('categories')
-            ->setTable('sys_category')->setField('title')->setValues(...$this->getNonVisibleCategoryTitles($visibleCategories)));
-    }
-
-    /**
-     * Dutch language has pages record and some content elements are translated
-     *
-     * @return array
-     */
-    public function dutchDataProvider(): array
-    {
-        //Expected behaviour:
-        //Page is translated to Dutch, so changing sys_language_mode does NOT change the results
-        //Page title is always [DK]Page, and both sys_language_content and sys_language_uid are always 1
-        return [
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                    config.sys_language_mode =',
-                'visibleRecords' => [
-                    300 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                    301 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                        'categories' => ['[Translate to Dansk:] Category 1', 'Category 4'],
-                    ],
-                    303 => [
-                        'header' => '[DK] Without default language',
-                        'image' => ['[T3BOARD] Image added to DK element without default language']
-                    ],
-                    308 => [
-                        'header' => '[DK] UnHidden Element #4',
-                        'image' => []
-                    ],
-                ],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = content_fallback',
-                'visibleRecords' => [
-                    300 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                    301 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                        'categories' => ['[Translate to Dansk:] Category 1', 'Category 4'],
-                    ],
-                    303 => [
-                        'header' => '[DK] Without default language',
-                        'image' => ['[T3BOARD] Image added to DK element without default language']
-                    ],
-                    308 => [
-                        'header' => '[DK] UnHidden Element #4',
-                        'image' => []
-                    ],
-                ],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = content_fallback;1,0',
-                'visibleRecords' => [
-                    300 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                    301 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                        'categories' => ['[Translate to Dansk:] Category 1', 'Category 4'],
-                    ],
-                    303 => [
-                        'header' => '[DK] Without default language',
-                        'image' => ['[T3BOARD] Image added to DK element without default language']
-                    ],
-                    308 => [
-                        'header' => '[DK] UnHidden Element #4',
-                        'image' => []
-                    ],
-                ],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = strict',
-                'visibleRecords' => [
-                    300 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                    301 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                        'categories' => ['[Translate to Dansk:] Category 1', 'Category 4'],
-                    ],
-                    303 => [
-                        'header' => '[DK] Without default language',
-                        'image' => ['[T3BOARD] Image added to DK element without default language']
-                    ],
-                    308 => [
-                        'header' => '[DK] UnHidden Element #4',
-                        'image' => []
-                    ],
-                ],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = ignore',
-                'visibleRecords' => [
-                    300 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                    301 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                        'categories' => ['[Translate to Dansk:] Category 1', 'Category 4'],
-                    ],
-                    303 => [
-                        'header' => '[DK] Without default language',
-                        'image' => ['[T3BOARD] Image added to DK element without default language']
-                    ],
-                    308 => [
-                        'header' => '[DK] UnHidden Element #4',
-                        'image' => []
-                    ],
-                ],
-            ],
-            5 => [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode =',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                        'categories' => ['[Translate to Dansk:] Category 1', 'Category 4'],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-            ],
-            // Expected behaviour:
-            // Not translated element #2 is shown because sys_language_overlay = 1 (with sys_language_overlay = hideNonTranslated, it would be hidden)
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = content_fallback',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                        'categories' => ['[Translate to Dansk:] Category 1', 'Category 4'],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-            ],
-            // Expected behaviour:
-            // Same as config.sys_language_mode = content_fallback because we're requesting language 1, so no additional fallback possible
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = content_fallback;1,0',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                        'categories' => ['[Translate to Dansk:] Category 1', 'Category 4'],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = strict',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                        'categories' => ['[Translate to Dansk:] Category 1', 'Category 4'],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = ignore',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                        'categories' => ['[Translate to Dansk:] Category 1', 'Category 4'],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-            ],
-            // Expected behaviour:
-            // Non translated default language elements are not shown, because of hideNonTranslated.
-            10 => [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode =',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                        'categories' => ['[Translate to Dansk:] Category 1', 'Category 4'],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = content_fallback',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                        'categories' => ['[Translate to Dansk:] Category 1', 'Category 4'],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = content_fallback;1,0',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                        'categories' => ['[Translate to Dansk:] Category 1', 'Category 4'],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-            ],
-            // Expected behaviour: Setting sys_language_mode = strict has the same effect as previous data sets,
-            // because the translation of the page exists
-            // This is not true in Extbase unfortunately. As visible here: sys_language_mode = strict, works like overlay = 0 in TypoScript rendering.
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = strict',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                        'categories' => ['[Translate to Dansk:] Category 1', 'Category 4'],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = ignore',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                        'categories' => ['[Translate to Dansk:] Category 1', 'Category 4'],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-            ],
-        ];
-    }
-
-    /**
-     * @test
-     * @dataProvider dutchDataProvider
-     *
-     * @param string $typoScript
-     * @param array $visibleRecords
-     */
-    public function renderingOfDutchLanguage(string $typoScript, array $visibleRecords)
-    {
-        $this->addTypoScriptToTemplateRecord(1, $typoScript);
-        $frontendResponse = $this->getFrontendResponse(self::VALUE_PageId, 1);
-        $responseSections = $frontendResponse->getResponseSections('Extbase:list()');
-        $visibleHeaders = array_map(function ($element) {
-            return $element['header'];
-        }, $visibleRecords);
-
-        $this->assertThat(
-            $responseSections,
-            $this->getRequestSectionHasRecordConstraint()
-                ->setTable(self::TABLE_Content)
-                ->setField('header')
-                ->setValues(...$visibleHeaders)
-        );
-        $this->assertThat(
-            $responseSections,
-            $this->getRequestSectionDoesNotHaveRecordConstraint()
-                ->setTable(self::TABLE_Content)
-                ->setField('header')
-                ->setValues(...$this->getNonVisibleHeaders($visibleHeaders))
-        );
-
-        foreach ($visibleRecords as $ttContentUid => $properties) {
-            $visibleFileTitles = $properties['image'];
-            if (!empty($visibleFileTitles)) {
-                $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
-                    ->setRecordIdentifier(self::TABLE_Content . ':' . $ttContentUid)->setRecordField('image')
-                    ->setTable('sys_file_reference')->setField('title')->setValues(...$visibleFileTitles));
-            }
-            $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
-                ->setRecordIdentifier(self::TABLE_Content . ':' . $ttContentUid)->setRecordField('image')
-                ->setTable('sys_file_reference')->setField('title')->setValues(...$this->getNonVisibleFileTitles($visibleFileTitles)));
-
-            $visibleCategoryTitles = $properties['categories'] ?? [];
-            if (!empty($visibleCategoryTitles)) {
-                $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
-                    ->setRecordIdentifier(self::TABLE_Content . ':' . $ttContentUid)->setRecordField('categories')
-                    ->setTable('sys_category')->setField('title')->setValues(...$visibleCategoryTitles));
-            }
-            $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
-                ->setRecordIdentifier(self::TABLE_Content . ':' . $ttContentUid)->setRecordField('categories')
-                ->setTable('sys_category')->setField('title')->setValues(...$this->getNonVisibleCategoryTitles($visibleCategoryTitles)));
-        }
-    }
-
-    public function contentOnNonTranslatedPageDataProvider(): array
-    {
-        //Expected behaviour:
-        //the page is NOT translated so setting sys_language_mode to different values changes the results
-        //- setting sys_language_mode to empty value makes TYPO3 return default language records
-        //- setting it to strict throws 404, independently from other settings
-        //Setting config.sys_language_overlay = 0
-        return [
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode =',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => 'Regular Element #1',
-                        'image' => ['T3BOARD'],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => 'Regular Element #3',
-                        'image' => ['Kasper'],
-                    ],
-                ],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = content_fallback',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => 'Regular Element #1',
-                        'image' => ['T3BOARD'],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => 'Regular Element #3',
-                        'image' => ['Kasper'],
-                    ],
-                ],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = content_fallback;1,0',
-                'visibleRecords' => [
-                    300 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                    301 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                    ],
-                    303 => [
-                        'header' => '[DK] Without default language',
-                        'image' => ['[T3BOARD] Image added to DK element without default language'],
-                    ],
-                    308 => [
-                        'header' => '[DK] UnHidden Element #4',
-                        'image' => [],
-                    ],
-                ],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = strict',
-                'visibleRecords' => [],
-                'statusCode' => 404,
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = ignore',
-                'visibleRecords' => [
-                    302 => [
-                        'header' => '[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1',
-                        'image' => ['[T3BOARD] image translated to DE from DK'],
-                    ],
-                    304 => [
-                        'header' => '[DE] Without default language',
-                        'image' => [],
-                    ],
-                ],
-            ],
-            5 => [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode =',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => 'Regular Element #1',
-                        'image' => ['T3BOARD'],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => 'Regular Element #3',
-                        'image' => ['Kasper'],
-                    ],
-                ],
-            ],
-            //falling back to default language
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = content_fallback',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => 'Regular Element #1',
-                        'image' => ['T3BOARD'],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => 'Regular Element #3',
-                        'image' => ['Kasper'],
-                    ],
-                ],
-            ],
-            //Dutch elements are shown because of the content fallback 1,0 - first Dutch, then default language
-            //note that '[DK] Without default language' is NOT shown - due to overlays (fetch default language and overlay it with translations)
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = content_fallback;1,0',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = strict',
-                'visibleRecords' => [],
-                'statusCode' => 404
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = ignore',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1',
-                        'image' => ['[T3BOARD] image translated to DE from DK'],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => 'Regular Element #3',
-                        'image' => ['Kasper'],
-                    ],
-                ],
-            ],
-            10 => [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode =',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => 'Regular Element #1',
-                        'image' => ['T3BOARD'],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => 'Regular Element #3',
-                        'image' => ['Kasper'],
-                    ],
-                ],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = content_fallback',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => 'Regular Element #1',
-                        'image' => ['T3BOARD'],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => 'Regular Element #3',
-                        'image' => ['Kasper'],
-                    ],
-                ],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = content_fallback;1,0',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = strict',
-                'visibleRecords' => [],
-                'statusCode' => 404,
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = ignore',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1',
-                        'image' => ['[T3BOARD] image translated to DE from DK'],
-                    ],
-                ],
-            ],
-        ];
-    }
-
-    /**
-     * Page uid 89 is NOT translated to german
-     *
-     * @test
-     * @dataProvider contentOnNonTranslatedPageDataProvider
-     *
-     * @param string $typoScript
-     * @param array $visibleRecords
-     * @param int $statusCode '200' or '404'
-     */
-    public function contentOnNonTranslatedPageGerman(string $typoScript, array $visibleRecords, int $statusCode = 200)
-    {
-        $this->addTypoScriptToTemplateRecord(1, $typoScript);
-        $visibleHeaders = array_column($visibleRecords, 'header');
-
-        $response = $this->executeFrontendRequest(
-            (new InternalRequest())
-                ->withPageId(self::VALUE_PageId)
-                ->withLanguageId(2)
-        );
-
-        if ($statusCode === 200) {
-            $responseSections = ResponseContent::fromString((string)$response->getBody())
-                ->getSections('Extbase:list()');
-            $this->assertThat(
-                $responseSections,
-                $this->getRequestSectionHasRecordConstraint()
-                    ->setTable(self::TABLE_Content)
-                    ->setField('header')
-                    ->setValues(...$visibleHeaders)
-            );
-            $this->assertThat(
-                $responseSections,
-                $this->getRequestSectionDoesNotHaveRecordConstraint()
-                    ->setTable(self::TABLE_Content)
-                    ->setField('header')
-                    ->setValues(...$this->getNonVisibleHeaders($visibleHeaders))
-            );
-
-            foreach ($visibleRecords as $ttContentUid => $properties) {
-                $visibleFileTitles = $properties['image'];
-                if (!empty($visibleFileTitles)) {
-                    $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
-                        ->setRecordIdentifier(self::TABLE_Content . ':' . $ttContentUid)->setRecordField('image')
-                        ->setTable('sys_file_reference')->setField('title')->setValues(...$visibleFileTitles));
-                }
-                $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
-                    ->setRecordIdentifier(self::TABLE_Content . ':' . $ttContentUid)->setRecordField('image')
-                    ->setTable('sys_file_reference')->setField('title')->setValues(...$this->getNonVisibleFileTitles($visibleFileTitles)));
-            }
-        }
-
-        $this->assertEquals($statusCode, $response->getStatusCode());
-    }
-
-    public function contentOnPartiallyTranslatedPageDataProvider(): array
-    {
-
-        //Expected behaviour:
-        //Setting sys_language_mode to different values doesn't influence the result as the requested page is translated to Polish,
-        //Page title is always [PL]Page, and both sys_language_content and sys_language_uid are always 3
-        return [
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode =',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = content_fallback',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = content_fallback;1,0',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = strict',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = ignore',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
-            ],
-            5 => [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode =',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
-            ],
-            // Expected behaviour:
-            // Not translated element #2 is shown because sys_language_overlay = 1 (with sys_language_overlay = hideNonTranslated, it would be hidden)
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = content_fallback',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
-            ],
-            // Expected behaviour:
-            // Element #3 is not translated in PL and it is translated in DK. It's not shown as content_fallback is not related to single CE level
-            // but on page level - and this page is translated to Polish, so no fallback is happening
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = content_fallback;1,0',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = strict',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = ignore',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
-            ],
-            // Expected behaviour:
-            // Non translated default language elements are not shown, because of hideNonTranslated
-            10 => [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode =',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1'],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = content_fallback',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1'],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = content_fallback;1,0',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1'],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = strict',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1'],
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = ignore',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1'],
-            ]
-        ];
-    }
-
-    /**
-     * Page uid 89 is translated to to Polish, but not all CE are translated
-     *
-     * @test
-     * @dataProvider contentOnPartiallyTranslatedPageDataProvider
-     *
-     * @param string $typoScript
-     * @param array $visibleHeaders
-     */
-    public function contentOnPartiallyTranslatedPage(string $typoScript, array $visibleHeaders)
-    {
-        $this->addTypoScriptToTemplateRecord(1, $typoScript);
-
-        $frontendResponse = $this->getFrontendResponse(self::VALUE_PageId, 3);
-        $this->assertEquals('success', $frontendResponse->getStatus());
-        $responseSections = $frontendResponse->getResponseSections('Extbase:list()');
-
-        $this->assertThat(
-            $responseSections,
-            $this->getRequestSectionHasRecordConstraint()
-                ->setTable(self::TABLE_Content)
-                ->setField('header')
-                ->setValues(...$visibleHeaders)
-        );
-        $this->assertThat(
-            $responseSections,
-            $this->getRequestSectionDoesNotHaveRecordConstraint()
-                ->setTable(self::TABLE_Content)
-                ->setField('header')
-                ->setValues(...$this->getNonVisibleHeaders($visibleHeaders))
-        );
-    }
-
-    /**
-     * Helper function to ease asserting that rest of the data set is not visible
-     *
-     * @param array $visibleHeaders
-     * @return array
-     */
-    protected function getNonVisibleHeaders(array $visibleHeaders): array
-    {
-        $allElements = [
-            'Regular Element #1',
-            'Regular Element #2',
-            'Regular Element #3',
-            'Hidden Element #4',
-            '[Translate to Dansk:] Regular Element #1',
-            '[Translate to Dansk:] Regular Element #3',
-            '[DK] Without default language',
-            '[DK] UnHidden Element #4',
-            '[DE] Without default language',
-            '[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1',
-            '[Translate to Polski:] Regular Element #1',
-            '[PL] Without default language',
-            '[PL] Hidden Regular Element #2'
-        ];
-        return array_diff($allElements, $visibleHeaders);
-    }
-
-    /**
-     * Helper function to ease asserting that rest of the data set is not visible
-     *
-     * @param array $visibleTitles
-     * @return array
-     */
-    protected function getNonVisibleFileTitles(array $visibleTitles): array
-    {
-        $allElements = [
-            'T3BOARD',
-            'Kasper',
-            '[Kasper] Image translated to Dansk',
-            '[T3BOARD] Image added in Dansk (without parent)',
-            '[T3BOARD] Image added to DK element without default language',
-            '[T3BOARD] image translated to DE from DK',
-            'Kasper2'
-        ];
-        return array_diff($allElements, $visibleTitles);
-    }
-
-    /**
-     * Helper function to ease asserting that rest of the data set is not visible
-     *
-     * @param array $visibleTitles
-     * @return array
-     */
-    protected function getNonVisibleCategoryTitles(array $visibleTitles): array
-    {
-        $allElements = [
-            'Category 1',
-            '[Translate to Dansk:] Category 1',
-            'Category 3 - not translated',
-            'Category 4',
-        ];
-        return array_diff($allElements, $visibleTitles);
-    }
-}
index d2d2591..499dd4e 100644 (file)
@@ -1,15 +1,10 @@
 config {
     no_cache = 1
     debug = 0
-    xhtml_cleaning = 0
     admPanel = 0
     disableAllHeaderCode = 1
     sendCacheHeaders = 0
-    sys_language_uid = 0
-    sys_language_mode = ignore
-    sys_language_overlay = 1
     absRefPrefix = /
-    linkVars = L
     contentObjectExceptionHandler = 0
     intTarget = _blank
 }
index 0810e6e..574177f 100644 (file)
@@ -5220,7 +5220,6 @@ class ContentObjectRenderer implements LoggerAwareInterface
                 'method' => 'GET',
                 'exclude' => 'id,type,cHash' . ($linkVars ? ',' . $linkVars : '')
             ];
-            $conf['useCacheHash'] = GeneralUtility::_GET('cHash') ? '1' : '0';
         }
 
         return $this->typoLink_URL($conf);
index a3c4029..d4dff40 100644 (file)
@@ -616,20 +616,20 @@ abstract class AbstractMenuContentObject
             } else {
                 $iState = $currentLanguageId === $sUid ? 'ACT' : 'NO';
             }
+            $getVars = '';
             if ($this->conf['addQueryString']) {
                 $getVars = $this->parent_cObj->getQueryArguments(
                     $this->conf['addQueryString.'],
-                    ['L' => $sUid],
+                    [],
                     true
                 );
                 $this->analyzeCacheHashRequirements($getVars);
-            } else {
-                $getVars = '&L=' . $sUid;
             }
             // Adding menu item:
             $menuItems[] = array_merge(
                 array_merge($currentPageWithNoOverlay, $lRecs),
                 [
+                    '_PAGES_OVERLAY_REQUESTEDLANGUAGE' => $sUid,
                     'ITEM_STATE' => $iState,
                     '_ADD_GETVARS' => $getVars,
                     '_SAFE' => true
@@ -1989,7 +1989,7 @@ abstract class AbstractMenuContentObject
         // Ensure that the typolink gets an info which language was actually requested. The $page record could be the record
         // from page translation language=1 as fallback but page translation language=2 was requested. Search for
         // "_PAGES_OVERLAY_REQUESTEDLANGUAGE" for more details
-        if ($page['_PAGES_OVERLAY_REQUESTEDLANGUAGE'] ?? 0) {
+        if (isset($page['_PAGES_OVERLAY_REQUESTEDLANGUAGE'])) {
             $conf['language'] = $page['_PAGES_OVERLAY_REQUESTEDLANGUAGE'];
         }
         if ($this->useCacheHash) {
index 583d8ab..58cc3e3 100644 (file)
@@ -467,8 +467,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface
     public $displayFieldEditIcons = '';
 
     /**
-     * Is set to the iso code of the sys_language_content if that is properly defined
-     * by the sys_language record representing the sys_language_uid.
+     * Is set to the iso code of the current language
      * @var string
      */
     public $sys_language_isocode = '';
@@ -1287,7 +1286,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface
      * If $this->id contains a translated page record, this needs to be resolved to the default language
      * in order for all rootline functionality and access restrictions to be in place further on.
      *
-     * Additionally, if a translated page is found, $this->sys_language_uid/sys_language_content is set as well.
+     * Additionally, if a translated page is found, LanguageAspect is set as well.
      */
     protected function resolveTranslatedPageId()
     {
@@ -1300,11 +1299,6 @@ class TypoScriptFrontendController implements LoggerAwareInterface
         $this->page = $this->sys_page->getPage($this->page[$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']]);
         $this->context->setAspect('language', GeneralUtility::makeInstance(LanguageAspect::class, $languageId));
         $this->id = $this->page['uid'];
-        // For common best-practice reasons, this is set, however, will be optional for new routing mechanisms
-        if (!$this->getCurrentSiteLanguage()) {
-            $_GET['L'] = $languageId;
-            $GLOBALS['HTTP_GET_VARS']['L'] = $languageId;
-        }
     }
 
     /**
@@ -1781,7 +1775,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface
     {
         // Ensure the language base is used for the hash base calculation as well, otherwise TypoScript and page-related rendering
         // is not cached properly as we don't have any language-specific conditions anymore
-        $siteBase = $this->getCurrentSiteLanguage() ? (string)$this->getCurrentSiteLanguage()->getBase() : '';
+        $siteBase = (string)$this->getCurrentSiteLanguage()->getBase();
 
         // Fetch the list of user groups
         /** @var UserAspect $userAspect */
@@ -1924,10 +1918,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface
         }
 
         // Auto-configure settings when a site is configured
-        if ($this->getCurrentSiteLanguage()) {
-            $this->config['config']['absRefPrefix'] = $this->config['config']['absRefPrefix'] ?? 'auto';
-        }
-
+        $this->config['config']['absRefPrefix'] = $this->config['config']['absRefPrefix'] ?? 'auto';
         $this->setUrlIdToken();
 
         // Hook for postProcessing the configuration array
@@ -1959,13 +1950,12 @@ class TypoScriptFrontendController implements LoggerAwareInterface
         Locales::initialize();
 
         $siteLanguage = $this->getCurrentSiteLanguage();
+        if (!$siteLanguage) {
+            throw new PageNotFoundException('Frontend cannot be displayed, as there is no language available', 1557924417);
+        }
 
         // Initialize charset settings etc.
-        if ($siteLanguage) {
-            $languageKey = $siteLanguage->getTypo3Language();
-        } else {
-            $languageKey = $this->config['config']['language'] ?? 'default';
-        }
+        $languageKey = $siteLanguage->getTypo3Language();
         $this->setOutputLanguage($languageKey);
 
         // Rendering charset of HTML page.
@@ -1974,11 +1964,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface
         }
 
         // Get values from site language
-        if ($siteLanguage) {
-            $languageAspect = LanguageAspectFactory::createFromSiteLanguage($siteLanguage);
-        } else {
-            $languageAspect = LanguageAspectFactory::createFromTypoScript($this->config['config'] ?? []);
-        }
+        $languageAspect = LanguageAspectFactory::createFromSiteLanguage($siteLanguage);
 
         $languageId = $languageAspect->getId();
         $languageContentId = $languageAspect->getContentId();
@@ -2088,29 +2074,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface
 
         // Finding the ISO code for the currently selected language
         // fetched by the sys_language record when not fetching content from the default language
-        if ($siteLanguage = $this->getCurrentSiteLanguage()) {
-            $this->sys_language_isocode = $siteLanguage->getTwoLetterIsoCode();
-        } elseif ($languageAspect->getContentId() > 0) {
-            // using sys_language_content because the ISO code only (currently) affect content selection from FlexForms - which should follow "sys_language_content"
-            // Set the fourth parameter to TRUE in the next two getRawRecord() calls to
-            // avoid versioning overlay to be applied as it generates an SQL error
-            $sys_language_row = $this->sys_page->getRawRecord('sys_language', $languageAspect->getContentId(), 'language_isocode,static_lang_isocode');
-            if (is_array($sys_language_row) && !empty($sys_language_row['language_isocode'])) {
-                $this->sys_language_isocode = $sys_language_row['language_isocode'];
-            }
-            // the DB value is overridden by TypoScript
-            if (!empty($this->config['config']['sys_language_isocode'])) {
-                $this->sys_language_isocode = $this->config['config']['sys_language_isocode'];
-            }
-        } else {
-            // fallback to the TypoScript option when rendering with sys_language_uid=0
-            // also: use "en" by default
-            if (!empty($this->config['config']['sys_language_isocode_default'])) {
-                $this->sys_language_isocode = $this->config['config']['sys_language_isocode_default'];
-            } else {
-                $this->sys_language_isocode = $languageKey !== 'default' ? $languageKey : 'en';
-            }
-        }
+        $this->sys_language_isocode = $siteLanguage->getTwoLetterIsoCode();
 
         $_params = [];
         foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['settingLanguage_postProcess'] ?? [] as $_funcRef) {
@@ -2136,12 +2100,8 @@ class TypoScriptFrontendController implements LoggerAwareInterface
      */
     public function settingLocale()
     {
-        // Setting locale
-        $locale = $this->config['config']['locale_all'];
         $siteLanguage = $this->getCurrentSiteLanguage();
-        if ($siteLanguage) {
-            $locale = $siteLanguage->getLocale();
-        }
+        $locale = $siteLanguage->getLocale();
         if ($locale) {
             $availableLocales = GeneralUtility::trimExplode(',', $locale, true);
             // If LC_NUMERIC is set e.g. to 'de_DE' PHP parses float values locale-aware resulting in strings with comma
@@ -3460,7 +3420,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface
      * Sets all internal measures what language the page should be rendered.
      * This is not for records, but rather the HTML / charset and the locallang labels
      *
-     * @param string $language - usually set via TypoScript config.language = dk
+     * @param string $language - usually set via Site Handling
      */
     protected function setOutputLanguage($language = 'default')
     {
index 9507d34..6315a9a 100644 (file)
@@ -23,15 +23,10 @@ use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\Context\Context;
 use TYPO3\CMS\Core\Context\UserAspect;
 use TYPO3\CMS\Core\Context\WorkspaceAspect;
-use TYPO3\CMS\Core\Database\ConnectionPool;
-use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
-use TYPO3\CMS\Core\Database\Query\Restriction\FrontendWorkspaceRestriction;
 use TYPO3\CMS\Core\Routing\PageArguments;
 use TYPO3\CMS\Core\Routing\RouteNotFoundException;
 use TYPO3\CMS\Core\Routing\SiteRouteResult;
 use TYPO3\CMS\Core\Site\Entity\Site;
-use TYPO3\CMS\Core\Site\Entity\SiteInterface;
-use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
 use TYPO3\CMS\Core\Type\Bitmask\Permission;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Frontend\Controller\ErrorController;
@@ -39,11 +34,13 @@ use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
 use TYPO3\CMS\Frontend\Page\PageAccessFailureReasons;
 
 /**
- * Process the ID, type and other parameters.
+ * Resolve the page ID based on TYPO3's routing functionality configured in a site.
+ *
+ * Processes the page ID, page type (typeNum) and other parameters built from queryArguments and routeParameters.
  * After this point we have an array, TSFE->page, which is the page-record of the current page, $TSFE->id.
  *
- * Now, if there is a backend user logged in and he has NO access to this page,
- * then re-evaluate the id shown!
+ * However, if there is a backend user logged in and he has NO access to this page (and the page is hidden),
+ * then the ID is determined again and the backend user is not considered for the rest of the frontend request.
  */
 class PageResolver implements MiddlewareInterface
 {
@@ -66,88 +63,72 @@ class PageResolver implements MiddlewareInterface
      */
     public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
     {
+        $site = $request->getAttribute('site', null);
+
+        if (!$site instanceof Site) {
+            return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
+                $request,
+                'No site configuration found.',
+                ['code' => PageAccessFailureReasons::PAGE_NOT_FOUND]
+            );
+        }
+
         // First, resolve the root page of the site, the Page ID of the current domain
-        if (($site = $request->getAttribute('site', null)) instanceof SiteInterface) {
-            $this->controller->domainStartPage = $site->getRootPageId();
+        $this->controller->domainStartPage = $site->getRootPageId();
+
+        /** @var SiteRouteResult $previousResult */
+        $previousResult = $request->getAttribute('routing', null);
+        if (!$previousResult) {
+            return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
+                $request,
+                'The requested page does not exist',
+                ['code' => PageAccessFailureReasons::PAGE_NOT_FOUND]
+            );
+        }
+
+        // Check for the route arguments or Query Parameter ID
+        try {
+            /** @var PageArguments $pageArguments */
+            $pageArguments = $site->getRouter()->matchRequest($request, $previousResult);
+        } catch (RouteNotFoundException $e) {
+            return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
+                $request,
+                'The requested page does not exist',
+                ['code' => PageAccessFailureReasons::PAGE_NOT_FOUND]
+            );
+        }
+
+        if (!$pageArguments->getPageId()) {
+            return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
+                $request,
+                'The requested page does not exist',
+                ['code' => PageAccessFailureReasons::PAGE_NOT_FOUND]
+            );
         }
-        $language = $request->getAttribute('language', null);
-
-        $hasSiteConfiguration = $language instanceof SiteLanguage && $site instanceof Site;
-
-        // Resolve the page ID based on TYPO3's native routing functionality
-        if ($hasSiteConfiguration) {
-            /** @var SiteRouteResult $previousResult */
-            $previousResult = $request->getAttribute('routing', null);
-            if (!$previousResult) {
-                return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
-                    $request,
-                    'The requested page does not exist',
-                    ['code' => PageAccessFailureReasons::PAGE_NOT_FOUND]
-                );
-            }
-
-            $requestId = (string)($request->getQueryParams()['id'] ?? '');
-            if (!empty($requestId)) {
-                // Legacy URIs (?id=12345) takes precedence, not matter if a route is given
-                if (!empty($page = $this->resolvePageId($requestId))) {
-                    $pageArguments = new PageArguments(
-                        (int)($page['l10n_parent'] ?: $page['uid']),
-                        (string)($request->getQueryParams()['type'] ?? '0'),
-                        [],
-                        [],
-                        $request->getQueryParams()
-                    );
-                } else {
-                    return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
-                        $request,
-                        'The requested page does not exist',
-                        ['code' => PageAccessFailureReasons::PAGE_NOT_FOUND]
-                    );
-                }
-            } else {
-                // Check for the route
-                try {
-                    $pageArguments = $site->getRouter()->matchRequest($request, $previousResult);
-                } catch (RouteNotFoundException $e) {
-                    return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
-                        $request,
-                        'The requested page does not exist',
-                        ['code' => PageAccessFailureReasons::PAGE_NOT_FOUND]
-                    );
-                }
-            }
-            if (!$pageArguments->getPageId()) {
-                return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
-                    $request,
-                    'The requested page does not exist',
-                    ['code' => PageAccessFailureReasons::PAGE_NOT_FOUND]
-                );
-            }
-
-            $this->controller->id = $pageArguments->getPageId();
-            $this->controller->type = $pageArguments->getPageType() ?? $this->controller->type;
-            $request = $request->withAttribute('routing', $pageArguments);
-            // stop in case arguments are dirty (=defined twice in route and GET query parameters)
-            if ($pageArguments->areDirty()) {
-                return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
-                    $request,
-                    'The requested URL is not distinct',
-                    ['code' => PageAccessFailureReasons::PAGE_NOT_FOUND]
-                );
-            }
-
-            // merge the PageArguments with the request query parameters
-            $queryParams = array_replace_recursive($request->getQueryParams(), $pageArguments->getArguments());
-            $request = $request->withQueryParams($queryParams);
-            $this->controller->setPageArguments($pageArguments);
+
+        $this->controller->id = $pageArguments->getPageId();
+        $this->controller->type = $pageArguments->getPageType() ?? $this->controller->type;
+        $request = $request->withAttribute('routing', $pageArguments);
+        // stop in case arguments are dirty (=defined twice in route and GET query parameters)
+        if ($pageArguments->areDirty()) {
+            return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
+                $request,
+                'The requested URL is not distinct',
+                ['code' => PageAccessFailureReasons::PAGE_NOT_FOUND]
+            );
         }
 
-        // as long as TSFE throws errors with the global object, this needs to be set, but
-        // should be removed later-on
+        // merge the PageArguments with the request query parameters
+        $queryParams = array_replace_recursive($request->getQueryParams(), $pageArguments->getArguments());
+        $request = $request->withQueryParams($queryParams);
+        $this->controller->setPageArguments($pageArguments);
+
+        // as long as TSFE throws errors with the global object, this needs to be set,
+        // but should be removed later-on
         $GLOBALS['TYPO3_REQUEST'] = $request;
         $this->controller->determineId();
 
-        // No access? Then remove user & Re-evaluate the page-id
+        // No access? Then remove user and re-evaluate the page id
         if ($this->controller->isBackendUserLoggedIn() && !$GLOBALS['BE_USER']->doesUserHaveAccess($this->controller->page, Permission::PAGE_SHOW)) {
             unset($GLOBALS['BE_USER']);
             // Register an empty backend user as aspect
@@ -159,38 +140,6 @@ class PageResolver implements MiddlewareInterface
     }
 
     /**
-     * @param string $pageId
-     * @return array|null
-     */
-    protected function resolvePageId(string $pageId): ?array
-    {
-        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
-            ->getQueryBuilderForTable('pages');
-        $queryBuilder
-            ->getRestrictions()
-            ->removeAll()
-            ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
-            ->add(GeneralUtility::makeInstance(FrontendWorkspaceRestriction::class));
-
-        $statement = $queryBuilder
-            ->select('uid', 'l10n_parent', 'pid')
-            ->from('pages')
-            ->where(
-                $queryBuilder->expr()->eq(
-                    'uid',
-                    $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT)
-                )
-            )
-            ->execute();
-
-        $page = $statement->fetch();
-        if (empty($page)) {
-            return null;
-        }
-        return $page;
-    }
-
-    /**
      * Register the backend user as aspect
      *
      * @param Context $context
index a009c0f..76ee01c 100644 (file)
@@ -33,11 +33,9 @@ use TYPO3\CMS\Core\Site\Entity\SiteInterface;
 use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
 use TYPO3\CMS\Core\Site\SiteFinder;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Core\Utility\HttpUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
 use TYPO3\CMS\Core\Utility\RootlineUtility;
 use TYPO3\CMS\Frontend\ContentObject\TypolinkModifyLinkConfigForPageLinksHookInterface;
-use TYPO3\CMS\Frontend\Page\CacheHashCalculator;
 use TYPO3\CMS\Frontend\Page\PageRepository;
 
 /**
@@ -79,7 +77,6 @@ class PageLinkBuilder extends AbstractTypolinkBuilder
             /** @var TypolinkModifyLinkConfigForPageLinksHookInterface $hookObject */
             $conf = $hookObject->modifyPageLinkConfiguration($conf, $linkDetails, $page);
         }
-        $enableLinksAcrossDomains = $tsfe->config['config']['typolinkEnableLinksAcrossDomains'];
         if ($conf['no_cache.']) {
             $conf['no_cache'] = (string)$this->contentObjectRenderer->stdWrap($conf['no_cache'], $conf['no_cache.']);
         }
@@ -129,10 +126,7 @@ class PageLinkBuilder extends AbstractTypolinkBuilder
             // menu. Mount points always work in the content of the current domain and we must not change
             // domain if MP variables exist.
             // If we link across domains and page is free type shortcut, we must resolve the shortcut first!
-            // If we do not do it, TYPO3 will fail to (1) link proper page in RealURL/CoolURI because
-            // they return relative links and (2) show proper page if no RealURL/CoolURI exists when link is clicked
-            if ($enableLinksAcrossDomains
-                && (int)$page['doktype'] === PageRepository::DOKTYPE_SHORTCUT
+            if ((int)$page['doktype'] === PageRepository::DOKTYPE_SHORTCUT
                 && (int)$page['shortcut_mode'] === PageRepository::SHORTCUT_MODE_NONE
             ) {
                 // Save in case of broken destination or endless loop
@@ -153,13 +147,9 @@ class PageLinkBuilder extends AbstractTypolinkBuilder
                 }
             }
         }
+
         if ($conf['useCacheHash']) {
-            $params = $tsfe->linkVars . $addQueryParams . '&id=' . $page['uid'];
-            if (trim($params, '& ') !== '') {
-                $cHash = GeneralUtility::makeInstance(CacheHashCalculator::class)->generateForParameters($params);
-                $addQueryParams .= $cHash ? '&cHash=' . $cHash : '';
-            }
-            unset($params);
+            trigger_error('Setting typolink.useCacheHash has no effect anymore. Remove the option in all your TypoScript code and Fluid templates.', E_USER_DEPRECATED);
         }
 
         // get config.linkVars and prepend them before the actual GET parameters
@@ -176,6 +166,7 @@ class PageLinkBuilder extends AbstractTypolinkBuilder
         // Override language property if not being set already
         if (isset($queryParameters['L']) && !isset($conf['language'])) {
             $conf['language'] = (int)$queryParameters['L'];
+            unset($queryParameters['L']);
         }
 
         // Check if the target page has a site configuration
@@ -212,8 +203,6 @@ class PageLinkBuilder extends AbstractTypolinkBuilder
                 }
             }
 
-            // No need for any L parameter with Site handling
-            unset($queryParameters['L']);
             if ($pageType) {
                 $queryParameters['type'] = (int)$pageType;
             }
@@ -242,24 +231,7 @@ class PageLinkBuilder extends AbstractTypolinkBuilder
                 }
             }
         } else {
-            // Now overlay the page in the target language, in order to have valid title attributes etc.
-            if (isset($conf['language']) && $conf['language'] > 0 && $conf['language'] !== 'current') {
-                $page = $tsfe->sys_page->getPageOverlay($page, (int)$conf['language']);
-            }
-            $languageField = $GLOBALS['TCA']['pages']['ctrl']['languageField'] ?? null;
-            $languageOfPageRecord = (int)($page[$languageField] ?? 0);
-            if ($languageOfPageRecord === 0 && GeneralUtility::hideIfDefaultLanguage($page['l18n_cfg'])) {
-                throw new UnableToLinkException('Default language of page  "' . $linkDetails['typoLinkParameter'] . '" is hidden, so "' . $linkText . '" was not linked.', 1529527301, null, $linkText);
-            }
-            if ($languageOfPageRecord > 0 && !isset($page['_PAGES_OVERLAY']) && GeneralUtility::hideIfNotTranslated($page['l18n_cfg'])) {
-                throw new UnableToLinkException('Fallback to default language of page "' . $linkDetails['typoLinkParameter'] . '" is disabled, so "' . $linkText . '" was not linked.', 1529527488, null, $linkText);
-            }
-
-            // If the typolink.language parameter was set, ensure that this is added to L query parameter
-            if (!isset($queryParameters['L']) && MathUtility::canBeInterpretedAsInteger($conf['language'] ?? false)) {
-                $queryParameters['L'] = $conf['language'];
-            }
-            list($url, $target) = $this->generateUrlForPageWithoutSiteConfiguration($page, $queryParameters, $conf, $pageType, $sectionMark, $target, $MPvarAcc);
+            throw new UnableToLinkException('Could not link to page with ID: ' . $page['uid'], 1546887172, null, $linkText);
         }
 
         // If link is to an access restricted page which should be redirected, then find new URL:
@@ -331,7 +303,6 @@ class PageLinkBuilder extends AbstractTypolinkBuilder
         // Set the "pageuid" to the default-language page ID.
         $linkDetails['pageuid'] = (int)$languageParentPage['uid'];
         $configuration['language'] = $language;
-        $linkDetails['parameters'] .= '&L=' . $language;
         return $languageParentPage;
     }
 
@@ -427,110 +398,6 @@ class PageLinkBuilder extends AbstractTypolinkBuilder
     }
 
     /**
-     * Generate a URL for a page without site configuration
-     *
-     * @param array $page
-     * @param array $additionalQueryParams
-     * @param array $conf
-     * @param string $pageType
-     * @param string $sectionMark
-     * @param string $target
-     * @param array $MPvarAcc
-     * @return array
-     */
-    protected function generateUrlForPageWithoutSiteConfiguration(array $page, array $additionalQueryParams, array $conf, string $pageType, string $sectionMark, string $target, array $MPvarAcc): array
-    {
-        // Build a string out of the query parameters
-        $additionalQueryParams = http_build_query($additionalQueryParams, '', '&', PHP_QUERY_RFC3986);
-        if (!empty($additionalQueryParams)) {
-            $additionalQueryParams = '&' . $additionalQueryParams;
-        }
-
-        $tsfe = $this->getTypoScriptFrontendController();
-        $enableLinksAcrossDomains = $tsfe->config['config']['typolinkEnableLinksAcrossDomains'];
-        $targetDomain = '';
-        $currentDomain = (string)GeneralUtility::getIndpEnv('HTTP_HOST');
-        $absoluteUrlScheme = GeneralUtility::getIndpEnv('TYPO3_SSL') ? 'https' : 'http';
-        // URL shall be absolute:
-        if (isset($conf['forceAbsoluteUrl']) && $conf['forceAbsoluteUrl']) {
-            // Override scheme:
-            if (isset($conf['forceAbsoluteUrl.']['scheme']) && $conf['forceAbsoluteUrl.']['scheme']) {
-                $absoluteUrlScheme = $conf['forceAbsoluteUrl.']['scheme'];
-            }
-            // If no domain records are defined, use current domain
-            $targetDomain = $targetDomain ?: $currentDomain;
-            // If go for an absolute link, add site path if it's not taken care about by absRefPrefix
-            if (!$tsfe->absRefPrefix && $targetDomain === $currentDomain) {
-                $targetDomain = $currentDomain . rtrim(GeneralUtility::getIndpEnv('TYPO3_SITE_PATH'), '/');
-            }
-        }
-        // If target page has a different domain and the current domain's linking scheme (e.g. RealURL/...) should not be used
-        if ($targetDomain !== '' && $targetDomain !== $currentDomain && !$enableLinksAcrossDomains) {
-            $target = $target ?: $this->resolveTargetAttribute($conf, 'extTarget', false, $tsfe->extTarget);
-            // Convert IDNA-like domain (if any)
-            if (!preg_match('/^[a-z0-9.\\-]*$/i', $targetDomain)) {
-                $targetDomain = HttpUtility::idn_to_ascii($targetDomain);
-            }
-            $url = $absoluteUrlScheme . '://' . $targetDomain . '/index.php?id=' . $page['uid'] . $additionalQueryParams;
-        } else {
-            // Internal link or current domain's linking scheme should be used
-            // Internal target:
-            $target = (isset($page['target']) && trim($page['target'])) ? $page['target'] : $target;
-            if (empty($target)) {
-                $target = $this->resolveTargetAttribute($conf, 'target', true, $tsfe->intTarget);
-            }
-            $LD = $this->createTotalUrlAndLinkData($page, $target, $conf['no_cache'], $additionalQueryParams, $pageType, $targetDomain);
-            if ($targetDomain !== '') {
-                // We will add domain only if URL does not have it already.
-                if ($enableLinksAcrossDomains && $targetDomain !== $currentDomain && !empty($tsfe->absRefPrefix)) {
-                    // Get rid of the absRefPrefix if necessary. absRefPrefix is applicable only
-                    // to the current web site. If we have domain here it means we link across
-                    // domains. absRefPrefix can contain domain name, which will screw up
-                    // the link to the external domain.
-                    $prefixLength = strlen($tsfe->absRefPrefix);
-                    if (strpos($LD['totalURL'], $tsfe->absRefPrefix) === 0) {
-                        $LD['totalURL'] = substr($LD['totalURL'], $prefixLength);
-                    }
-                }
-                $urlParts = parse_url($LD['totalURL']);
-                if (empty($urlParts['host'])) {
-                    $LD['totalURL'] = $absoluteUrlScheme . '://' . $targetDomain . ($LD['totalURL'][0] === '/' ? '' : '/') . $LD['totalURL'];
-                }
-            }
-            $url = $LD['totalURL'];
-        }
-        $url .= $sectionMark;
-        // If sectionMark is set, there is no baseURL AND the current page is the page the link is to,
-        // check if there are any additional parameters or addQueryString parameters and if not, drop the url.
-        if ($sectionMark
-            && !$tsfe->config['config']['baseURL']
-            && (int)$page['uid'] === (int)$tsfe->id
-            && !trim($additionalQueryParams)
-            && (empty($conf['addQueryString']) || !isset($conf['addQueryString.']))
-        ) {
-            $currentQueryArray = [];
-            parse_str(GeneralUtility::getIndpEnv('QUERY_STRING'), $currentQueryArray);
-
-            if (empty($currentQueryArray)) {
-                list(, $URLparams) = explode('?', $url);
-                list($URLparams) = explode('#', (string)$URLparams);
-                parse_str($URLparams . $LD['orig_type'], $URLparamsArray);
-                // Type nums must match as well as page ids
-                if ((int)$URLparamsArray['type'] === (int)$tsfe->type) {
-                    unset($URLparamsArray['id']);
-                    unset($URLparamsArray['type']);
-                    // If there are no parameters left.... set the new url.
-                    if (empty($URLparamsArray)) {
-                        $url = $sectionMark;
-                    }
-                }
-            }
-        }
-        return [$url, $target];
-    }
-
-    /**
-     * Returns the &MP variable value for a page id.
      * The function will do its best to find a MP value that will keep the page id inside the current Mount Point rootline if any.
      *
      * @param int $pageId page id
@@ -737,76 +604,6 @@ class PageLinkBuilder extends AbstractTypolinkBuilder
     }
 
     /**
-     * The mother of all functions creating links/URLs etc in a TypoScript environment.
-     * See the references below.
-     * Basically this function takes care of issues such as type,id and Mount Points, URL rewriting (through hooks), M5/B6 encoded parameters etc.
-     * It is important to pass all links created through this function since this is the guarantee that globally configured settings for link creating are observed and that your applications will conform to the various/many configuration options in TypoScript Templates regarding this.
-     *
-     * @param array $page The page record of the page to which we are creating a link. Needed due to fields like uid, target, title and sectionIndex_uid.
-     * @param string $target Target string
-     * @param bool $no_cache If set, then the "&no_cache=1" parameter is included in the URL.
-     * @param string $addParams Additional URL parameters to set in the URL. Syntax is "&foo=bar&foo2=bar2" etc. Also used internally to add parameters if needed.
-     * @param string $typeOverride If you set this value to something else than a blank string, then the typeNumber used in the link will be forced to this value. Normally the typeNum is based on the target set OR on $this->getTypoScriptFrontendController()->config['config']['forceTypeValue'] if found.
-     * @param string $targetDomain The target Doamin, if any was detected in typolink
-     * @return array Contains keys like "totalURL", "url", "sectionIndex", "linkVars", "no_cache", "type" of which "totalURL" is normally the value you would use while the other keys contains various parts that was used to construct "totalURL
-     */
-    protected function createTotalUrlAndLinkData($page, $target, $no_cache, $addParams = '', $typeOverride = '', $targetDomain = '')
-    {
-        $LD = [];
-        // Adding Mount Points, "&MP=", parameter for the current page if any is set
-        // but non other set explicitly
-        if (strpos($addParams, '&MP=') === false) {
-            $mountPointParameter = $this->getMountPointParameterFromRootPointMaps((int)$page['uid']);
-            if ($mountPointParameter) {
-                $addParams .= '&MP=' . rawurlencode($mountPointParameter);
-            }
-        }
-        // Setting ID/alias:
-        $script = 'index.php';
-        $LD['url'] = $script . '?id=' . $page['uid'];
-        // typeNum
-        $typeNum = $this->getTypoScriptFrontendController()->tmpl->setup[$target . '.']['typeNum'];
-        if (!MathUtility::canBeInterpretedAsInteger($typeOverride) && (int)$this->getTypoScriptFrontendController()->config['config']['forceTypeValue']) {
-            $typeOverride = (int)$this->getTypoScriptFrontendController()->config['config']['forceTypeValue'];
-        }
-        if ((string)$typeOverride !== '') {
-            $typeNum = $typeOverride;
-        }
-        // Override...
-        if ($typeNum) {
-            $LD['type'] = '&type=' . (int)$typeNum;
-        } else {
-            $LD['type'] = '';
-        }
-        // Preserving the type number.
-        $LD['orig_type'] = $LD['type'];
-        // noCache
-        $LD['no_cache'] = $no_cache ? '&no_cache=1' : '';
-        // linkVars
-        if ($addParams) {
-            $LD['linkVars'] = HttpUtility::buildQueryString(GeneralUtility::explodeUrl2Array($this->getTypoScriptFrontendController()->linkVars . $addParams), '&');
-        } else {
-            $LD['linkVars'] = $this->getTypoScriptFrontendController()->linkVars;
-        }
-        // Add absRefPrefix if exists.
-        $LD['url'] = $this->getTypoScriptFrontendController()->absRefPrefix . $LD['url'];
-        // If the special key 'sectionIndex_uid' (added 'manually' in tslib/menu.php to the page-record) is set, then the link jumps directly to a section on the page.
-        $LD['sectionIndex'] = $page['sectionIndex_uid'] ? '#c' . $page['sectionIndex_uid'] : '';
-        // Compile the normal total url
-        $LD['totalURL'] = rtrim($LD['url'] . $LD['type'] . $LD['no_cache'] . $LD['linkVars'] . $this->getTypoScriptFrontendController()->getMethodUrlIdToken, '?') . $LD['sectionIndex'];
-        // Call post processing function for link rendering:
-        $_params = [
-            'LD' => &$LD,
-            'args' => ['page' => $page, 'oTarget' => $target, 'no_cache' => $no_cache, 'script' => $script, 'addParams' => $addParams, 'typeOverride' => $typeOverride, 'targetDomain' => $targetDomain],
-            'typeNum' => $typeNum
-        ];
-        foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tstemplate.php']['linkData-PostProc'] ?? [] as $_funcRef) {
-            GeneralUtility::callUserFunction($_funcRef, $_params, $this->getTypoScriptFrontendController()->tmpl);
-        }
-        return $LD;
-    }
-
-    /**
      * Check if we have a site object in the current request. if null, this usually means that
      * this class was called from CLI context.
      *
index f4935c4..e59e4fd 100644 (file)
@@ -20,11 +20,6 @@ page {
     externalJS.excludeFromConcatenation = 1
     externalJS.disableCompression = 1
   }
-
-  10 = TEXT
-  10 {
-    typolink.parameter = {$localLink}
-  }
   20 = IMAGE
   20 {
     file = {$localImage}
diff --git a/typo3/sysext/frontend/Tests/Functional/Rendering/LocalizedContentRenderingTest.php b/typo3/sysext/frontend/Tests/Functional/Rendering/LocalizedContentRenderingTest.php
deleted file mode 100644 (file)
index d2aadcd..0000000
+++ /dev/null
@@ -1,1236 +0,0 @@
-<?php
-declare(strict_types = 1);
-
-namespace TYPO3\CMS\Frontend\Tests\Functional\Rendering;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
-use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\ResponseContent;
-
-/**
- * Test case checking if localized tt_content is rendered correctly with different language settings
- *
- * The following values are relevant:
- *
- * -- TypoScript --
- * config.sys_language_uid = [0,1,2,3,4...] (set via the language parameter &L=1 from the FrontendRequest in the tests)
- *      Fetch the page overlay of the current page if the value is > 0 and if not available, then
- *      "config.sys_language_mode" is evaluated.
- *      If this setting is set to "0" or empty, then no page overlay is evaluated, and no further parameters are
- *      relevant or evaluated.
- *
- * config.sys_language_mode = [strict, content_fallback;2,3, ignore]
- *      Only evaluated when sys_language_uid > 0, and the requested page translation is NOT available.
- *      Decides if "pageNotFound" (strict), "content_fallback" with a fallback chain ($TSFE->sys_language_content is set
- *      to that value) or "ignore" (just render the page and the content as this translation would exist).
- *      When set to "0" or not set "", this means that the page request is using the default language for content
- *      and page properties.
- *      Content fallback is evaluated on page level, not on the CE level. So it only makes a difference when the page translation
- *      for the requested language does not exist.
- *
- * config.sys_language_overlay = [0, 1, hideNonTranslated]
- *      Only relevant if $TSFE->sys_language_content is > 0.
- *      Sets the property $TSFE->sys_language_contentOL at a request. Further calls via $TSFE->sys_page->getRecordOverlay
- *      receive this value to see if an overlay should happen.
- *      0:
- *          Just fetch records from selected ($TSFE->sys_language_content) language, no overlay will happen,
- *          no fetching of the records from the default language. This boils down to "free mode" language handling.
- *
- *      1:
- *          Fetch records from the default language and overlay them with translations. If some record is not translated
- *          default language version will be shown.
- *
- *      hideNotTranslated:
- *          Fetch records from the default language and overlay them with translations. If some record is not translated
- *          it will not be shown.
- *
- * -- Frontend / TypoScriptFrontendController --
- *
- * $TSFE->sys_language_uid
- *      Defines in which language the current page was requested, this is relevant when building menus or links to other
- *      pages.
- * $TSFE->sys_language_content
- *      Contains the language UID of the content records that should be overlaid to would be fetched.
- *      This is especially useful when a page requested with language=4 should fall back to showing content of language=2 (see config.sys_language_mode=content_fallback)
- * $TSFE->sys_language_contentOL
- *      Contains the info if and how record overlays (when fetching content) should be handled, either "0" (no overlays done)
- *      or "1" (do overlays with possible mixed content, or "hideNonTranslated". see "config.sys_language_overlay"
- *      This is used in conjunction with $TSFE->sys_language_content.
- * $TSFE->sys_language_mode
- *      Contains the config.sys_language_mode parameter, which is either "", "strict", "content_fallback" or "ignore"
- *      Only used within $TSFE->settingLanguage() and in Extbase.
- */
-class LocalizedContentRenderingTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\AbstractDataHandlerActionTestCase
-{
-    const VALUE_PageId = 89;
-    const TABLE_Content = 'tt_content';
-    const TABLE_Pages = 'pages';
-
-    /**
-     * @var string
-     */
-    protected $scenarioDataSetDirectory = 'typo3/sysext/frontend/Tests/Functional/Rendering/DataSet/';
-
-    /**
-     * Custom 404 handler returning valid json is registered so the $this->getFrontendResponse()
-     * does not fail on 404 pages
-     *
-     * @var array
-     */
-    protected $configurationToUseInTestInstance = [
-        'FE' => [
-            'pageNotFound_handling' => 'READFILE:typo3/sysext/frontend/Tests/Functional/Rendering/DataSet/404Template.html'
-        ]
-    ];
-
-    /**
-     * @var array
-     */
-    protected $pathsToLinkInTestInstance = [
-        'typo3/sysext/core/Tests/Functional/Fixtures/Frontend/AdditionalConfiguration.php' => 'typo3conf/AdditionalConfiguration.php',
-        'typo3/sysext/frontend/Tests/Functional/Fixtures/Images' => 'fileadmin/user_upload'
-    ];
-
-    protected function setUp(): void
-    {
-        parent::setUp();
-        $this->importDataSet('PACKAGE:typo3/testing-framework/Resources/Core/Functional/Fixtures/sys_file_storage.xml');
-        $this->importScenarioDataSet('LiveDefaultPages');
-        $this->importScenarioDataSet('LiveDefaultElements');
-        $this->setUpFrontendRootPage(1, [
-            'typo3/sysext/core/Tests/Functional/Fixtures/Frontend/JsonRenderer.typoscript',
-        ]);
-    }
-
-    public function defaultLanguageConfigurationDataProvider(): array
-    {
-        return [
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode =',
-                'sys_language_mode' => '',
-                'sys_language_contentOL' => '0'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = content_fallback',
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => '0'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = content_fallback;1,0',
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => '0'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = strict',
-                'sys_language_mode' => 'strict',
-                'sys_language_contentOL' => '0'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = ignore',
-                'sys_language_mode' => 'ignore',
-                'sys_language_contentOL' => '0'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode =',
-                'sys_language_mode' => '',
-                'sys_language_contentOL' => '1'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = content_fallback',
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => '1'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = content_fallback;1,0',
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => '1'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = strict',
-                'sys_language_mode' => 'strict',
-                'sys_language_contentOL' => '1'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = ignore',
-                'sys_language_mode' => 'ignore',
-                'sys_language_contentOL' => '1'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode =',
-                'sys_language_mode' => '',
-                'sys_language_contentOL' => 'hideNonTranslated'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = content_fallback',
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => 'hideNonTranslated'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = content_fallback;1,0',
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => 'hideNonTranslated'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = strict',
-                'sys_language_mode' => 'strict',
-                'sys_language_contentOL' => 'hideNonTranslated'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = ignore',
-                'sys_language_mode' => 'ignore',
-                'sys_language_contentOL' => 'hideNonTranslated'
-            ],
-        ];
-    }
-
-    /**
-     * For the default language all combination of language settings should give the same result,
-     * regardless of TypoScript settings, if the requested language is "0" then no TypoScript settings apply.
-     *
-     * @test
-     * @dataProvider defaultLanguageConfigurationDataProvider
-     *
-     * @param string $typoScript
-     * @param string $sysLanguageMode
-     * @param string $sysLanguageContentOL
-     */
-    public function onlyEnglishContentIsRenderedForDefaultLanguage(string $typoScript, string $sysLanguageMode, string $sysLanguageContentOL)
-    {
-        $this->addTypoScriptToTemplateRecord(1, $typoScript);
-
-        $frontendResponse = $this->getFrontendResponse(self::VALUE_PageId, 0);
-        $responseSections = $frontendResponse->getResponseSections();
-        $visibleHeaders = ['Regular Element #1', 'Regular Element #2', 'Regular Element #3'];
-        $this->assertThat(
-            $responseSections,
-            $this->getRequestSectionHasRecordConstraint()
-            ->setTable(self::TABLE_Content)
-            ->setField('header')
-            ->setValues(...$visibleHeaders)
-        );
-        $this->assertThat(
-            $responseSections,
-            $this->getRequestSectionDoesNotHaveRecordConstraint()
-            ->setTable(self::TABLE_Content)
-            ->setField('header')
-            ->setValues(...$this->getNonVisibleHeaders($visibleHeaders))
-        );
-
-        //assert FAL relations
-        $visibleFiles = ['T3BOARD'];
-        $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
-            ->setRecordIdentifier(self::TABLE_Content . ':297')->setRecordField('image')
-            ->setTable('sys_file_reference')->setField('title')->setValues(...$visibleFiles));
-
-        $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
-            ->setRecordIdentifier(self::TABLE_Content . ':297')->setRecordField('image')
-            ->setTable('sys_file_reference')->setField('title')->setValues(...$this->getNonVisibleFileTitles($visibleFiles)));
-
-        $visibleFiles = ['Kasper2'];
-        $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
-            ->setRecordIdentifier(self::TABLE_Content . ':298')->setRecordField('image')
-            ->setTable('sys_file_reference')->setField('title')->setValues(...$visibleFiles));
-
-        $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
-            ->setRecordIdentifier(self::TABLE_Content . ':298')->setRecordField('image')
-            ->setTable('sys_file_reference')->setField('title')->setValues(...$this->getNonVisibleFileTitles($visibleFiles)));
-
-        //Assert TSFE and page record title
-        $content = json_decode($frontendResponse->getContent());
-        $this->assertEquals('Default language Page', $content->Scope->page->title);
-        $this->assertEquals(0, $content->Scope->tsfe->sys_language_uid, 'sys_language_uid doesn\'t match');
-        $this->assertEquals(0, $content->Scope->tsfe->sys_language_content, 'sys_language_content doesn\'t match');
-        $this->assertEquals($sysLanguageMode, $content->Scope->tsfe->sys_language_mode, 'sys_language_mode doesn\t match');
-        $this->assertEquals($sysLanguageContentOL, $content->Scope->tsfe->sys_language_contentOL, 'sys_language_contentOL doesn\t match');
-    }
-
-    /**
-     * Dutch language has page translation record and some content elements are translated
-     *
-     * @return array
-     */
-    public function dutchDataProvider(): array
-    {
-        //Expected behaviour:
-        //Page is translated to Dutch, so changing sys_language_mode does NOT change the results
-        //Page title is always [DK]Page, and both sys_language_content and sys_language_uid are always 1
-        return [
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode =',
-                'visibleRecords' => [
-                    300 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                    301 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                    ],
-                    303 => [
-                        'header' => '[DK] Without default language',
-                        'image' => ['[T3BOARD] Image added to DK element without default language']
-                    ],
-                    308 => [
-                        'header' => '[DK] UnHidden Element #4',
-                        'image' => []
-                    ],
-                ],
-                'sys_language_mode' => '',
-                'sys_language_contentOL' => '0'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = content_fallback',
-                'visibleRecords' => [
-                    300 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                    301 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                    ],
-                    303 => [
-                        'header' => '[DK] Without default language',
-                        'image' => ['[T3BOARD] Image added to DK element without default language']
-                    ],
-                    308 => [
-                        'header' => '[DK] UnHidden Element #4',
-                        'image' => []
-                    ],
-                ],
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => '0'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = content_fallback;1,0',
-                'visibleRecords' => [
-                    300 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                    301 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                    ],
-                    303 => [
-                        'header' => '[DK] Without default language',
-                        'image' => ['[T3BOARD] Image added to DK element without default language']
-                    ],
-                    308 => [
-                        'header' => '[DK] UnHidden Element #4',
-                        'image' => []
-                    ],
-                ],
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => '0'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = strict',
-                'visibleRecords' => [
-                    300 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                    301 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                    ],
-                    303 => [
-                        'header' => '[DK] Without default language',
-                        'image' => ['[T3BOARD] Image added to DK element without default language']
-                    ],
-                    308 => [
-                        'header' => '[DK] UnHidden Element #4',
-                        'image' => []
-                    ],
-                ],
-                'sys_language_mode' => 'strict',
-                'sys_language_contentOL' => '0'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = ignore',
-                'visibleRecords' => [
-                    300 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                    301 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                    ],
-                    303 => [
-                        'header' => '[DK] Without default language',
-                        'image' => ['[T3BOARD] Image added to DK element without default language']
-                    ],
-                    308 => [
-                        'header' => '[DK] UnHidden Element #4',
-                        'image' => []
-                    ],
-                ],
-                'sys_language_mode' => 'ignore',
-                'sys_language_contentOL' => '0'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode =',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-                'sys_language_mode' => '',
-                'sys_language_contentOL' => '1'
-            ],
-            // Expected behaviour:
-            // Not translated element #2 is shown because sys_language_overlay = 1 (with sys_language_overlay = hideNonTranslated, it would be hidden)
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = content_fallback',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => '1'
-            ],
-            // Expected behaviour:
-            // Same as config.sys_language_mode = content_fallback because we're requesting language 1, so no additional fallback possible
-            //
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = content_fallback;1,0',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => '1'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = strict',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-                'sys_language_mode' => 'strict',
-                'sys_language_contentOL' => '1'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = ignore',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-                'sys_language_mode' => 'ignore',
-                'sys_language_contentOL' => '1'
-            ],
-            // Expected behaviour:
-            // Non translated default language elements are not shown, because of hideNonTranslated
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode =',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-                'sys_language_mode' => '',
-                'sys_language_contentOL' => 'hideNonTranslated'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = content_fallback',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => 'hideNonTranslated'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = content_fallback;1,0',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => 'hideNonTranslated'
-            ],
-            //Setting sys_language_mode = strict has the same effect as previous data sets, because the translation of the page exists
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = strict',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-                'sys_language_mode' => 'strict',
-                'sys_language_contentOL' => 'hideNonTranslated'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = ignore',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-                'sys_language_mode' => 'ignore',
-                'sys_language_contentOL' => 'hideNonTranslated'
-            ],
-        ];
-    }
-
-    /**
-     * @test
-     * @dataProvider dutchDataProvider
-     *
-     * @param string $typoScript
-     * @param array $visibleRecords
-     * @param string $sysLanguageMode
-     * @param string $sysLanguageContentOL
-     */
-    public function renderingOfDutchLanguage(string $typoScript, array $visibleRecords, string $sysLanguageMode, string $sysLanguageContentOL)
-    {
-        $this->addTypoScriptToTemplateRecord(1, $typoScript);
-        $frontendResponse = $this->getFrontendResponse(self::VALUE_PageId, 1);
-        $responseSections = $frontendResponse->getResponseSections();
-        $visibleHeaders = array_map(function ($element) {
-            return $element['header'];
-        }, $visibleRecords);
-
-        $this->assertThat(
-            $responseSections,
-            $this->getRequestSectionHasRecordConstraint()
-            ->setTable(self::TABLE_Content)
-            ->setField('header')
-            ->setValues(...$visibleHeaders)
-        );
-        $this->assertThat(
-            $responseSections,
-            $this->getRequestSectionDoesNotHaveRecordConstraint()
-            ->setTable(self::TABLE_Content)
-            ->setField('header')
-            ->setValues(...$this->getNonVisibleHeaders($visibleHeaders))
-        );
-
-        foreach ($visibleRecords as $ttContentUid => $properties) {
-            $visibleFileTitles = $properties['image'];
-            if (!empty($visibleFileTitles)) {
-                $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
-                    ->setRecordIdentifier(self::TABLE_Content . ':' . $ttContentUid)->setRecordField('image')
-                    ->setTable('sys_file_reference')->setField('title')->setValues(...$visibleFileTitles));
-            }
-            $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
-                ->setRecordIdentifier(self::TABLE_Content . ':' . $ttContentUid)->setRecordField('image')
-                ->setTable('sys_file_reference')->setField('title')->setValues(...$this->getNonVisibleFileTitles($visibleFileTitles)));
-        }
-
-        $content = json_decode($frontendResponse->getContent());
-        $this->assertEquals('[DK]Page', $content->Scope->page->title);
-        $this->assertEquals(1, $content->Scope->tsfe->sys_language_uid, 'sys_language_uid doesn\'t match');
-        $this->assertEquals(1, $content->Scope->tsfe->sys_language_content, 'sys_language_content doesn\'t match');
-        $this->assertEquals($sysLanguageMode, $content->Scope->tsfe->sys_language_mode, 'sys_language_mode doesn\t match');
-        $this->assertEquals($sysLanguageContentOL, $content->Scope->tsfe->sys_language_contentOL, 'sys_language_contentOL doesn\t match');
-    }
-
-    public function contentOnNonTranslatedPageDataProvider(): array
-    {
-        //Expected behaviour:
-        //the page is NOT translated so setting sys_language_mode to different values changes the results
-        //- setting sys_language_mode to empty value makes TYPO3 return default language records
-        //- setting it to strict throws 404, independently from other settings
-        //Setting config.sys_language_overlay = 0
-        return [
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode =',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => 'Regular Element #1',
-                        'image' => ['T3BOARD'],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => 'Regular Element #3',
-                        'image' => ['Kasper'],
-                    ],
-                ],
-                'pageTitle' => 'Default language Page',
-                'sys_language_uid' => 0,
-                'sys_language_content' => 0,
-                'sys_language_mode' => '',
-                'sys_language_contentOL' => '0',
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = content_fallback',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => 'Regular Element #1',
-                        'image' => ['T3BOARD'],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => 'Regular Element #3',
-                        'image' => ['Kasper'],
-                    ],
-                ],
-                'pageTitle' => 'Default language Page',
-                'sys_language_uid' => 2,
-                'sys_language_content' => 0,
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => '0',
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = content_fallback;1,0',
-                'visibleRecords' => [
-                    300 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                    301 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                    ],
-                    303 => [
-                        'header' => '[DK] Without default language',
-                        'image' => ['[T3BOARD] Image added to DK element without default language'],
-                    ],
-                    308 => [
-                        'header' => '[DK] UnHidden Element #4',
-                        'image' => [],
-                    ],
-                ],
-                'pageTitle' => '[DK]Page',
-                'sys_language_uid' => 2,
-                'sys_language_content' => 1,
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => '0',
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = strict',
-                'visibleRecords' => [],
-                'pageTitle' => '',
-                'sys_language_uid' => 2,
-                'sys_language_content' => 2,
-                'sys_language_mode' => 'strict',
-                'sys_language_contentOL' => '0',
-                'statusCode' => 404,
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = ignore',
-                'visibleRecords' => [
-                    302 => [
-                        'header' => '[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1',
-                        'image' => ['[T3BOARD] image translated to DE from DK'],
-                    ],
-                    304 => [
-                        'header' => '[DE] Without default language',
-                        'image' => [],
-                    ],
-                ],
-                'pageTitle' => 'Default language Page',
-                'sys_language_uid' => 2,
-                'sys_language_content' => 2,
-                'sys_language_mode' => 'ignore',
-                'sys_language_contentOL' => '0',
-            ],
-            5 => [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode =',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => 'Regular Element #1',
-                        'image' => ['T3BOARD'],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => 'Regular Element #3',
-                        'image' => ['Kasper'],
-                    ],
-                ],
-                'pageTitle' => 'Default language Page',
-                'sys_language_uid' => 0,
-                'sys_language_content' => 0,
-                'sys_language_mode' => '',
-                'sys_language_contentOL' => '1',
-            ],
-            //falling back to default language
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = content_fallback',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => 'Regular Element #1',
-                        'image' => ['T3BOARD'],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => 'Regular Element #3',
-                        'image' => ['Kasper'],
-                    ],
-                ],
-                'pageTitle' => 'Default language Page',
-                'sys_language_uid' => 2,
-                'sys_language_content' => 0,
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => '1',
-            ],
-            //Dutch elements are shown because of the content fallback 1,0 - first Dutch, then default language
-            //note that '[DK] Without default language' is NOT shown - due to overlays (fetch default language and overlay it with translations)
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = content_fallback;1,0',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-                'pageTitle' => '[DK]Page',
-                'sys_language_uid' => 2,
-                'sys_language_content' => 1,
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => '1',
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = strict',
-                'visibleRecords' => [],
-                'pageTitle' => '',
-                'sys_language_uid' => 2,
-                'sys_language_content' => 2,
-                'sys_language_mode' => 'strict',
-                'sys_language_contentOL' => '1',
-                'statusCode' => 404
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = ignore',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1',
-                        'image' => ['[T3BOARD] image translated to DE from DK'],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => 'Regular Element #3',
-                        'image' => ['Kasper'],
-                    ],
-                ],
-                'pageTitle' => 'Default language Page',
-                'sys_language_uid' => 2,
-                'sys_language_content' => 2,
-                'sys_language_mode' => 'ignore',
-                'sys_language_contentOL' => '1',
-            ],
-            10 => [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode =',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => 'Regular Element #1',
-                        'image' => ['T3BOARD'],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => 'Regular Element #3',
-                        'image' => ['Kasper'],
-                    ],
-                ],
-                'pageTitle' => 'Default language Page',
-                'sys_language_uid' => 0,
-                'sys_language_content' => 0,
-                'sys_language_mode' => '',
-                'sys_language_contentOL' => 'hideNonTranslated',
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = content_fallback',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => 'Regular Element #1',
-                        'image' => ['T3BOARD'],
-                    ],
-                    298 => [
-                        'header' => 'Regular Element #2',
-                        'image' => ['Kasper2'],
-                    ],
-                    299 => [
-                        'header' => 'Regular Element #3',
-                        'image' => ['Kasper'],
-                    ],
-                ],
-                'pageTitle' => 'Default language Page',
-                'sys_language_uid' => 2,
-                'sys_language_content' => 0,
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => 'hideNonTranslated',
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = content_fallback;1,0',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Dansk:] Regular Element #1',
-                        'image' => [],
-                    ],
-                    299 => [
-                        'header' => '[Translate to Dansk:] Regular Element #3',
-                        'image' => ['[Kasper] Image translated to Dansk', '[T3BOARD] Image added in Dansk (without parent)'],
-                    ],
-                ],
-                'pageTitle' => '[DK]Page',
-                'sys_language_uid' => 2,
-                'sys_language_content' => 1,
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => 'hideNonTranslated',
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = strict',
-                'visibleRecords' => [],
-                'pageTitle' => '',
-                'sys_language_uid' => 2,
-                'sys_language_content' => 2,
-                'sys_language_mode' => 'strict',
-                'sys_language_contentOL' => 'hideNonTranslated',
-                'statusCode' => 404,
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = ignore',
-                'visibleRecords' => [
-                    297 => [
-                        'header' => '[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1',
-                        'image' => ['[T3BOARD] image translated to DE from DK'],
-                    ],
-                ],
-                'pageTitle' => 'Default language Page',
-                'sys_language_uid' => 2,
-                'sys_language_content' => 2,
-                'sys_language_mode' => 'ignore',
-                'sys_language_contentOL' => 'hideNonTranslated',
-            ],
-        ];
-    }
-
-    /**
-     * Page uid 89 is NOT translated to german
-     *
-     * @test
-     * @dataProvider contentOnNonTranslatedPageDataProvider
-     *
-     * @param string $typoScript
-     * @param array $visibleRecords
-     * @param string $pageTitle
-     * @param int $sysLanguageUid
-     * @param int $sysLanguageContent
-     * @param string $sysLanguageMode
-     * @param string $sysLanguageContentOL
-     * @param string $statusCode 200 or 404
-     */
-    public function contentOnNonTranslatedPageGerman(string $typoScript, array $visibleRecords, string $pageTitle, int $sysLanguageUid, int $sysLanguageContent, string $sysLanguageMode, string $sysLanguageContentOL, int $statusCode = 200)
-    {
-        $this->addTypoScriptToTemplateRecord(1, $typoScript);
-        $visibleHeaders = array_column($visibleRecords, 'header');
-
-        $response = $this->executeFrontendRequest(
-            (new InternalRequest())
-                ->withPageId(self::VALUE_PageId)
-                ->withLanguageId(2)
-        );
-
-        if ($statusCode === 200) {
-            $responseStructure = ResponseContent::fromString((string)$response->getBody());
-            $responseSections = $responseStructure->getSections();
-
-            $this->assertThat(
-                $responseSections,
-                $this->getRequestSectionHasRecordConstraint()
-                ->setTable(self::TABLE_Content)
-                ->setField('header')
-                ->setValues(...$visibleHeaders)
-            );
-            $this->assertThat(
-                $responseSections,
-                $this->getRequestSectionDoesNotHaveRecordConstraint()
-                ->setTable(self::TABLE_Content)
-                ->setField('header')
-                ->setValues(...$this->getNonVisibleHeaders($visibleHeaders))
-            );
-
-            foreach ($visibleRecords as $ttContentUid => $properties) {
-                $visibleFileTitles = $properties['image'];
-                if (!empty($visibleFileTitles)) {
-                    $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
-                        ->setRecordIdentifier(self::TABLE_Content . ':' . $ttContentUid)->setRecordField('image')
-                        ->setTable('sys_file_reference')->setField('title')->setValues(...$visibleFileTitles));
-                }
-                $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
-                    ->setRecordIdentifier(self::TABLE_Content . ':' . $ttContentUid)->setRecordField('image')
-                    ->setTable('sys_file_reference')->setField('title')->setValues(...$this->getNonVisibleFileTitles($visibleFileTitles)));
-            }
-
-            $this->assertEquals($pageTitle, $responseStructure->getScopePath('page/title'));
-            $this->assertEquals($sysLanguageUid, $responseStructure->getScopePath('tsfe/sys_language_uid'), 'sys_language_uid doesn\'t match');
-            $this->assertEquals($sysLanguageContent, $responseStructure->getScopePath('tsfe/sys_language_content'), 'sys_language_content doesn\'t match');
-            $this->assertEquals($sysLanguageMode, $responseStructure->getScopePath('tsfe/sys_language_mode'), 'sys_language_mode doesn\t match');
-            $this->assertEquals($sysLanguageContentOL, $responseStructure->getScopePath('tsfe/sys_language_contentOL'), 'sys_language_contentOL doesn\t match');
-        }
-
-        $this->assertEquals($statusCode, $response->getStatusCode());
-    }
-
-    public function contentOnPartiallyTranslatedPageDataProvider(): array
-    {
-
-        //Expected behaviour:
-        //Setting sys_language_mode to different values doesn't influence the result as the requested page is translated to Polish,
-        //Page title is always [PL]Page, and both sys_language_content and sys_language_uid are always 3
-        return [
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode =',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
-                'sys_language_mode' => '',
-                'sys_language_contentOL' => '0'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = content_fallback',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => '0'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = content_fallback;1,0',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => '0'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = strict',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
-                'sys_language_mode' => 'strict',
-                'sys_language_contentOL' => '0'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 0
-                                config.sys_language_mode = ignore',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
-                'sys_language_mode' => 'ignore',
-                'sys_language_contentOL' => '0'
-            ],
-            5 => [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode =',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
-                'sys_language_mode' => '',
-                'sys_language_contentOL' => '1'
-            ],
-            // Expected behaviour:
-            // Not translated element #2 is shown because sys_language_overlay = 1 (with sys_language_overlay = hideNonTranslated, it would be hidden)
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = content_fallback',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => '1'
-            ],
-            // Expected behaviour:
-            // Element #3 is not translated in PL and it is translated in DK. It's not shown as content_fallback is not related to single CE level
-            // but on page level - and this page is translated to Polish, so no fallback is happening
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = content_fallback;1,0',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => '1'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = strict',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
-                'sys_language_mode' => 'strict',
-                'sys_language_contentOL' => '1'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = 1
-                                config.sys_language_mode = ignore',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
-                'sys_language_mode' => 'ignore',
-                'sys_language_contentOL' => '1'
-            ],
-            // Expected behaviour:
-            // Non translated default language elements are not shown, because of hideNonTranslated
-            10 => [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode =',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1'],
-                'sys_language_mode' => '',
-                'sys_language_contentOL' => 'hideNonTranslated'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = content_fallback',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1'],
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => 'hideNonTranslated'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = content_fallback;1,0',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1'],
-                'sys_language_mode' => 'content_fallback',
-                'sys_language_contentOL' => 'hideNonTranslated'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = strict',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1'],
-                'sys_language_mode' => 'strict',
-                'sys_language_contentOL' => 'hideNonTranslated'
-            ],
-            [
-                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
-                                config.sys_language_mode = ignore',
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1'],
-                'sys_language_mode' => 'ignore',
-                'sys_language_contentOL' => 'hideNonTranslated'
-            ]
-        ];
-    }
-
-    /**
-     * Page uid 89 is translated to to Polish, but not all CE are translated
-     *
-     * @test
-     * @dataProvider contentOnPartiallyTranslatedPageDataProvider
-     *
-     * @param string $typoScript
-     * @param array $visibleHeaders
-     * @param string $sysLanguageMode
-     * @param string $sysLanguageContentOL
-     */
-    public function contentOnPartiallyTranslatedPage(string $typoScript, array $visibleHeaders, string $sysLanguageMode, string $sysLanguageContentOL)
-    {
-        $this->addTypoScriptToTemplateRecord(1, $typoScript);
-
-        $frontendResponse = $this->getFrontendResponse(self::VALUE_PageId, 3);
-        $this->assertEquals('success', $frontendResponse->getStatus());
-        $responseSections = $frontendResponse->getResponseSections();
-
-        $this->assertThat(
-            $responseSections,
-            $this->getRequestSectionHasRecordConstraint()
-            ->setTable(self::TABLE_Content)
-            ->setField('header')
-            ->setValues(...$visibleHeaders)
-        );
-        $this->assertThat(
-            $responseSections,
-            $this->getRequestSectionDoesNotHaveRecordConstraint()
-            ->setTable(self::TABLE_Content)
-            ->setField('header')
-            ->setValues(...$this->getNonVisibleHeaders($visibleHeaders))
-        );
-
-        $content = json_decode($frontendResponse->getContent());
-        $this->assertEquals('[PL]Page', $content->Scope->page->title);
-        $this->assertEquals(3, $content->Scope->tsfe->sys_language_uid, 'sys_language_uid doesn\'t match');
-        $this->assertEquals(3, $content->Scope->tsfe->sys_language_content, 'sys_language_content doesn\'t match');
-        $this->assertEquals($sysLanguageMode, $content->Scope->tsfe->sys_language_mode, 'sys_language_mode doesn\t match');
-        $this->assertEquals($sysLanguageContentOL, $content->Scope->tsfe->sys_language_contentOL, 'sys_language_contentOL doesn\t match');
-    }
-
-    /**
-     * Helper function to ease asserting that rest of the data set is not visible
-     *
-     * @param array $visibleHeaders
-     * @return array
-     */
-    protected function getNonVisibleHeaders(array $visibleHeaders): array
-    {
-        $allElements = [
-            'Regular Element #1',
-            'Regular Element #2',
-            'Regular Element #3',
-            'Hidden Element #4',
-            '[Translate to Dansk:] Regular Element #1',
-            '[Translate to Dansk:] Regular Element #3',
-            '[DK] Without default language',
-            '[DK] UnHidden Element #4',
-            '[DE] Without default language',
-            '[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1',
-            '[Translate to Polski:] Regular Element #1',
-            '[PL] Without default language',
-            '[PL] Hidden Regular Element #2'
-        ];
-        return array_diff($allElements, $visibleHeaders);
-    }
-
-    /**
-     * Helper function to ease asserting that rest of the files are not present
-     *
-     * @param array $visibleTitles
-     * @return array
-     */
-    protected function getNonVisibleFileTitles(array $visibleTitles): array
-    {
-        $allElements = [
-            'T3BOARD',
-            'Kasper',
-            '[Kasper] Image translated to Dansk',
-            '[T3BOARD] Image added in Dansk (without parent)',
-            '[T3BOARD] Image added to DK element without default language',
-            '[T3BOARD] image translated to DE from DK',
-            'Kasper2',
-        ];
-        return array_diff($allElements, $visibleTitles);
-    }
-}
index 983737d..d17c8a4 100644 (file)
@@ -1,13 +1,9 @@
 config {
   no_cache = 1
   debug = 0
-  xhtml_cleaning = 0
   admPanel = 0
   disableAllHeaderCode = 1
   sendCacheHeaders = 0
-  sys_language_uid = 0
-  sys_language_mode = ignore
-  sys_language_overlay = 1
   additionalHeaders.10.header = Content-Type: application/json; charset=utf-8
   additionalHeaders.10.replace = 1
 }
index e30bdc8..333bf04 100644 (file)
@@ -1,13 +1,9 @@
 config {
   no_cache = 1
   debug = 0
-  xhtml_cleaning = 0
   admPanel = 0
   disableAllHeaderCode = 1
   sendCacheHeaders = 0
-  sys_language_uid = 0
-  sys_language_mode = ignore
-  sys_language_overlay = 1
   additionalHeaders.10.header = Content-Type: application/json; charset=utf-8
   additionalHeaders.10.replace = 1
 }
diff --git a/typo3/sysext/frontend/Tests/Functional/SiteHandling/LinkGeneratorTest.php b/typo3/sysext/frontend/Tests/Functional/SiteHandling/LinkGeneratorTest.php
deleted file mode 100644 (file)
index 0f4aee0..0000000
+++ /dev/null
@@ -1,784 +0,0 @@
-<?php
-declare(strict_types = 1);
-namespace TYPO3\CMS\Frontend\Tests\Functional\SiteHandling;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\CMS\Backend\Utility\BackendUtility;
-use TYPO3\CMS\Core\Core\Bootstrap;
-use TYPO3\CMS\Core\TypoScript\TemplateService;
-use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataHandlerFactory;
-use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataHandlerWriter;
-use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\Internal\TypoScriptInstruction;
-use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
-use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequestContext;
-
-/**
- * Test case for frontend requests not having site handling configured
- * (aka testing legacy link generation)
- */
-class LinkGeneratorTest extends AbstractTestCase
-{
-    /**
-     * @var string
-     */
-    private $siteTitle = 'A Company that Manufactures Everything Inc';
-
-    /**
-     * @var InternalRequestContext
-     */
-    private $internalRequestContext;
-
-    public static function setUpBeforeClass(): void
-    {
-        parent::setUpBeforeClass();
-        static::initializeDatabaseSnapshot();
-    }
-
-    public static function tearDownAfterClass(): void
-    {
-        static::destroyDatabaseSnapshot();
-        parent::tearDownAfterClass();
-    }
-
-    protected function setUp(): void
-    {
-        parent::setUp();
-
-        // these settings are forwarded to the frontend sub-request as well
-        $this->internalRequestContext = (new InternalRequestContext())
-            ->withGlobalSettings(['TYPO3_CONF_VARS' => static::TYPO3_CONF_VARS]);
-
-        $this->withDatabaseSnapshot(function () {
-            $this->setUpDatabase();
-        });
-    }
-
-    protected function setUpDatabase()
-    {
-        $backendUser = $this->setUpBackendUserFromFixture(1);
-        Bootstrap::initializeLanguageObject();
-
-        $scenarioFile = __DIR__ . '/Fixtures/PlainScenario.yaml';
-        $factory = DataHandlerFactory::fromYamlFile($scenarioFile);
-        $writer = DataHandlerWriter::withBackendUser($backendUser);
-        $writer->invokeFactory($factory);
-        static::failIfArrayIsNotEmpty(
-            $writer->getErrors()
-        );
-
-        $this->setUpFrontendRootPage(
-            1000,
-            [
-                'typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/LinkGenerator.typoscript',
-            ],
-            [
-                'title' => 'ACME Root',
-                'sitetitle' => $this->siteTitle,
-            ]
-        );
-        $this->setUpFrontendRootPage(
-            2000,
-            [
-                'typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/LinkGenerator.typoscript',
-            ],
-            [
-                'title' => 'ACME Blog',
-                'sitetitle' => $this->siteTitle,
-            ]
-        );
-    }
-
-    protected function tearDown(): void
-    {
-        unset($this->internalRequestContext);
-        parent::tearDown();
-    }
-
-    /**
-     * @return array
-     */
-    public function linkIsGeneratedDataProvider(): array
-    {
-        $instructions = [
-            // acme.com -> acme.com (same site)
-            [1100, 1000, 'index.php?id=1000'],
-            [1100, 1100, 'index.php?id=1100'],
-            [1100, 1200, 'index.php?id=1200'],
-            [1100, 1210, 'index.php?id=1210'],
-            [1100, 404, 'index.php?id=404'],
-            // acme.com -> products.acme.com (nested sub-site)
-            [1100, 1300, 'index.php?id=1300'],
-            [1100, 1310, 'index.php?id=1310'],
-            // acme.com -> blog.acme.com (different site)
-            [1100, 2000, 'index.php?id=2000'],
-            [1100, 2100, 'index.php?id=2100'],
-            [1100, 2110, 'index.php?id=2110'],
-            [1100, 2111, 'index.php?id=2111'],
-            // blog.acme.com -> acme.com (different site)
-            [2100, 1000, 'index.php?id=1000'],
-            [2100, 1100, 'index.php?id=1100'],
-            [2100, 1200, 'index.php?id=1200'],
-            [2100, 1210, 'index.php?id=1210'],
-            [2100, 404, 'index.php?id=404'],
-            // blog.acme.com -> products.acme.com (different sub-site)
-            [2100, 1300, 'index.php?id=1300'],
-            [2100, 1310, 'index.php?id=1310'],
-        ];
-
-        return $this->keysFromTemplate(
-            $instructions,
-            '%1$d->%2$d'
-        );
-    }
-
-    /**
-     * @param int $sourcePageId
-     * @param int $targetPageId
-     * @param string $expectation
-     *
-     * @test
-     * @dataProvider linkIsGeneratedDataProvider
-     */
-    public function linkIsGenerated(int $sourcePageId, int $targetPageId, string $expectation)
-    {
-        $response = $this->executeFrontendRequest(
-            (new InternalRequest())
-                ->withPageId($sourcePageId)
-                ->withInstructions([
-                    $this->createTypoLinkUrlInstruction([
-                        'parameter' => $targetPageId,
-                    ])
-                ]),
-            $this->internalRequestContext
-        );
-
-        static::assertSame($expectation, (string)$response->getBody());
-    }
-
-    /**
-     * @return array
-     */
-    public function linkIsGeneratedFromMountPointDataProvider(): array
-    {
-        $instructions = [
-            // acme.com -> acme.com (same site)
-            [[7100, 1700], 7110, 1000, 'index.php?id=1000'],
-            [[7100, 1700], 7110, 1100, 'index.php?id=1100'],
-            [[7100, 1700], 7110, 1200, 'index.php?id=1200'],
-            [[7100, 1700], 7110, 1210, 'index.php?id=1210'],
-            [[7100, 1700], 7110, 404, 'index.php?id=404'],
-            // acme.com -> products.acme.com (nested sub-site)
-            [[7100, 1700], 7110, 1300, 'index.php?id=1300'],
-            [[7100, 1700], 7110, 1310, 'index.php?id=1310'],
-            // acme.com -> blog.acme.com (different site)
-            [[7100, 1700], 7110, 2000, 'index.php?id=2000'],
-            [[7100, 1700], 7110, 2100, 'index.php?id=2100'],
-            [[7100, 1700], 7110, 2110, 'index.php?id=2110'],
-            [[7100, 1700], 7110, 2111, 'index.php?id=2111'],
-            // blog.acme.com -> acme.com (different site)
-            [[7100, 2700], 7110, 1000, 'index.php?id=1000'],
-            [[7100, 2700], 7110, 1100, 'index.php?id=1100'],
-            [[7100, 2700], 7110, 1200, 'index.php?id=1200'],
-            [[7100, 2700], 7110, 1210, 'index.php?id=1210'],
-            [[7100, 2700], 7110, 404, 'index.php?id=404'],
-            // blog.acme.com -> products.acme.com (different sub-site)
-            [[7100, 2700], 7110, 1300, 'index.php?id=1300'],
-            [[7100, 2700], 7110, 1310, 'index.php?id=1310'],
-        ];
-
-        return $this->keysFromTemplate(
-            $instructions,
-            '%2$d->%3$d (mount:%1$s)',
-            function (array $items) {
-                array_splice(
-                    $items,
-                    0,
-                    1,
-                    [implode('->', $items[0])]
-                );
-                return $items;
-            }
-        );
-    }
-
-    /**
-     * @param array $pageMount
-     * @param int $sourcePageId
-     * @param int $targetPageId
-     * @param string $expectation
-     *
-     * @test
-     * @dataProvider linkIsGeneratedFromMountPointDataProvider
-     */
-    public function linkIsGeneratedFromMountPoint(array $pageMount, int $sourcePageId, int $targetPageId, string $expectation)
-    {
-        // @todo Fix mount point resolving for for pseudo-sites
-        // (PseudoSite should be resolved based on MP-value instead of ID in middleware)
-        $this->markTestSkipped('Mount points currently cannot be resolved in legacy mode');
-
-        $response = $this->executeFrontendRequest(
-            (new InternalRequest())
-                ->withMountPoint(...$pageMount)
-                ->withPageId($sourcePageId)
-                ->withInstructions([
-                    $this->createTypoLinkUrlInstruction([
-                        'parameter' => $targetPageId,
-                    ])
-                ]),
-            $this->internalRequestContext
-        );
-
-        static::assertSame($expectation, (string)$response->getBody());
-    }
-
-    /**
-     * @return array
-     */
-    public function linkIsGeneratedForLanguageDataProvider(): array
-    {
-        $instructions = [
-            // acme.com -> acme.com (same site)
-            [1100, 1100, 0, 'index.php?id=1100&L=0'],
-            [1100, 1100, 1, 'index.php?id=1100&L=1'],
-            [1100, 1100, 2, 'index.php?id=1100&L=2'],
-            [1100, 1101, 0, 'index.php?id=1100&L=1'],
-            [1100, 1102, 0, 'index.php?id=1100&L=2'],
-            // acme.com -> products.acme.com (nested sub-site)
-            [1100, 1300, 0, 'index.php?id=1300&L=0'],
-            [1100, 1310, 0, 'index.php?id=1310&L=0'],
-            // acme.com -> products.acme.com (nested sub-site, l18n_cfg=1)
-            [1100, 1410, 0, ''],
-            [1100, 1410, 1, 'index.php?id=1410&L=1'],
-            [1100, 1410, 2, 'index.php?id=1410&L=2'],
-            [1100, 1411, 0, 'index.php?id=1410&L=1'],
-            [1100, 1412, 0, 'index.php?id=1410&L=2'],
-            // acme.com -> archive (outside site)
-            [1100, 3100, 0, 'index.php?id=3100&L=0'],
-            [1100, 3100, 1, 'index.php?id=3100&L=1'],
-            [1100, 3100, 2, 'index.php?id=3100&L=2'],
-            [1100, 3101, 0, 'index.php?id=3100&L=1'],
-            [1100, 3102, 0, 'index.php?id=3100&L=2'],
-            // blog.acme.com -> acme.com (different site)
-            [2100, 1100, 0, 'index.php?id=1100&L=0'],
-            [2100, 1100, 1, 'index.php?id=1100&L=1'],
-            [2100, 1100, 2, 'index.php?id=1100&L=2'],
-            [2100, 1101, 0, 'index.php?id=1100&L=1'],
-            [2100, 1102, 0, 'index.php?id=1100&L=2'],
-            // blog.acme.com -> archive (outside site)
-            [2100, 3100, 0, 'index.php?id=3100&L=0'],
-            [2100, 3100, 1, 'index.php?id=3100&L=1'],
-            [2100, 3100, 2, 'index.php?id=3100&L=2'],
-            [2100, 3101, 0, 'index.php?id=3100&L=1'],
-            [2100, 3102, 0, 'index.php?id=3100&L=2'],
-            // blog.acme.com -> products.acme.com (different sub-site)
-            [2100, 1300, 0, 'index.php?id=1300&L=0'],
-            [2100, 1310, 0, 'index.php?id=1310&L=0'],
-        ];
-
-        return $this->keysFromTemplate(
-            $instructions,
-            '%1$d->%2$d (lang:%3$d)'
-        );
-    }
-
-    /**
-     * @param int $sourcePageId
-     * @param int $targetPageId
-     * @param int $targetLanguageId
-     * @param string $expectation
-     *
-     * @test
-     * @dataProvider linkIsGeneratedForLanguageDataProvider
-     */
-    public function linkIsGeneratedForLanguage(int $sourcePageId, int $targetPageId, int $targetLanguageId, string $expectation)
-    {
-        $response = $this->executeFrontendRequest(
-            (new InternalRequest())
-                ->withPageId($sourcePageId)
-                ->withInstructions([
-                    $this->createTypoLinkUrlInstruction([
-                        'parameter' => $targetPageId,
-                        'additionalParams' => '&L=' . $targetLanguageId,
-                    ])
-                ]),
-            $this->internalRequestContext
-        );
-
-        static::assertSame($expectation, (string)$response->getBody());
-    }
-
-    /**
-     * @return array
-     */
-    public function linkIsGeneratedWithQueryParametersDataProvider(): array
-    {
-        $instructions = [
-            // acme.com -> acme.com (same site)
-            [1100, 1000, 'index.php?id=1000&testing%5Bvalue%5D=1&cHash=7d1f13fa91159dac7feb3c824936b39d'],
-            [1100, 1100, 'index.php?id=1100&testing%5Bvalue%5D=1&cHash=f42b850e435f0cedd366f5db749fc1af'],
-            [1100, 1200, 'index.php?id=1200&testing%5Bvalue%5D=1&cHash=784e11c50ea1a13fd7d969df4ec53ea3'],
-            [1100, 1210, 'index.php?id=1210&testing%5Bvalue%5D=1&cHash=ccb7067022b9835ebfd8f720722bc708'],
-            [1100, 404, 'index.php?id=404&testing%5Bvalue%5D=1&cHash=864e96f586a78a53452f3bf0f4d24591'],
-            // acme.com -> products.acme.com (nested sub-site)
-            [1100, 1300, 'index.php?id=1300&testing%5Bvalue%5D=1&cHash=dbd6597d72ed5098cce3d03eac1eeefe'],
-            [1100, 1310, 'index.php?id=1310&testing%5Bvalue%5D=1&cHash=e64bfc7ab7dd6b70d161e4d556be9726'],
-            // acme.com -> blog.acme.com (different site)
-            [1100, 2000, 'index.php?id=2000&testing%5Bvalue%5D=1&cHash=a14da633e46dba71640cb85226cd12c5'],
-            [1100, 2100, 'index.php?id=2100&testing%5Bvalue%5D=1&cHash=d23d74cb50383f8788a9930ec8ba679f'],
-            [1100, 2110, 'index.php?id=2110&testing%5Bvalue%5D=1&cHash=bf25eea89f44a9a79dabdca98f38a432'],
-            [1100, 2111, 'index.php?id=2111&testing%5Bvalue%5D=1&cHash=42dbaeb9172b6b1ca23b49941e194db2'],
-            // blog.acme.com -> acme.com (different site)
-            [2100, 1000, 'index.php?id=1000&testing%5Bvalue%5D=1&cHash=7d1f13fa91159dac7feb3c824936b39d'],
-            [2100, 1100, 'index.php?id=1100&testing%5Bvalue%5D=1&cHash=f42b850e435f0cedd366f5db749fc1af'],
-            [2100, 1200, 'index.php?id=1200&testing%5Bvalue%5D=1&cHash=784e11c50ea1a13fd7d969df4ec53ea3'],
-            [2100, 1210, 'index.php?id=1210&testing%5Bvalue%5D=1&cHash=ccb7067022b9835ebfd8f720722bc708'],
-            [2100, 404, 'index.php?id=404&testing%5Bvalue%5D=1&cHash=864e96f586a78a53452f3bf0f4d24591'],
-            // blog.acme.com -> products.acme.com (different sub-site)
-            [2100, 1300, 'index.php?id=1300&testing%5Bvalue%5D=1&cHash=dbd6597d72ed5098cce3d03eac1eeefe'],
-            [2100, 1310, 'index.php?id=1310&testing%5Bvalue%5D=1&cHash=e64bfc7ab7dd6b70d161e4d556be9726'],
-        ];
-
-        return $this->keysFromTemplate(
-            $instructions,
-            '%1$d->%2$d'
-        );
-    }
-
-    /**
-     * @param int $sourcePageId
-     * @param int $targetPageId
-     * @param string $expectation
-     *
-     * @test
-     * @dataProvider linkIsGeneratedWithQueryParametersDataProvider
-     */
-    public function linkIsGeneratedWithQueryParameters(int $sourcePageId, int $targetPageId, string $expectation)
-    {
-        $response = $this->executeFrontendRequest(
-            (new InternalRequest())
-                ->withPageId($sourcePageId)
-                ->withInstructions([
-                    $this->createTypoLinkUrlInstruction([
-                        'parameter' => $targetPageId,
-                        'additionalParams' => '&testing[value]=1',
-                        'useCacheHash' => 1,
-                    ])
-                ]),
-            $this->internalRequestContext
-        );
-
-        static::assertSame($expectation, (string)$response->getBody());
-    }
-
-    /**
-     * @return array
-     */
-    public function linkIsGeneratedForRestrictedPageDataProvider(): array
-    {
-        $instructions = [
-            [1100, 1510, 0, ''],
-            // [1100, 1511, 0, ''], // @todo Fails, not expanded to sub-pages
-            [1100, 1512, 0, ''],
-            [1100, 1515, 0, ''],
-            [1100, 1520, 0, ''],
-            // [1100, 1521, 0, ''], // @todo Fails, not expanded to sub-pages
-            //
-            [1100, 1510, 1, 'index.php?id=1510'],
-            [1100, 1511, 1, 'index.php?id=1511'],
-            [1100, 1512, 1, 'index.php?id=1512'],
-            [1100, 1515, 1, ''],
-            [1100, 1520, 1, ''],
-            // [1100, 1521, 1, ''], // @todo Fails, not expanded to sub-pages
-            //
-            [1100, 1510, 2, 'index.php?id=1510'],
-            [1100, 1511, 2, 'index.php?id=1511'],
-            [1100, 1512, 2, ''],
-            [1100, 1515, 2, 'index.php?id=1515'],
-            [1100, 1520, 2, 'index.php?id=1520'],
-            [1100, 1521, 2, 'index.php?id=1521'],
-            //
-            [1100, 1510, 3, 'index.php?id=1510'],
-            [1100, 1511, 3, 'index.php?id=1511'],
-            [1100, 1512, 3, 'index.php?id=1512'],
-            [1100, 1515, 3, 'index.php?id=1515'],
-            [1100, 1520, 3, 'index.php?id=1520'],
-            [1100, 1521, 3, 'index.php?id=1521'],
-        ];
-
-        return $this->keysFromTemplate(
-            $instructions,
-            '%1$d->%2$d (user:%3$d)'
-        );
-    }
-
-    /**
-     * @param int $sourcePageId
-     * @param int $targetPageId
-     * @param int $frontendUserId
-     * @param string $expectation
-     *
-     * @test
-     * @dataProvider linkIsGeneratedForRestrictedPageDataProvider
-     */
-    public function linkIsGeneratedForRestrictedPage(int $sourcePageId, int $targetPageId, int $frontendUserId, string $expectation)
-    {
-        $response = $this->executeFrontendRequest(
-            (new InternalRequest())
-                ->withPageId($sourcePageId)
-                ->withInstructions([
-                    $this->createTypoLinkUrlInstruction([
-                        'parameter' => $targetPageId,
-                    ])
-                ]),
-            $this->internalRequestContext
-                ->withFrontendUserId($frontendUserId)
-        );
-
-        static::assertSame($expectation, (string)$response->getBody());
-    }
-
-    /**
-     * @return array
-     */
-    public function linkIsGeneratedForRestrictedPageUsingLoginPageDataProvider(): array
-    {
-        $instructions = [
-            // no frontend user given
-            [1100, 1510, 1500, 0, 'index.php?id=1500&pageId=1510'],
-            // [1100, 1511, 1500, 0, 'index.php?id=1500&pageId=1511'], // @todo Fails, not expanded to sub-pages
-            [1100, 1512, 1500, 0, 'index.php?id=1500&pageId=1512'],
-            [1100, 1515, 1500, 0, 'index.php?id=1500&pageId=1515'],
-            [1100, 1520, 1500, 0, 'index.php?id=1500&pageId=1520'],
-            // [1100, 1521, 1500, 0, 'index.php?id=1500&pageId=1521'], // @todo Fails, not expanded to sub-pages
-            // frontend user 1
-            [1100, 1510, 1500, 1, 'index.php?id=1510'],
-            [1100, 1511, 1500, 1, 'index.php?id=1511'],
-            [1100, 1512, 1500, 1, 'index.php?id=1512'],
-            [1100, 1515, 1500, 1, 'index.php?id=1500&pageId=1515'],
-            [1100, 1520, 1500, 1, 'index.php?id=1500&pageId=1520'],
-            // [1100, 1521, 1500, 1, 'index.php?id=1500&pageId=1521'], // @todo Fails, not expanded to sub-pages
-            // frontend user 2
-            [1100, 1510, 1500, 2, 'index.php?id=1510'],
-            [1100, 1511, 1500, 2, 'index.php?id=1511'],
-            [1100, 1512, 1500, 2, 'index.php?id=1500&pageId=1512'],
-            [1100, 1515, 1500, 2, 'index.php?id=1515'],
-            [1100, 1520, 1500, 2, 'index.php?id=1520'],
-            [1100, 1521, 1500, 2, 'index.php?id=1521'],
-            // frontend user 3
-            [1100, 1510, 1500, 3, 'index.php?id=1510'],
-            [1100, 1511, 1500, 3, 'index.php?id=1511'],
-            [1100, 1512, 1500, 3, 'index.php?id=1512'],
-            [1100, 1515, 1500, 3, 'index.php?id=1515'],
-            [1100, 1520, 1500, 3, 'index.php?id=1520'],
-            [1100, 1521, 1500, 3, 'index.php?id=1521'],
-        ];
-
-        return $this->keysFromTemplate(
-            $instructions,
-            '%1$d->%2$d (via: %3$d, user:%4$d)'
-        );
-    }
-
-    /**
-     * @param int $sourcePageId
-     * @param int $targetPageId
-     * @param int $loginPageId
-     * @param int $frontendUserId
-     * @param string $expectation
-     *
-     * @test
-     * @dataProvider linkIsGeneratedForRestrictedPageUsingLoginPageDataProvider
-     */
-    public function linkIsGeneratedForRestrictedPageUsingLoginPage(int $sourcePageId, int $targetPageId, int $loginPageId, int $frontendUserId, string $expectation)
-    {
-        $response = $this->executeFrontendRequest(
-            (new InternalRequest())
-                ->withPageId($sourcePageId)
-                ->withInstructions([
-                    (new TypoScriptInstruction(TemplateService::class))
-                        ->withTypoScript([
-                            'config.' => [
-                                'typolinkLinkAccessRestrictedPages' => $loginPageId,
-                                'typolinkLinkAccessRestrictedPages_addParams' => '&pageId=###PAGE_ID###'
-                            ],
-                        ]),
-                    $this->createTypoLinkUrlInstruction([
-                        'parameter' => $targetPageId,
-                    ])
-                ]),
-            $this->internalRequestContext
-                ->withFrontendUserId($frontendUserId)
-        );
-
-        static::assertSame($expectation, (string)$response->getBody());
-    }
-
-    /**
-     * @return array
-     */
-    public function linkIsGeneratedForPageVersionDataProvider(): array
-    {
-        $instructions = [
-            // acme.com -> acme.com (same site)
-            [1100, 1100, false, 'index.php?id=1100'],
-            [1100, 1100, true, 'index.php?id=7131'],
-            [1100, 1950, false, 'index.php?id=1950'],
-            [1100, 1950, true, 'index.php?id={targetPageId}'],
-            // blog.acme.com -> acme.com (different site)
-            [2100, 1100, false, 'index.php?id=1100'],
-            // @todo https://acme.us/ not prefixed for resolved version
-            [2100, 1100, true, 'index.php?id=7131'],
-            [2100, 1950, false, 'index.php?id=1950'],
-            // @todo https://acme.us/ not prefixed for resolved version
-            [2100, 1950, true, 'index.php?id={targetPageId}'],
-        ];
-
-        return $this->keysFromTemplate(
-            $instructions,
-            '%1$d->%2$d (resolve:%3$d)'
-        );
-    }
-
-    /**
-     * @param int $sourcePageId
-     * @param int $targetPageId
-     * @param bool $resolveVersion
-     * @param string $expectation
-     *
-     * @test
-     * @dataProvider linkIsGeneratedForPageVersionDataProvider
-     */
-    public function linkIsGeneratedForPageVersion(int $sourcePageId, int $targetPageId, bool $resolveVersion, string $expectation)
-    {
-        $workspaceId = 1;
-        $backendUserId = 1;
-        if ($resolveVersion) {
-            $targetPageId = BackendUtility::getWorkspaceVersionOfRecord(
-                $workspaceId,
-                'pages',
-                $targetPageId,
-                'uid'
-            )['uid'] ?? null;
-        }
-
-        $response = $this->executeFrontendRequest(
-            (new InternalRequest())
-                ->withPageId($sourcePageId)
-                ->withInstructions([
-                    $this->createTypoLinkUrlInstruction([
-                        'parameter' => $targetPageId,
-                    ])
-                ]),
-            $this->internalRequestContext
-                ->withWorkspaceId($workspaceId)
-                ->withBackendUserId($backendUserId)
-        );
-
-        $expectation = str_replace(
-            ['{targetPageId}'],
-            [$targetPageId],
-            $expectation
-        );
-
-        static::assertSame($expectation, (string)$response->getBody());
-    }
-
-    /**
-     * @return array
-     */
-    public function hierarchicalMenuIsGeneratedDataProvider(): array
-    {
-        return [
-            'ACME Inc' => [
-                1100,
-                [
-                    ['title' => 'EN: Welcome', 'link' => 'index.php?id=1100'],
-                    [
-                        'title' => 'EN: Features',
-                        'link' => 'index.php?id=1200',
-                        'children' => [
-                            [
-                                'title' => 'EN: Frontend Editing',
-                                'link' => 'index.php?id=1210',
-                            ],
-                        ],
-                    ],
-                    [
-                        'title' => 'EN: Products',
-                        'link' => 'index.php?id=1300',
-                        'children' => [
-                            [
-                                'title' => 'EN: Planets',
-                                'link' => 'index.php?id=1310',
-                            ],
-                            [
-                                'title' => 'EN: Spaceships',
-                                'link' => 'index.php?id=1320',
-                            ],
-                            [
-                                'title' => 'EN: Dark Matter',
-                                'link' => 'index.php?id=1330',
-                            ],
-                        ],
-                    ],
-                    ['title' => 'EN: ACME in your Region', 'link' => 'index.php?id=1400'],
-                    ['title' => 'Internal', 'link' => 'index.php?id=1500'],
-                    ['title' => 'About us', 'link' => 'index.php?id=1600'],
-                    [
-                        'title' => 'Announcements & News',
-                        'link' => 'index.php?id=1700',
-                        'children' => [
-                            [
-                                'title' => 'Markets',
-                                'link' => 'index.php?id=7110&MP=7100-1700',
-                            ],
-                            [
-                                'title' => 'Products',
-                                'link' => 'index.php?id=7120&MP=7100-1700',
-                            ],
-                            [
-                                'title' => 'Partners',
-                                'link' => 'index.php?id=7130&MP=7100-1700',
-                            ],
-                        ],
-                    ],
-                    ['title' => 'Page not found', 'link' => 'index.php?id=404'],
-                    ['title' => 'Our Blog', 'link' => 'index.php?id=2100'],
-                ]
-            ],
-            'ACME Blog' => [
-                2100,
-                [
-                    [
-                        'title' => 'Authors',
-                        'link' => 'index.php?id=2100',
-                        'children' => [
-                            [
-                                'title' => 'John Doe',
-                                'link' => 'index.php?id=2110',
-                            ],
-                            [
-                                'title' => 'Jane Doe',
-                                'link' => 'index.php?id=2120',
-                            ],
-                        ],
-                    ],
-                    1 =>
-                        [
-                            'title' => 'Announcements & News',
-                            'link' => 'index.php?id=2700',
-                            'children' => [
-                                [
-                                    'title' => 'Markets',
-                                    'link' => 'index.php?id=7110&MP=7100-2700',
-                                ],
-                                [
-                                    'title' => 'Products',
-                                    'link' => 'index.php?id=7120&MP=7100-2700',
-                                ],
-                                [
-                                    'title' => 'Partners',
-                                    'link' => 'index.php?id=7130&MP=7100-2700',
-                                ],
-                            ],
-                        ],
-                    ['title' => 'ACME Inc', 'link' => 'index.php?id=1100'],
-                ]
-            ]
-        ];
-    }
-
-    /**
-     * @param int $sourcePageId
-     * @param array $expectation
-     *
-     * @test
-     * @dataProvider hierarchicalMenuIsGeneratedDataProvider
-     */
-    public function hierarchicalMenuIsGenerated(int $sourcePageId, array $expectation)
-    {
-        $response = $this->executeFrontendRequest(
-            (new InternalRequest())
-                ->withPageId($sourcePageId)
-                ->withInstructions([
-                    $this->createHierarchicalMenuProcessorInstruction([
-                        'levels' => 2,
-                        'entryLevel' => 0,
-                        'expandAll' => 1,
-                        'includeSpacer' => 1,
-                        'titleField' => 'title',
-                        'as' => 'results',
-                    ])
-                ]),
-            $this->internalRequestContext
-        );
-
-        $json = json_decode((string)$response->getBody(), true);
-        $json = $this->filterMenu($json);
-
-        static::assertSame($expectation, $json);
-    }
-
-    /**
-     * @return array
-     */
-    public function languageMenuIsGeneratedDataProvider(): array
-    {
-        return [
-            'ACME Inc' => [
-                1100,
-                [
-                    ['title' => 'Default', 'link' => 'index.php?id=1100&L=0'],
-                    ['title' => 'French', 'link' => 'index.php?id=1100&L=1'],
-                    ['title' => 'Franco-Canadian', 'link' => 'index.php?id=1100&L=2'],
-                ]
-            ],
-            'ACME Blog' => [
-                2100,
-                [
-                    ['title' => 'Default', 'link' => 'index.php?id=2100&L=0'],
-                    ['title' => 'French', 'link' => 'index.php?id=2100&L=1'],
-                    ['title' => 'Franco-Canadian', 'link' => 'index.php?id=2100&L=2'],
-                ]
-            ]
-        ];
-    }
-
-    /**
-     * @param int $sourcePageId
-     * @param array $expectation
-     *
-     * @test
-     * @dataProvider languageMenuIsGeneratedDataProvider
-     */
-    public function languageMenuIsGenerated(int $sourcePageId, array $expectation)
-    {
-        $response = $this->executeFrontendRequest(
-            (new InternalRequest())
-                ->withPageId($sourcePageId)
-                ->withInstructions([
-                    $this->createLanguageMenuProcessorInstruction([
-                        'languages' => 'auto',
-                    ])
-                ]),
-            $this->internalRequestContext
-        );
-
-        $json = json_decode((string)$response->getBody(), true);
-        $json = $this->filterMenu($json);
-
-        static::assertSame($expectation, $json);
-    }
-}
diff --git a/typo3/sysext/frontend/Tests/Functional/SiteHandling/PlainRequestTest.php b/typo3/sysext/frontend/Tests/Functional/SiteHandling/PlainRequestTest.php
deleted file mode 100644 (file)
index 2ca43af..0000000
+++ /dev/null
@@ -1,581 +0,0 @@
-<?php
-declare(strict_types = 1);
-namespace TYPO3\CMS\Frontend\Tests\Functional\SiteHandling;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\CMS\Core\Core\Bootstrap;
-use TYPO3\CMS\Core\Error\Http\PageNotFoundException;
-use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataHandlerFactory;
-use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataHandlerWriter;
-use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
-use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequestContext;
-use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\ResponseContent;
-
-/**
- * Test case for frontend requests without having site handling configured
- */
-class PlainRequestTest extends AbstractTestCase
-{
-    /**
-     * @var string
-     */
-    private $siteTitle = 'A Company that Manufactures Everything Inc';
-
-    /**
-     * @var InternalRequestContext
-     */
-    private $internalRequestContext;
-
-    public static function setUpBeforeClass(): void
-    {
-        parent::setUpBeforeClass();
-        static::initializeDatabaseSnapshot();
-    }
-
-    public static function tearDownAfterClass(): void
-    {
-        static::destroyDatabaseSnapshot();
-        parent::tearDownAfterClass();
-    }
-
-    protected function setUp(): void
-    {
-        parent::setUp();
-
-        // these settings are forwarded to the frontend sub-request as well
-        $this->internalRequestContext = (new InternalRequestContext())
-            ->withGlobalSettings(['TYPO3_CONF_VARS' => static::TYPO3_CONF_VARS]);
-
-        $this->withDatabaseSnapshot(function () {
-            $this->setUpDatabase();
-        });
-    }
-
-    protected function setUpDatabase()
-    {
-        $backendUser = $this->setUpBackendUserFromFixture(1);
-        Bootstrap::initializeLanguageObject();
-
-        $scenarioFile = __DIR__ . '/Fixtures/PlainScenario.yaml';
-        $factory = DataHandlerFactory::fromYamlFile($scenarioFile);
-        $writer = DataHandlerWriter::withBackendUser($backendUser);
-        $writer->invokeFactory($factory);
-        static::failIfArrayIsNotEmpty(
-            $writer->getErrors()
-        );
-
-        $this->setUpFrontendRootPage(
-            1000,
-            [
-                'typo3/sysext/core/Tests/Functional/Fixtures/Frontend/JsonRenderer.typoscript',
-                'typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/JsonRenderer.typoscript',
-            ],
-            [
-                'title' => 'ACME Root',
-                'sitetitle' => $this->siteTitle,
-            ]
-        );
-        $this->setUpFrontendRootPage(
-            3000,
-            [
-                'typo3/sysext/core/Tests/Functional/Fixtures/Frontend/JsonRenderer.typoscript',
-                'typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/JsonRenderer.typoscript',
-            ],
-            [
-                'title' => 'ACME Archive',
-                'sitetitle' => $this->siteTitle,
-            ]
-        );
-    }
-
-    protected function tearDown(): void
-    {
-        unset($this->internalRequestContext);
-        parent::tearDown();
-    }
-
-    /**
-     * @return array
-     */
-    public function shortcutsAreRedirectedDataProvider(): array
-    {
-        $domainPaths = [
-            '/',
-            'https://localhost/',
-            'https://website.local/',
-        ];
-
-        $queries = [
-            '?',
-            '?id=1000',
-        ];
-
-        return $this->wrapInArray(
-            $this->keysFromValues(
-                $this->meltStrings([$domainPaths, $queries])
-            )
-        );
-    }
-
-    /**
-     * @param string $uri
-     *
-     * @test
-     * @dataProvider shortcutsAreRedirectedDataProvider
-     */
-    public function shortcutsAreRedirectedToFirstSubPage(string $uri)
-    {
-        $expectedStatusCode = 307;
-        $expectedHeaders = ['location' => ['index.php?id=1100']];
-
-        $response = $this->executeFrontendRequest(
-            new InternalRequest($uri),
-            $this->internalRequestContext
-        );
-        static::assertSame($expectedStatusCode, $response->getStatusCode());
-        static::assertSame($expectedHeaders, $response->getHeaders());
-    }
-
-    /**
-     * @param string $uri
-     *
-     * @test
-     * @dataProvider shortcutsAreRedirectedDataProvider
-     */
-    public function shortcutsAreRedirectedAndRenderFirstSubPage(string $uri)
-    {
-        $expectedStatusCode = 200;
-        $expectedPageTitle = 'EN: Welcome';
-
-        $response = $this->executeFrontendRequest(
-            new InternalRequest($uri),
-            $this->internalRequestContext,
-            true
-        );
-        $responseStructure = ResponseContent::fromString(
-            (string)$response->getBody()
-        );
-
-        static::assertSame(
-            $expectedStatusCode,
-            $response->getStatusCode()
-        );
-        static::assertSame(
-            $this->siteTitle,
-            $responseStructure->getScopePath('template/sitetitle')
-        );
-        static::assertSame(
-            $expectedPageTitle,
-            $responseStructure->getScopePath('page/title')
-        );
-    }
-
-    /**
-     * @return array
-     */
-    public function pageIsRenderedDataProvider(): array
-    {
-        $domainPaths = [
-            '/',
-            'https://localhost/',
-            'https://website.local/',
-        ];
-
-        $queries = [
-            '?id=1100',
-        ];
-
-        $languageQueries = [
-            '',
-            '&L=0',
-            '&L=1',
-            '&L=2',
-        ];
-
-        return array_map(
-            function (string $uri) {
-                if (strpos($uri, '&L=1') !== false) {
-                    $expectedPageTitle = 'FR: Welcome';
-                } elseif (strpos($uri, '&L=2') !== false) {
-                    $expectedPageTitle = 'FR-CA: Welcome';
-                } else {
-                    $expectedPageTitle = 'EN: Welcome';
-                }
-                return [$uri, $expectedPageTitle];
-            },
-            $this->keysFromValues(
-                $this->meltStrings([$domainPaths, $queries, $languageQueries])
-            )
-        );
-    }
-
-    /**
-     * @param string $uri
-     * @param string $expectedPageTitle
-     *
-     * @test
-     * @dataProvider pageIsRenderedDataProvider
-     */
-    public function pageIsRendered(string $uri, string $expectedPageTitle)
-    {
-        $response = $this->executeFrontendRequest(
-            new InternalRequest($uri),
-            $this->internalRequestContext
-        );
-        $responseStructure = ResponseContent::fromString(
-            (string)$response->getBody()
-        );
-
-        static::assertSame(
-            200,
-            $response->getStatusCode()
-        );
-        static::assertSame(
-            $this->siteTitle,
-            $responseStructure->getScopePath('template/sitetitle')
-        );
-        static::assertSame(
-            $expectedPageTitle,
-            $responseStructure->getScopePath('page/title')
-        );
-    }
-
-    /**
-     * @return array
-     */
-    public function pageIsRenderedWithDomainsDataProvider(): array
-    {
-        $instructions = [
-            ['https://archive.acme.com/?id=3100', 'EN: Statistics'],
-            ['https://archive.acme.com/?id=3110', 'EN: Markets'],
-            ['https://archive.acme.com/?id=3120', 'EN: Products'],
-            ['https://archive.acme.com/?id=3130', 'EN: Partners'],
-        ];
-
-        return $this->keysFromTemplate($instructions, '%1$s');
-    }
-
-    /**
-     * @param string $uri
-     * @param string $expectedPageTitle
-     *
-     * @test
-     * @dataProvider pageIsRenderedWithDomainsDataProvider
-     */
-    public function pageIsRenderedWithDomains(string $uri, string $expectedPageTitle)
-    {
-        $response = $this->executeFrontendRequest(
-            new InternalRequest($uri),
-            $this->internalRequestContext
-        );
-        $responseStructure = ResponseContent::fromString(
-            (string)$response->getBody()
-        );
-
-        static::assertSame(
-            200,
-            $response->getStatusCode()
-        );
-        static::assertSame(
-            $this->siteTitle,
-            $responseStructure->getScopePath('template/sitetitle')
-        );
-        static::assertSame(
-            $expectedPageTitle,
-            $responseStructure->getScopePath('page/title')
-        );
-    }
-
-    /**
-     * @return array
-     */
-    public function restrictedPageIsRenderedDataProvider(): array
-    {
-        $instructions = [
-            // frontend user 1
-            ['https://website.local/?id=1510', 1, 'Whitepapers'],
-            ['https://website.local/?id=1511', 1, 'Products'],
-            ['https://website.local/?id=1512', 1, 'Solutions'],
-            // frontend user 2
-            ['https://website.local/?id=1510', 2, 'Whitepapers'],
-            ['https://website.local/?id=1511', 2, 'Products'],
-            ['https://website.local/?id=1515', 2, 'Research'],
-            ['https://website.local/?id=1520', 2, 'Forecasts'],
-            ['https://website.local/?id=1521', 2, 'Current Year'],
-            // frontend user 3
-            ['https://website.local/?id=1510', 3, 'Whitepapers'],
-            ['https://website.local/?id=1511', 3, 'Products'],
-            ['https://website.local/?id=1512', 3, 'Solutions'],
-            ['https://website.local/?id=1515', 3, 'Research'],
-            ['https://website.local/?id=1520', 3, 'Forecasts'],
-            ['https://website.local/?id=1521', 3, 'Current Year'],
-        ];
-
-        return $this->keysFromTemplate($instructions, '%1$s (user:%2$s)');
-    }
-
-    /**
-     * @param string $uri
-     * @param int $frontendUserId
-     * @param string $expectedPageTitle
-     *
-     * @test
-     * @dataProvider restrictedPageIsRenderedDataProvider
-     */
-    public function restrictedPageIsRendered(string $uri, int $frontendUserId, string $expectedPageTitle)
-    {
-        $response = $this->executeFrontendRequest(
-            new InternalRequest($uri),
-            $this->internalRequestContext
-                ->withFrontendUserId($frontendUserId)
-        );
-        $responseStructure = ResponseContent::fromString(
-            (string)$response->getBody()
-        );
-
-        static::assertSame(
-            200,
-            $response->getStatusCode()
-        );
-        static::assertSame(
-            $this->siteTitle,
-            $responseStructure->getScopePath('template/sitetitle')
-        );
-        static::assertSame(
-            $expectedPageTitle,
-            $responseStructure->getScopePath('page/title')
-        );
-    }
-
-    /**
-     * @return array
-     */
-    public function restrictedPageSendsForbiddenResponseWithUnauthorizedVisitorDataProvider(): array
-    {
-        $instructions = [
-            // no frontend user given
-            ['https://website.local/?id=1510', 0],
-            ['https://website.local/?id=1511', 0],
-            ['https://website.local/?id=1512', 0],
-            ['https://website.local/?id=1515', 0],
-            ['https://website.local/?id=1520', 0],
-            ['https://website.local/?id=1521', 0],
-            // frontend user 1
-            ['https://website.local/?id=1515', 1],
-            ['https://website.local/?id=1520', 1],
-            ['https://website.local/?id=1521', 1],
-            // frontend user 2
-            ['https://website.local/?id=1512', 2],
-        ];
-
-        return $this->keysFromTemplate($instructions, '%1$s (user:%2$s)');
-    }
-
-    /**
-     * @param string $uri
-     * @param int $frontendUserId
-     *
-     * @test
-     * @dataProvider restrictedPageSendsForbiddenResponseWithUnauthorizedVisitorDataProvider
-     */
-    public function restrictedPageSendsForbiddenResponseWithUnauthorizedVisitorUsingDefaultErrorHandling(string $uri, int $frontendUserId)
-    {
-        $response = $this->executeFrontendRequest(
-            new InternalRequest($uri),
-            $this->internalRequestContext
-                ->withFrontendUserId($frontendUserId)
-        );
-
-        static::assertSame(
-            403,
-            $response->getStatusCode()
-        );
-        static::assertThat(
-            (string)$response->getBody(),
-            static::logicalOr(
-                static::stringContains('Reason: ID was not an accessible page'),
-                static::stringContains('Reason: Subsection was found and not accessible')
-            )
-        );
-    }
-
-    /**
-     * @param string $uri
-     * @param int $frontendUserId
-     *
-     * @test
-     * @dataProvider restrictedPageSendsForbiddenResponseWithUnauthorizedVisitorDataProvider
-     */
-    public function restrictedPageSendsForbiddenResponseWithUnauthorizedVisitorUsingCustomErrorHandling(string $uri, int $frontendUserId)
-    {
-        $response = $this->executeFrontendRequest(
-            new InternalRequest($uri),
-            $this->internalRequestContext
-                ->withFrontendUserId($frontendUserId)
-                ->withMergedGlobalSettings([
-                    'TYPO3_CONF_VARS' => [
-                        'FE' => [
-                            'pageNotFound_handling' => 'READFILE:typo3/sysext/core/Tests/Functional/Fixtures/Frontend/PageError.txt',
-                        ]
-                    ]
-                ])
-        );
-
-        static::assertSame(
-            403,
-            $response->getStatusCode()
-        );
-        static::assertThat(
-            (string)$response->getBody(),
-            static::logicalOr(
-                static::stringContains('reason: ID was not an accessible page'),
-                static::stringContains('reason: Subsection was found and not accessible')
-            )
-        );
-    }
-
-    /**
-     * @return array
-     */
-    public function pageRenderingStopsWithInvalidCacheHashDataProvider(): array
-    {
-        $domainPaths = [
-            '/',
-            'https://localhost/',
-            'https://website.local/',
-        ];
-
-        $queries = [
-            '?',
-            '?id=1000',
-            '?id=1100',
-        ];
-
-        $customQueries = [
-            '&testing[value]=1',
-            '&testing[value]=1&cHash=',
-            '&testing[value]=1&cHash=WRONG',
-        ];
-
-        return $this->wrapInArray(
-            $this->keysFromValues(
-                $this->meltStrings([$domainPaths, $queries, $customQueries])
-            )
-        );
-    }
-
-    /**
-     * @param string $uri
-     *
-     * @test
-     * @dataProvider pageRenderingStopsWithInvalidCacheHashDataProvider
-     * @todo In TYPO3 v8 this seemed to be rendered, without throwing that exception
-     */
-    public function pageRequestThrowsExceptionWithInvalidCacheHash(string $uri)
-    {
-        $this->expectExceptionCode(1518472189);
-        $this->expectException(PageNotFoundException::class);
-
-        $this->executeFrontendRequest(
-            new InternalRequest($uri),
-            $this->internalRequestContext
-        );
-    }
-
-    /**
-     * @param string $uri
-     *
-     * @test
-     * @dataProvider pageRenderingStopsWithInvalidCacheHashDataProvider
-     */
-    public function pageRequestSendsNotFoundResponseWithInvalidCacheHash(string $uri)
-    {
-        $response = $this->executeFrontendRequest(
-            new InternalRequest($uri),
-            $this->internalRequestContext->withMergedGlobalSettings([
-                'TYPO3_CONF_VARS' => [
-                    'FE' => [
-                        'pageNotFound_handling' => 'READFILE:typo3/sysext/core/Tests/Functional/Fixtures/Frontend/PageError.txt',
-                    ]
-                ]
-            ])
-        );
-
-        static::assertSame(
-            404,
-            $response->getStatusCode()
-        );
-        static::assertThat(
-            (string)$response->getBody(),
-            static::logicalOr(
-                static::stringContains('reason: Request parameters could not be validated (&amp;cHash empty)'),
-                static::stringContains('reason: Request parameters could not be validated (&amp;cHash comparison failed)')
-            )
-        );
-    }
-
-    /**
-     * @return array
-     */
-    public function pageIsRenderedWithValidCacheHashDataProvider(): array
-    {
-        $domainPaths = [
-            '/',
-            'https://localhost/',
-            'https://website.local/',
-        ];
-
-        // cHash has been calculated with encryption key set to
-        // '4408d27a916d51e624b69af3554f516dbab61037a9f7b9fd6f81b4d3bedeccb6'
-        $queries = [
-            // @todo Currently fails since cHash is verified after(!) redirect to page 1100
-            // '?&cHash=7d1f13fa91159dac7feb3c824936b39d&id=1000',
-            '?&cHash=f42b850e435f0cedd366f5db749fc1af&id=1100',
-        ];
-
-        $customQueries = [
-            '&testing[value]=1',
-        ];
-
-        $dataSet = $this->wrapInArray(
-            $this->keysFromValues(
-                $this->meltStrings([$domainPaths, $queries, $customQueries])
-            )
-        );
-
-        return $dataSet;
-    }
-
-    /**
-     * @param string $uri
-     *
-     * @test
-     * @dataProvider pageIsRenderedWithValidCacheHashDataProvider
-     */
-    public function pageIsRenderedWithValidCacheHash($uri)
-    {
-        $response = $this->executeFrontendRequest(
-            new InternalRequest($uri),
-            $this->internalRequestContext
-        );
-        $responseStructure = ResponseContent::fromString(
-            (string)$response->getBody()
-        );
-        static::assertSame(
-            '1',
-            $responseStructure->getScopePath('getpost/testing.value')
-        );
-    }
-}
index ddb7426..e1d41cf 100644 (file)
@@ -575,22 +575,22 @@ class SlugLinkGeneratorTest extends AbstractTestCase
             ['https://acme.us/', 1100, 1100, false, 1, '/welcome-modified'],
             ['https://acme.us/', 1100, 1100, true, 1, '/welcome-modified'],
             ['https://acme.us/', 1100, 1100, false, 0, '/welcome'],
-            ['https://acme.us/', 1100, 1100, true, 0, '/index.php?id={targetPageId}'], // @todo this is wrong, link should be empty
+            ['https://acme.us/', 1100, 1100, true, 0, ''], // @todo link is empty, but should create a link
             // acme.com -> acme.com (same site): link to new page
             ['https://acme.us/', 1100, 1950, false, 1, '/bye'],
             ['https://acme.us/', 1100, 1950, true, 1, '/bye'],
             ['https://acme.us/', 1100, 1950, false, 0, ''],
-            ['https://acme.us/', 1100, 1950, true, 0, '/index.php?id={targetPageId}'], // @todo this is wrong, link should be empty
+            ['https://acme.us/', 1100, 1950, true, 0, ''], // @todo link is empty, but should create a link
             // blog.acme.com -> acme.com (different site): link to changed page
             ['https://blog.acme.com/', 2100, 1100, true, 1, 'https://acme.us/welcome-modified'],
             ['https://blog.acme.com/', 2100, 1100, false, 1, 'https://acme.us/welcome-modified'],
             ['https://blog.acme.com/', 2100, 1100, false, 0, 'https://acme.us/welcome'],
-            ['https://blog.acme.com/', 2100, 1100, true, 0, '/index.php?id=7131'], // @todo this is wrong, link should be empty
+            ['https://blog.acme.com/', 2100, 1100, true, 0, ''], // @todo link is empty, but should create a link
             // blog.acme.com -> acme.com (different site): link to new page
             ['https://blog.acme.com/', 2100, 1950, false, 1, 'https://acme.us/bye'],
             ['https://blog.acme.com/', 2100, 1950, true, 1, 'https://acme.us/bye'],
             ['https://blog.acme.com/', 2100, 1950, false, 0, ''],
-            ['https://blog.acme.com/', 2100, 1950, true, 0, '/index.php?id={targetPageId}'], // @todo this is wrong, link should be empty
+            ['https://blog.acme.com/', 2100, 1950, true, 0, ''], // @todo link is empty, but should create a link
         ];
 
         return $this->keysFromTemplate(
index a2d9bc3..42b7650 100644 (file)
@@ -235,28 +235,25 @@ class SlugSiteRequestTest extends AbstractTestCase
             $this->buildErrorHandlingConfiguration('Fluid', [404])
         );
 
-        $expectedStatusCode = 307;
-        $expectedHeaders = ['location' => ['https://website.local/en-en/welcome']];
-
         $uri = 'https://website.other/any/invalid/slug';
         $response = $this->executeFrontendRequest(
             new InternalRequest($uri),
-            $this->internalRequestContext
+            $this->internalRequestContext->withMergedGlobalSettings([
+                'TYPO3_CONF_VARS' => [
+                    'FE' => [
+                        'pageNotFound_handling' => 'READFILE:typo3/sysext/core/Tests/Functional/Fixtures/Frontend/PageError.txt',
+                    ]
+                ]
+            ])
         );
-
         static::assertSame(
-            $expectedStatusCode,
+            404,
             $response->getStatusCode()
         );
-        static::assertSame(
-            $expectedHeaders,
-            $response->getHeaders()
+        static::assertThat(
+            (string)$response->getBody(),
+            static::stringContains('No site configuration found')
         );
-        // @todo Expected page not found response (404) instead
-        // static::assertContains(
-        //     'message: The requested page does not exist',
-        //    (string)$response->getBody()
-        // );
     }
 
     /**
index 54275ba..db26f8b 100644 (file)
@@ -122,7 +122,7 @@ class TypoScriptFrontendControllerTest extends UnitTestCase
     {
         $string = $this->getUniqueId();
         $this->subject->page = [];
-        $this->subject->settingLanguage();
+        $this->subject->_call('setOutputLanguage');
         $this->assertEquals($string, $this->subject->sL($string));
     }
 
index 17c0187..f2d6c8e 100644 (file)
@@ -22,7 +22,6 @@ use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer;
 use TYPO3\CMS\Core\Exception\Page\RootLineException;
 use TYPO3\CMS\Core\Exception\SiteNotFoundException;
 use TYPO3\CMS\Core\Html\HtmlParser;
-use TYPO3\CMS\Core\Site\PseudoSiteFinder;
 use TYPO3\CMS\Core\Site\SiteFinder;
 use TYPO3\CMS\Core\Type\File\ImageInfo;
 use TYPO3\CMS\Core\TypoScript\TypoScriptService;
@@ -1442,12 +1441,7 @@ class SearchController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControlle
                 ->getBase()
                 ->getHost();
         } catch (SiteNotFoundException $e) {
-            $pseudoSiteFinder = GeneralUtility::makeInstance(PseudoSiteFinder::class);
-            try {
-                $domain = trim((string)$pseudoSiteFinder->getSiteByPageId($id)->getBase(), '/');
-            } catch (SiteNotFoundException $e) {
-                // site was not found, we return an empty string as default
-            }
+            // site was not found, we return an empty string as default
         }
         return $domain;
     }
index 09e9a08..99a4196 100644 (file)
@@ -19,7 +19,6 @@ use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Backend\View\PageLayoutView;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\Localization\LanguageService;
-use TYPO3\CMS\Core\Site\Entity\PseudoSite;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -175,13 +174,6 @@ class PageInformationController
         foreach ($modTSconfig as $key => $item) {
             $fieldList = str_replace('###ALL_TABLES###', $this->cleanTableNames(), $item['fields']);
             $fields = GeneralUtility::trimExplode(',', $fieldList, true);
-            if ((int)$key === 0) {
-                // If "Basic settings" is rendered, hide the slug field on PseudoSites.
-                $site = $request->getAttribute('site');
-                if ($site instanceof PseudoSite) {
-                    $fields = array_diff($fields, ['slug']);
-                }
-            }
             $key = trim($key, '.');
             $this->fieldConfiguration[$key] = [
                 'label' => $item['label'] ? $this->getLanguageService()->sL($item['label']) : $key,
index 9dc86a2..2519b50 100644 (file)
@@ -246,6 +246,11 @@ return [
             'Breaking-87193-DeprecatedFunctionalityRemoved.rst',
         ],
     ],
+    '$GLOBALS[\'TYPO3_CONF_VARS\'][\'SC_OPTIONS\'][\'t3lib/class.t3lib_tstemplate.php\'][\'linkData-PostProc\']' => [
+        'restFiles' => [
+            'Breaking-87193-DeprecatedFunctionalityRemoved.rst',
+        ],
+    ],
     '$GLOBALS[\'TCA\'][\'sys_history\']' => [
         'restFiles' => [
             'Breaking-87936-TCAForSysHistoryRemoved.rst',
index 532e235..65e885c 100644 (file)
@@ -1271,4 +1271,14 @@ return [
             'Deprecation-87882-FileRelatedControllersMovedToEXTfilelist.rst'
         ],
     ],
+    'TYPO3\CMS\Core\Site\Entity\PseudoSite' => [
+        'restFiles' => [
+            'Breaking-87193-DeprecatedFunctionalityRemoved.rst',
+        ],
+    ],
+    'TYPO3\CMS\Core\Site\PseudoSiteFinder' => [
+        'restFiles' => [
+            'Breaking-87193-DeprecatedFunctionalityRemoved.rst',
+        ],
+    ],
 ];
index 3e65200..9538cc7 100644 (file)
@@ -875,4 +875,11 @@ return [
             'Deprecation-87894-GeneralUtilityidnaEncode.rst',
         ],
     ],
+    'TYPO3\CMS\Core\Context\LanguageAspectFactory::createFromTypoScript' => [
+        'numberOfMandatoryArguments' => 1,
+        'maximumNumberOfArguments' => 1,
+        'restFiles' => [
+            'Breaking-87193-DeprecatedFunctionalityRemoved.rst',
+        ],
+    ],
 ];
index 1a82f87..5d4b0b8 100644 (file)
@@ -480,21 +480,6 @@ config.inlineStyle2TempFile = 1]]></description>
                        <default><![CDATA[
 ]]></default>
                </property>
-               <property name="language" type="string">
-                       <description><![CDATA[Language key. See stdWrap.lang for more information.
-Select between:
-English  (default) = [empty]
-Danish = dk
-German = de
-Norwegian = no
-Italian = it
-etc...
-
-Value must correspond with the key used for backend system language if there is one. Look at the translation page on TYPO3.org for the official 2-byte key for a given language. Notice that selecting the official key is important if you want labels in the correct language from "locallang" files.
-If the language you need is not yet a system language in TYPO3 you can use an artificial string of your choice and provide values for it via the TypoScript template where the property "_LOCAL_LANG" for most plugins will provide a way to override/add values for labels. The keys to use must be looked up in the locallang-file used by the plugin of course.]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
                <property name="language_alt" type="string">
                        <description><![CDATA[If "config.language" (above) is used, this can be set to another language key which will be used for labels if a label was not found for the main language. For instance a brazil portuguese website might specify "pt" as alternative language which means the portuguese label will be shown if none was available in the main language, brazil portuguese. This feature makes sense if one language is incompletely translated and close to another language.]]></description>
                        <default><![CDATA[
@@ -520,17 +505,6 @@ Same as above, but "&L=[L-value]" will only be added if the current value is 1,
                        <default><![CDATA[
 ]]></default>
                </property>
-               <property name="locale_all" type="string">
-                       <description><![CDATA[PHP: setlocale("LC_ALL", [value]);
-value-examples: deutsch, de_DE, danish, portuguese, spanish, french, norwegian, italian. See www.php.net for other value. Also on linux, look at /usr/share/locale/
-
-Example:
-This will render dates in danish made with stdWrap/strftime:
-locale_all = danish
-locale_all = da_DK]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
                <property name="message_preview" type="string">
                        <description><![CDATA[Alternative message in HTML that appears when the preview function is active!]]></description>
                        <default><![CDATA[
@@ -606,13 +580,6 @@ pageRendererTemplateFile = fileadmin/test_pagerender.html
                        <description><![CDATA[The signs which should be printed in the title tag between the website name and the page title.]]></description>
                        <default><![CDATA[:]]></default>
                </property>
-               <property name="prefixLocalAnchors" type="string">
-                       <description><![CDATA[If set to one of the keywords, the content will have all local anchors in links prefixed with the path of the script. Basically this means that <a href="#"> will be transformed to <a href="path/path/script?params#">. This procedure is necessary if the <base> tag is set in the script (eg. if "realurl" extension is used to produce Speaking URLs).
-
-Keywords are the same as for "xhtml_cleaning", see above.]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
                <property name="removeDefaultCss" type="boolean">
                        <description><![CDATA[Remove CSS generated by _CSS_DEFAULT_STYLE configuration of extensions.]]></description>
                        <default><![CDATA[false]]></default>
@@ -759,56 +726,6 @@ If set, the words MUST be surrounded by whitespace in order to be marked up.]]><
                        <default><![CDATA[
 ]]></default>
                </property>
-               <property name="sys_language_mode" type="string">
-                       <description><![CDATA[Setting various modes of handling localization.
-The syntax is "[keyword] ; [value]".
-
-Possible keywords are:
-
-[default] - The system will look for a translation of the page (from "Alternative Page Language" table) and if it is not found it will fall back to the default language and display that.
-
-content_fallback - [ Recommended ] The system will always operate with the selected language even if the page is not translated with a page overlay record. This will keep menus etc. translated. However, the content on the page can still fall back to another language, defined by the value of this keyword, eg. "content_fallback ; 1,0" to fall back to the content of sys_language_uid 1 and if that is not present either, to default (0)
-
-strict - The system will report an error if the requested translation does not exist. Basically this means that all pages with gray background in the Web>Info / Localization overview module will fail (they would otherwise fall back to default language in one or another way)
-
-ignore - The system will stay with the selected language even if the page is not translated and there's no content available in this language, so you can handle that situation on your own then.]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
-               <property name="sys_language_overlay" type="string">
-                       <description><![CDATA[boolean / keyword
-                       If set, records from certain tables selected by the CONTENT cObject using the "languageField" setting will select the default language (0) instead of any language set by sys_language_uid / sys_language_mode. In addition the system will look for a translation of the selected record and overlay configured fields.
-The requirements for this is that the table is configured with "languageField" and "transOrigPointerField" in the [ctrl] section of $TCA. Also, exclusion of certain fields can be done with the "l10n_mode" directive in the field-configuration of $TCA.
-
-For backend administration this requires that you configure the "Web>Page" module to display content elements accordingly; That each default element is shown and next to it any translation found. This configuration can be done with Page TSconfig for a section of the website using the object path "mod.web_layout.defLangBinding = 1".
-
-Keyword:
-hideNonTranslated : If this keyword is used a record that has no translation will not be shown. The default is that records with no translation will show up in the default language.]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
-               <property name="sys_language_uid" type="int">
-                       <description><![CDATA[This value points to the uid of a record from the "sys_language" table and if set, this means that various parts of the frontend display code will select records which are assigned to this language. See ->SELECT
-
-Internally, the value is depending on whether a Alternative Page Language record can be found with that language. If not, the value will default to zero (default language) except if "sys_language_mode" is set to a value like "content_fallback".]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
-               <property name="typolinkEnableLinksAcrossDomains" type="boolean">
-                       <description><![CDATA[This option enables to create links across domains using current domain's linking scheme.
-
-If this option is not set, then all cross-domain links will be generated as
-
-"http://domain.tld/index.php?id=12345" (where 12345 is page id). Setting this option requires that domains, where pages are linked, have the same configuration for:
-
-- linking scheme (i.e. all use RealURL or CoolURI but not any mixture)
-- all domains have identical localization settings (config.sys_language_XXX directives)
-- all domains have the same set of languages defined
-
-Disclaimer: it must be understood that while link is generated to another domain, it is still generated in the context of current domain. No side effects are known at the time of writing of this documentation but they may exist. If any side effects are found, this documentation will be updated to include them.]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
                <property name="typolinkLinkAccessRestrictedPages" type="string">
                        <description><![CDATA[integer (page id) / keyword "NONE"
                        If set, typolinks pointing to access restricted pages will still link to the page even though the page cannot be accessed. If the value of this setting is an integer it will be interpreted as a page id to which the link will be directed.
@@ -854,35 +771,6 @@ same as config.doctype if set to a keyword]]></description>
                        <default><![CDATA[
 ]]></default>
                </property>
-               <property name="xhtml_cleaning" type="string">
-                       <description><![CDATA[Tries to clean up the output to make it XHTML compliant and a bit more. THIS IS NOT COMPLETE YET, but a "pilot" to see if it makes sense anyways. For now this is what is done:
-
-What it does at this point:
-- All tags (img,br,hr) is ended with "/>" - others?
-- Lowercase for elements and attributes
-- All attributes in quotes
-- Add "alt" attribute to img-tags if it's not there already.
-
-What it does NOT do (yet) according to XHTML specs.:
-- Wellformedness: Nesting is NOT checked
-- name/id attribute issue is not observed at this point.
-- Certain nesting of elements not allowed. Most interesting, <PRE> cannot contain img, big,small,sub,sup ...
-- Wrapping scripts and style element contents in CDATA - or alternatively they should have entitites converted.
-- Setting charsets may put some special requirements on both XML declaration/ meta-http-equiv. (C.9)
-- UTF-8 encoding is in fact expected by XML!!
-- stylesheet element and attribute names are NOT converted to lowercase
-- ampersands (and entities in general I think) MUST be converted to an entity reference! (&amps;). This may mean further conversion of non-tag content before output to page. May be related to the charset issue as a whole.
-- Minimized values not allowed: Must do this: selected="selected"
-
-Please see the class \TYPO3\CMS\Core\Html\HtmlParser for details.
-You can enable this function by the following values:
-
-all = the content is always processed before it may be stored in cache.
-cached = only if the page is put into the cache,
-output = only the output code just before it's echoed out.]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
                <property name="xmlprologue" type="string">
                        <description><![CDATA[If empty (not set) then the default XML 1.0 prologue is set, when the doctype is set to a known keyword (eg xhtml_11):
 
@@ -2348,9 +2236,7 @@ Notice: Affects all sub menus as well. To set the value for each menu level indi
 The check is only carried out if a translation is requested ("config.sys_language_uid" is not zero).
 
 Keyword: "all"
-When set to "all" the same check is carried out but it will not look if "Hide page if no translation for current language exists" is set - it always reverts to default language if no translation is found.
-
-For these options to make sense, they should only be used when "config.sys_language_mode" is not set to "content_fallback".]]></description>
+When set to "all" the same check is carried out but it will not look if "Hide page if no translation for current language exists" is set - it always reverts to default language if no translation is found.]]></description>
                        <default><![CDATA[
 ]]></default>
                </property>
@@ -3258,11 +3144,6 @@ Default is to REMOVE all tags, which are not specifically assigned to be allowed
                        <default><![CDATA[
 ]]></default>
                </property>
-               <property name="xhtml_cleaning" type="boolean">
-                       <description><![CDATA[Cleans up the content for XHTML compliance. Still slightly experimental and supports only some clean up operations (like conversion tags and attributes to lower case).]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
        </type>
        <type id="HTMLparser_tags">
                <property name="allowedAttribs" type="string">
@@ -6243,12 +6124,6 @@ This is used create a link, which jumps from one page directly the section on an
                        <default><![CDATA[
 ]]></default>
                </property>
-               <property name="useCacheHash" type="boolean">
-                       <description><![CDATA[If set, the additionalParams list is exploded and calculated into a hashstring appended to the url, like "&cHash=ae83fd7s87". When the caching mechanism sees this value, it calculates the same value on the server based on incoming values in HTTP_GET_VARS, excluding id,type,no_cache,ftu,cHash,MP values. If the incoming cHash value matches the calculated value, the page may be cached based on this.
-The [SYS][encryptionKey] is included in the hash in order to make it unique for the server and non-predictable.]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
                <property name="userFunc" type="string">
                        <description><![CDATA[This passes the link-data compiled by the typolink function to a user-defined function for final manipulation.
 The $content variable passed to the user-function (first parameter) is an array with the keys "TYPE",  "TAG", "url", "targetParams" and "aTagParams".
index 097a807..6d70d76 100644 (file)
         'sword_standAlone': kw('sword_standAlone'),
         'sys_dmail': B,
         'sys_filemounts': B,
-        'sys_language_mode': kw('sys_language_mode'),
-        'sys_language_overlay': kw('sys_language_overlay'),
-        'sys_language_uid': kw('sys_language_uid'),
         'sys_note': B,
         'sys_template': B,
         'system': A,