[BUGFIX] Use proper typolink with clean TSFE for redirects 32/59032/6
authorBenni Mack <benni@typo3.org>
Tue, 4 Dec 2018 20:33:33 +0000 (21:33 +0100)
committerGeorg Ringer <georg.ringer@gmail.com>
Mon, 14 Jan 2019 07:18:12 +0000 (08:18 +0100)
Instead of re-using $GLOBALS['TSFE'] with
an already set $id and $type query
params, a new instance is created depending
on the given site.

Resolves: #87070
Releases: master, 9.5
Change-Id: I65b0b5c7c89db69c99600232927a00575c15d231
Reviewed-on: https://review.typo3.org/59032
Tested-by: TYPO3com <noreply@typo3.com>
Reviewed-by: Daniel Goerz <daniel.goerz@posteo.de>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
typo3/sysext/redirects/Classes/Http/Middleware/RedirectHandler.php
typo3/sysext/redirects/Classes/Service/RedirectService.php
typo3/sysext/redirects/Tests/Unit/Service/RedirectServiceTest.php

index 0846442..d59a08a 100644 (file)
@@ -57,7 +57,7 @@ class RedirectHandler implements MiddlewareInterface, LoggerAwareInterface
 
         // If the matched redirect is found, resolve it, and check further
         if (is_array($matchedRedirect)) {
-            $url = $redirectService->getTargetUrl($matchedRedirect, $request->getQueryParams());
+            $url = $redirectService->getTargetUrl($matchedRedirect, $request->getQueryParams(), $request->getAttribute('site', null));
             if ($url instanceof UriInterface) {
                 $this->logger->debug('Redirecting', ['record' => $matchedRedirect, 'uri' => $url]);
                 $response = $this->buildRedirectResponse($url, $matchedRedirect);
index 91420e6..7d6dbd9 100644 (file)
@@ -23,7 +23,10 @@ use TYPO3\CMS\Core\LinkHandling\LinkService;
 use TYPO3\CMS\Core\Resource\Exception\InvalidPathException;
 use TYPO3\CMS\Core\Resource\File;
 use TYPO3\CMS\Core\Resource\Folder;
+use TYPO3\CMS\Core\Site\Entity\SiteInterface;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\HttpUtility;
+use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
 use TYPO3\CMS\Frontend\Service\TypoLinkCodecService;
 use TYPO3\CMS\Frontend\Typolink\AbstractTypolinkBuilder;
 use TYPO3\CMS\Frontend\Typolink\UnableToLinkException;
@@ -159,9 +162,10 @@ class RedirectService implements LoggerAwareInterface
     /**
      * @param array $matchedRedirect
      * @param array $queryParams
-     * @return UriInterface|Uri|null
+     * @param SiteInterface|null $site
+     * @return UriInterface|null
      */
-    public function getTargetUrl(array $matchedRedirect, array $queryParams)
+    public function getTargetUrl(array $matchedRedirect, array $queryParams, ?SiteInterface $site = null): ?UriInterface
     {
         $this->logger->debug('Found a redirect to process', $matchedRedirect);
         $linkParameterParts = GeneralUtility::makeInstance(TypoLinkCodecService::class)->decode((string)$matchedRedirect['target']);
@@ -177,11 +181,10 @@ class RedirectService implements LoggerAwareInterface
             if ($matchedRedirect['keep_query_parameters']) {
                 $url = $this->addQueryParams($queryParams, $url);
             }
-        } else {
-            // If it's a record or page, then boot up TSFE
-            $url = $this->getUriFromCustomLinkDetails($linkDetails, $matchedRedirect);
+            return $url;
         }
-        return $url;
+        // If it's a record or page, then boot up TSFE and use typolink
+        return $this->getUriFromCustomLinkDetails($matchedRedirect, $site, $linkDetails, $queryParams);
     }
 
     /**
@@ -210,36 +213,39 @@ class RedirectService implements LoggerAwareInterface
     /**
      * Called when TypoScript/TSFE is available, so typolink is used to generate the URL
      *
-     * @param array $linkDetails
      * @param array $redirectRecord
+     * @param SiteInterface|null $site
+     * @param array $linkDetails
+     * @param array $queryParams
      * @return UriInterface|null
      */
-    protected function getUriFromCustomLinkDetails(array $linkDetails, array $redirectRecord)
+    protected function getUriFromCustomLinkDetails(array $redirectRecord, ?SiteInterface $site, array $linkDetails, array $queryParams): ?UriInterface
     {
         if (!isset($linkDetails['type'], $GLOBALS['TYPO3_CONF_VARS']['FE']['typolinkBuilder'][$linkDetails['type']])) {
             return null;
         }
-        $this->bootFrontendController();
+        $controller = $this->bootFrontendController($site, $queryParams);
         /** @var AbstractTypolinkBuilder $linkBuilder */
         $linkBuilder = GeneralUtility::makeInstance(
             $GLOBALS['TYPO3_CONF_VARS']['FE']['typolinkBuilder'][$linkDetails['type']],
-            $GLOBALS['TSFE']->cObj,
-            $GLOBALS['TSFE']
+            $controller->cObj,
+            $controller
         );
         try {
             $configuration = [
+                'parameter' => (string)$redirectRecord['target'],
                 'forceAbsoluteUrl' => true,
             ];
             if ($redirectRecord['force_https']) {
                 $configuration['forceAbsoluteUrl.']['scheme'] = 'https';
             }
             if ($redirectRecord['keep_query_parameters']) {
-                $configuration['useCacheHash'] = false;
-                $configuration['addQueryString'] = true;
+                $configuration['additionalParams'] = HttpUtility::buildQueryString($queryParams, '&');
             }
             list($url) = $linkBuilder->build($linkDetails, '', '', $configuration);
             return new Uri($url);
         } catch (UnableToLinkException $e) {
+            return null;
         }
     }
 
@@ -254,16 +260,29 @@ class RedirectService implements LoggerAwareInterface
      * - TSFE->config
      * - TSFE->cObj
      *
-     * So a link to a page could be generated.
+     * So a link to a page can be generated.
+     *
+     * @param SiteInterface|null $site
+     * @param array $queryParams
+     * @return TypoScriptFrontendController
      */
-    protected function bootFrontendController()
+    protected function bootFrontendController(?SiteInterface $site, array $queryParams): TypoScriptFrontendController
     {
         // disable page errors
         $GLOBALS['TYPO3_CONF_VARS']['FE']['pageUnavailable_handling'] = false;
-        $GLOBALS['TSFE']->fetch_the_id();
-        $GLOBALS['TSFE']->getConfigArray();
-        $GLOBALS['TSFE']->settingLanguage();
-        $GLOBALS['TSFE']->settingLocale();
-        $GLOBALS['TSFE']->newCObj();
+        $controller = GeneralUtility::makeInstance(
+            TypoScriptFrontendController::class,
+            null,
+            $site ? $site->getRootPageId() : $GLOBALS['TSFE']->id,
+            0
+        );
+        $controller->fe_user = $GLOBALS['TSFE']->fe_user ?? null;
+        $controller->fetch_the_id();
+        $controller->calculateLinkVars($queryParams);
+        $controller->getConfigArray();
+        $controller->settingLanguage();
+        $controller->settingLocale();
+        $controller->newCObj();
+        return $controller;
     }
 }
index a25e89a..622c07c 100644 (file)
@@ -23,6 +23,7 @@ use TYPO3\CMS\Core\LinkHandling\LinkService;
 use TYPO3\CMS\Core\Resource\Exception\InvalidPathException;
 use TYPO3\CMS\Core\Resource\File;
 use TYPO3\CMS\Core\Resource\Folder;
+use TYPO3\CMS\Core\Site\Entity\Site;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Redirects\Service\RedirectCacheService;
 use TYPO3\CMS\Redirects\Service\RedirectService;
@@ -413,7 +414,7 @@ class RedirectServiceTest extends UnitTestCase
         $linkServiceProphecy->resolve(Argument::any())->willThrow(new InvalidPathException('', 1516531195));
         GeneralUtility::setSingletonInstance(LinkService::class, $linkServiceProphecy->reveal());
 
-        $result = $this->redirectService->getTargetUrl(['target' => 'invalid'], []);
+        $result = $this->redirectService->getTargetUrl(['target' => 'invalid'], [], new Site('dummy', 13, []));
 
         self::assertNull($result);
     }
@@ -436,7 +437,7 @@ class RedirectServiceTest extends UnitTestCase
         $linkServiceProphecy->resolve($redirectTargetMatch['target'])->willReturn($linkDetails);
         GeneralUtility::setSingletonInstance(LinkService::class, $linkServiceProphecy->reveal());
 
-        $result = $this->redirectService->getTargetUrl($redirectTargetMatch, []);
+        $result = $this->redirectService->getTargetUrl($redirectTargetMatch, [], new Site('dummy', 13, []));
 
         $uri = new Uri('https://example.com/');
         self::assertEquals($uri, $result);
@@ -462,7 +463,7 @@ class RedirectServiceTest extends UnitTestCase
         $linkServiceProphecy->resolve($redirectTargetMatch['target'])->willReturn($linkDetails);
         GeneralUtility::setSingletonInstance(LinkService::class, $linkServiceProphecy->reveal());
 
-        $result = $this->redirectService->getTargetUrl($redirectTargetMatch, []);
+        $result = $this->redirectService->getTargetUrl($redirectTargetMatch, [], new Site('dummy', 13, []));
 
         $uri = new Uri('https://example.com/file.txt');
         self::assertEquals($uri, $result);
@@ -489,7 +490,7 @@ class RedirectServiceTest extends UnitTestCase
         $linkServiceProphecy->resolve($redirectTargetMatch['target'])->willReturn($linkDetails);
         GeneralUtility::setSingletonInstance(LinkService::class, $linkServiceProphecy->reveal());
 
-        $result = $this->redirectService->getTargetUrl($redirectTargetMatch, []);
+        $result = $this->redirectService->getTargetUrl($redirectTargetMatch, [], new Site('dummy', 13, []));
 
         $uri = new Uri('https://example.com/folder/');
         self::assertEquals($uri, $result);
@@ -513,7 +514,7 @@ class RedirectServiceTest extends UnitTestCase
         $linkServiceProphecy->resolve($redirectTargetMatch['target'])->willReturn($linkDetails);
         GeneralUtility::setSingletonInstance(LinkService::class, $linkServiceProphecy->reveal());
 
-        $result = $this->redirectService->getTargetUrl($redirectTargetMatch, []);
+        $result = $this->redirectService->getTargetUrl($redirectTargetMatch, [], new Site('dummy', 13, []));
 
         $uri = new Uri('https://example.com');
         self::assertEquals($uri, $result);
@@ -537,7 +538,7 @@ class RedirectServiceTest extends UnitTestCase
         $linkServiceProphecy->resolve($redirectTargetMatch['target'])->willReturn($linkDetails);
         GeneralUtility::setSingletonInstance(LinkService::class, $linkServiceProphecy->reveal());
 
-        $result = $this->redirectService->getTargetUrl($redirectTargetMatch, ['bar' => 3, 'baz' => 4]);
+        $result = $this->redirectService->getTargetUrl($redirectTargetMatch, ['bar' => 3, 'baz' => 4], new Site('dummy', 13, []));
 
         $uri = new Uri('https://example.com/?bar=2&baz=4&foo=1');
         self::assertEquals($uri, $result);