From 2fc2326606e0d35467a89c917bb3b3b88acab3ef Mon Sep 17 00:00:00 2001 From: Benni Mack <benni@typo3.org> Date: Mon, 7 Nov 2022 17:31:17 +0100 Subject: [PATCH] [BUGFIX] Resolve shortcut to a different page in a localized page When a page translation of type=shortcut (doktype=4) contains a different value than its original page, the proper target URL is now resolved correctly upon link creation and link resolving in TSFE. This additionally fixes flaws in the behavior of first subpage in cases where the first subpage differs between languages. Resolves: #98565 Resolves: #98566 Resolves: #87815 Releases: main, 12.4 Change-Id: If44033affc1cde1f59d5ccab97d75cffd01d2ad0 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/79751 Tested-by: core-ci <typo3@b13.com> Tested-by: Benni Mack <benni@typo3.org> Reviewed-by: Benni Mack <benni@typo3.org> --- .../TypoScriptFrontendController.php | 1 + .../Classes/Typolink/PageLinkBuilder.php | 8 +++++ .../SiteHandling/Fixtures/SlugScenario.yaml | 2 ++ .../SiteHandling/SlugLinkGeneratorTest.php | 16 ++++++++- .../SiteHandling/SlugSiteRequestTest.php | 36 +++++++++++++------ 5 files changed, 51 insertions(+), 12 deletions(-) diff --git a/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php b/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php index 09b3b0a3ae67..37e64b4acc16 100644 --- a/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php +++ b/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php @@ -905,6 +905,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface // about languages - whether we took the correct shortcut or // whether a translation of the page overwrites the shortcut // target and we need to follow the new target + $this->settingLanguage($request); $this->originalShortcutPage = $this->page; $this->page = $this->sys_page->resolveShortcutPage($this->page, true); $this->id = (int)$this->page['uid']; diff --git a/typo3/sysext/frontend/Classes/Typolink/PageLinkBuilder.php b/typo3/sysext/frontend/Classes/Typolink/PageLinkBuilder.php index d2c82fb3f2bd..01a5b27ef27a 100644 --- a/typo3/sysext/frontend/Classes/Typolink/PageLinkBuilder.php +++ b/typo3/sysext/frontend/Classes/Typolink/PageLinkBuilder.php @@ -408,6 +408,14 @@ class PageLinkBuilder extends AbstractTypolinkBuilder if (empty($page) || !is_array($page)) { return []; } + + // If the page repository (= current page) does actually link to a different page + // It is needed to also resolve the page translation now, as it might have a different shortcut + // page + if (isset($configuration['language']) && $configuration['language'] !== 'current') { + $page = $pageRepository->getLanguageOverlay('pages', $page, new LanguageAspect($configuration['language'], $configuration['language'])); + } + $page = $this->resolveShortcutPage($page, $pageRepository, $disableGroupAccessCheck); $languageField = $GLOBALS['TCA']['pages']['ctrl']['languageField'] ?? null; diff --git a/typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/SlugScenario.yaml b/typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/SlugScenario.yaml index bb23dd44db59..3e392b91f552 100644 --- a/typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/SlugScenario.yaml +++ b/typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/SlugScenario.yaml @@ -141,6 +141,8 @@ entities: - self: {id: 2021, title: 'FEGroups Restricted', visitorGroups: 30, slug: '/sysfolder-restricted'} - self: {id: 2022, title: 'FEGroups Restricted', hidden: 1, visitorGroups: 30, slug: '/sysfolder-restricted-hidden'} - self: {id: 2030, title: 'Cross Site Shortcut', slug: '/cross-site-shortcut', type: *pageShortcut, shortcut: 2100} + languageVariants: + - self: {id: 2031, title: 'Shortcut to Research - shows a different page', language: 1, type: *pageShortcut, shortcut: 1400, slug: '/other-cross-site-shortcut', l10n_state: '{"starttime":"parent","endtime":"parent","nav_hide":"parent","url":"parent","lastUpdated":"parent","newUntil":"parent","no_search":"parent","shortcut":"custom","shortcut_mode":"parent","content_from_pid":"parent","author":"parent","author_email":"parent","media":"parent","og_image":"parent","twitter_image":"parent"}' } - self: {id: 2000, title: 'ACME Blog', type: *pageShortcut, shortcut: 'first', root: true, slug: '/'} children: - self: {id: 2100, title: 'Authors', slug: '/authors'} diff --git a/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugLinkGeneratorTest.php b/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugLinkGeneratorTest.php index 93b0891ee784..16418efd09cb 100644 --- a/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugLinkGeneratorTest.php +++ b/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugLinkGeneratorTest.php @@ -830,6 +830,20 @@ final class SlugLinkGeneratorTest extends AbstractTestCase ], ], ], + 'resolved shortcut in translation' => [ + 'https://acme.fr/', + 1100, + '2030', + [ + [ + 'title' => 'Shortcut to Research - shows a different page', + 'link' => '/acme-dans-votre-region', + 'active' => 0, + 'current' => 0, + ], + ], + ], + ]; } @@ -837,7 +851,7 @@ final class SlugLinkGeneratorTest extends AbstractTestCase * @test * @dataProvider hierarchicalMenuSetsActiveStateProperlyDataProvider */ - public function hierarchicalMenuSetsActiveStateProperly(string $hostPrefix, int $sourcePageId, string $menuPageIds, array $expectation): void + public function hierarchicalMenuSetsActiveStateProperly(string $hostPrefix, int $sourcePageId, string $menuPageIds, array $expectation, int $languageId = 0): void { $response = $this->executeFrontendSubRequest( (new InternalRequest($hostPrefix)) diff --git a/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugSiteRequestTest.php b/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugSiteRequestTest.php index 3770327c0b11..5bb44f007416 100644 --- a/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugSiteRequestTest.php +++ b/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugSiteRequestTest.php @@ -1220,16 +1220,22 @@ final class SlugSiteRequestTest extends AbstractTestCase ); } - public static function crossSiteShortcutsAreRedirectedDataProvider(): array + public static function crossSiteShortcutsAreRedirectedDataProvider(): \Generator { - return [ - 'shortcut is redirected' => [ - 'https://website.local/cross-site-shortcut', - 307, - [ - 'X-Redirect-By' => ['TYPO3 Shortcut/Mountpoint'], - 'location' => ['https://blog.local/authors'], - ], + yield 'shortcut is redirected' => [ + 'https://website.local/cross-site-shortcut', + 307, + [ + 'X-Redirect-By' => ['TYPO3 Shortcut/Mountpoint'], + 'location' => ['https://blog.local/authors'], + ], + ]; + yield 'shortcut of translated page is redirected to a different page than the original page' => [ + 'https://website.local/fr/other-cross-site-shortcut', + 307, + [ + 'X-Redirect-By' => ['TYPO3 Shortcut/Mountpoint'], + 'location' => ['https://website.local/fr/acme-dans-votre-region'], ], ]; } @@ -1242,11 +1248,19 @@ final class SlugSiteRequestTest extends AbstractTestCase { $this->writeSiteConfiguration( 'website-local', - $this->buildSiteConfiguration(1000, 'https://website.local/') + $this->buildSiteConfiguration(1000, 'https://website.local/'), + [ + $this->buildDefaultLanguageConfiguration('EN', '/'), + $this->buildLanguageConfiguration('FR', '/fr/', ['EN']), + ] ); $this->writeSiteConfiguration( 'blog-local', - $this->buildSiteConfiguration(2000, 'https://blog.local/') + $this->buildSiteConfiguration(2000, 'https://blog.local/'), + [ + $this->buildDefaultLanguageConfiguration('EN', '/'), + $this->buildLanguageConfiguration('FR', '/fr/', ['EN']), + ] ); $this->setUpFrontendRootPage( 2000, -- GitLab