From 1c530c51e7246bbd38cdaf2e1c8c17ccd2d42c04 Mon Sep 17 00:00:00 2001
From: Markus Klein <markus.klein@typo3.org>
Date: Tue, 18 Apr 2023 10:36:14 +0200
Subject: [PATCH] [BUGFIX] Restore correct context after redirect evaluation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Remove any modification done to Context by the
RedirectHandler/RedirectService in order to have a
proper rendering of FE in case no valid redirect
is found (circular).

Resolves: #100654
Releases: main, 11.5
Change-Id: I7fb0c1ac9619d7599151e57cbcacc916deee41c5
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/78722
Tested-by: core-ci <typo3@b13.com>
Tested-by: Stefan Bürk <stefan@buerk.tech>
Reviewed-by: Stefan Bürk <stefan@buerk.tech>
---
 typo3/sysext/core/Classes/Context/Context.php    | 12 ++++++++++++
 .../Classes/Service/RedirectService.php          | 16 ++++++++++++++++
 2 files changed, 28 insertions(+)

diff --git a/typo3/sysext/core/Classes/Context/Context.php b/typo3/sysext/core/Classes/Context/Context.php
index e4e03f2e6f1c..2d6e923a2676 100644
--- a/typo3/sysext/core/Classes/Context/Context.php
+++ b/typo3/sysext/core/Classes/Context/Context.php
@@ -164,4 +164,16 @@ class Context implements SingletonInterface
     {
         $this->aspects[$name] = $aspect;
     }
+
+    /**
+     * @internal Using this method is a sign of a technical debt. It is used by RedirectService,
+     *           but may vanish any time when this is fixed, and thus internal.
+     *           In general, Context aspects should never have to be unset.
+     *           When a middleware has to use this method, it is either located
+     *           at the wrong position in the chain, or has some other dependency issue.
+     */
+    public function unsetAspect(string $name): void
+    {
+        unset($this->aspects[$name]);
+    }
 }
diff --git a/typo3/sysext/redirects/Classes/Service/RedirectService.php b/typo3/sysext/redirects/Classes/Service/RedirectService.php
index 9e7659a72ba9..56c0d911470c 100644
--- a/typo3/sysext/redirects/Classes/Service/RedirectService.php
+++ b/typo3/sysext/redirects/Classes/Service/RedirectService.php
@@ -338,6 +338,7 @@ class RedirectService implements LoggerAwareInterface
                 $configuration['additionalParams'] = HttpUtility::buildQueryString($queryParams, '&');
             }
             $result = $linkBuilder->build($linkDetails, '', '', $configuration);
+            $this->cleanupTSFE();
             if (is_array($result)) {
                 return new Uri($result[0] ?? '');
             }
@@ -348,6 +349,7 @@ class RedirectService implements LoggerAwareInterface
         } catch (UnableToLinkException $e) {
             // This exception is also thrown by the DatabaseRecordTypolinkBuilder
             $url = $controller->cObj->lastTypoLinkUrl;
+            $this->cleanupTSFE();
             if (!empty($url)) {
                 return new Uri($url);
             }
@@ -431,4 +433,18 @@ class RedirectService implements LoggerAwareInterface
 
         return null;
     }
+
+    /**
+     * @todo: Needs to vanish. The existence of this method is a side-effect of the technical debt that
+     *        a TSFE has to be set up for link generation, see the comment on bootFrontendController()
+     *        for more details.
+     */
+    private function cleanupTSFE(): void
+    {
+        $context = GeneralUtility::makeInstance(Context::class);
+        $context->unsetAspect('language');
+        $context->unsetAspect('typoscript');
+        $context->unsetAspect('frontend.preview');
+        unset($GLOBALS['TSFE']);
+    }
 }
-- 
GitLab