diff --git a/Classes/Event/Listener/AfterLinkIsGeneratedListener.php b/Classes/Event/Listener/AfterLinkIsGeneratedListener.php index be460c24..6879b177 100644 --- a/Classes/Event/Listener/AfterLinkIsGeneratedListener.php +++ b/Classes/Event/Listener/AfterLinkIsGeneratedListener.php @@ -14,8 +14,13 @@ use FriendsOfTYPO3\Headless\Utility\HeadlessFrontendUrlInterface; use TYPO3\CMS\Core\LinkHandling\LinkService; use TYPO3\CMS\Core\Site\Entity\NullSite; +use TYPO3\CMS\Core\Site\Entity\Site; use TYPO3\CMS\Frontend\Event\AfterLinkIsGeneratedEvent; +use function is_numeric; +use function is_string; +use function str_starts_with; + final class AfterLinkIsGeneratedListener { public function __construct( @@ -39,16 +44,26 @@ public function __invoke(AfterLinkIsGeneratedEvent $event): void $urlUtility = $this->urlUtility->withRequest($event->getContentObjectRenderer()->getRequest()); - if ($pageId) { + if (is_numeric($pageId) && ((int)$pageId) > 0) { $href = $urlUtility->getFrontendUrlForPage( $event->getLinkResult()->getUrl(), (int)$pageId ); } else { + /** + * @var Site $site + */ $site = $event->getContentObjectRenderer()->getRequest()->getAttribute('site'); + $key = 'frontendBase'; + + $sitemapConfig = $site->getConfiguration()['settings']['headless']['sitemap'] ?? []; + + if (is_string($pageId) && str_starts_with($pageId, 't3://page?uid=current&type=' . ($sitemapConfig['type'] ?? '1533906435'))) { + $key = $sitemapConfig['key'] ?? 'frontendApiProxy'; + } if (!$site instanceof NullSite) { - $href = $urlUtility->getFrontendUrlWithSite($event->getLinkResult()->getUrl(), $site); + $href = $urlUtility->getFrontendUrlWithSite($event->getLinkResult()->getUrl(), $site, $key); } } diff --git a/Classes/Utility/UrlUtility.php b/Classes/Utility/UrlUtility.php index 2552f186..ccaf2d32 100644 --- a/Classes/Utility/UrlUtility.php +++ b/Classes/Utility/UrlUtility.php @@ -26,6 +26,7 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; use function array_merge; +use function ltrim; use function rtrim; use function str_contains; @@ -96,11 +97,15 @@ public function getFrontendUrlWithSite($url, SiteInterface $site, string $return $frontendBase = GeneralUtility::makeInstance(Uri::class, $this->sanitizeBaseUrl($frontendBaseUrl)); $frontBase = $frontendBase->getHost(); + $frontExtraPath = $frontendBase->getPath(); $frontPort = $frontendBase->getPort(); $targetUri = new Uri($this->sanitizeBaseUrl($url)); if (str_contains($url, $base)) { $targetUri = $targetUri->withHost($frontBase); + if ($frontExtraPath) { + $targetUri = $targetUri->withPath($frontExtraPath . ($targetUri->getPath() !== '' ? '/' . ltrim($targetUri->getPath(), '/') : '')); + } } if ($port === $frontPort) { diff --git a/Tests/Unit/Event/Listener/AfterLinkIsGeneratedListenerTest.php b/Tests/Unit/Event/Listener/AfterLinkIsGeneratedListenerTest.php index 2f7c25b4..c3fc744d 100644 --- a/Tests/Unit/Event/Listener/AfterLinkIsGeneratedListenerTest.php +++ b/Tests/Unit/Event/Listener/AfterLinkIsGeneratedListenerTest.php @@ -33,7 +33,10 @@ public function test__construct() $resolver->evaluate(Argument::any())->willReturn(true); $siteFinder = $this->prophesize(SiteFinder::class); - $listener = new AfterLinkIsGeneratedListener(new UrlUtility(null, $resolver->reveal(), $siteFinder->reveal()), $this->prophesize(LinkService::class)->reveal()); + $listener = new AfterLinkIsGeneratedListener( + new UrlUtility(null, $resolver->reveal(), $siteFinder->reveal()), + $this->prophesize(LinkService::class)->reveal() + ); self::assertInstanceOf(AfterLinkIsGeneratedListener::class, $listener); } @@ -44,7 +47,10 @@ public function test__invokeNotModifingAnything() $resolver->evaluate(Argument::any())->willReturn(true); $siteFinder = $this->prophesize(SiteFinder::class); - $listener = new AfterLinkIsGeneratedListener(new UrlUtility(null, $resolver->reveal(), $siteFinder->reveal()), $this->prophesize(LinkService::class)->reveal()); + $listener = new AfterLinkIsGeneratedListener( + new UrlUtility(null, $resolver->reveal(), $siteFinder->reveal()), + $this->prophesize(LinkService::class)->reveal() + ); $site = new Site('test', 1, []); $cObj = $this->prophesize(ContentObjectRenderer::class); @@ -73,8 +79,15 @@ public function test__invokeModifingFromPageUid() $resolver->evaluate(Argument::any())->willReturn(true); $urlUtility = $this->prophesize(UrlUtility::class); - $urlUtility->getFrontendUrlForPage(Argument::is('/'), Argument::is(2))->willReturn('https://frontend-domain.tld/page'); - $urlUtility->getFrontendUrlWithSite(Argument::is('/'), Argument::any())->willReturn('https://frontend-domain.tld/page'); + $urlUtility->getFrontendUrlForPage( + Argument::is('/'), + Argument::is(2) + )->willReturn('https://frontend-domain.tld/page'); + $urlUtility->getFrontendUrlWithSite( + Argument::is('/'), + Argument::any(), + Argument::is('frontendBase') + )->willReturn('https://frontend-domain.tld/page'); $site = new Site('test', 1, []); $cObj = $this->prophesize(ContentObjectRenderer::class); @@ -83,7 +96,10 @@ public function test__invokeModifingFromPageUid() $urlUtility->withRequest($request)->willReturn($urlUtility->reveal()); - $listener = new AfterLinkIsGeneratedListener($urlUtility->reveal(), $this->prophesize(LinkService::class)->reveal()); + $listener = new AfterLinkIsGeneratedListener( + $urlUtility->reveal(), + $this->prophesize(LinkService::class)->reveal() + ); $linkResult = new LinkResult('page', '/'); $linkResult = $linkResult->withLinkText('t3://page?uid=2'); @@ -102,7 +118,11 @@ public function test__invokeModifingWithoutPageId() $site = new Site('test', 1, []); $urlUtility = $this->prophesize(UrlUtility::class); - $urlUtility->getFrontendUrlWithSite(Argument::is('/'), Argument::is($site))->willReturn('https://front.typo3.tld'); + $urlUtility->getFrontendUrlWithSite( + Argument::is('/'), + Argument::is($site), + Argument::is('frontendBase') + )->willReturn('https://front.typo3.tld'); $cObj = $this->prophesize(ContentObjectRenderer::class); $request = (new ServerRequest())->withAttribute('site', $site); @@ -110,7 +130,10 @@ public function test__invokeModifingWithoutPageId() $urlUtility->withRequest($request)->willReturn($urlUtility->reveal()); - $listener = new AfterLinkIsGeneratedListener($urlUtility->reveal(), $this->prophesize(LinkService::class)->reveal()); + $listener = new AfterLinkIsGeneratedListener( + $urlUtility->reveal(), + $this->prophesize(LinkService::class)->reveal() + ); $linkResult = new LinkResult('page', '/'); $linkResult = $linkResult->withLinkText('|'); @@ -149,4 +172,46 @@ public function test__invokeModifingExternalSite() self::assertSame('https://front.typo3.tld', $event->getLinkResult()->getUrl()); } + + public function test__SitemapLink() + { + $resolver = $this->prophesize(Resolver::class); + $resolver->evaluate(Argument::any())->willReturn(true); + + $site = new Site('test', 1, []); + + $urlUtility = $this->prophesize(UrlUtility::class); + $urlUtility->getFrontendUrlWithSite( + Argument::is('https://typo3.tld/sitemap-type/pages/sitemap.xml'), + Argument::is($site), + Argument::is('frontendApiProxy') + ) + ->willReturn('https://front.typo3.tld/headless/sitemap-type/pages/sitemap.xml'); + + $linkService = $this->prophesize(LinkService::class); + $linkService->resolve(Argument::any())->willReturn(['pageuid' => 5]); + + $cObj = $this->prophesize(ContentObjectRenderer::class); + $request = (new ServerRequest())->withAttribute('site', $site); + $cObj->getRequest()->willReturn($request); + + $urlUtility->withRequest($request)->willReturn($urlUtility->reveal()); + + $listener = new AfterLinkIsGeneratedListener($urlUtility->reveal(), $linkService->reveal()); + + $linkResult = new LinkResult('page', 'https://typo3.tld/sitemap-type/pages/sitemap.xml'); + $linkResult = $linkResult->withLinkConfiguration([ + 'parameter' => 't3://page?uid=current&type=1533906435&sitemap=pages', + 'forceAbsoluteUrl' => true, + 'additionalParams' => '&sitemap=pages', + ]); + + $event = new AfterLinkIsGeneratedEvent($linkResult, $cObj->reveal(), []); + $listener($event); + + self::assertSame( + 'https://front.typo3.tld/headless/sitemap-type/pages/sitemap.xml', + $event->getLinkResult()->getUrl() + ); + } } diff --git a/Tests/Unit/Utility/UrlUtilityTest.php b/Tests/Unit/Utility/UrlUtilityTest.php index bfd84b11..73f176e3 100644 --- a/Tests/Unit/Utility/UrlUtilityTest.php +++ b/Tests/Unit/Utility/UrlUtilityTest.php @@ -102,6 +102,8 @@ public function testFrontendUrls(): void $siteFinder = $this->prophesize(SiteFinder::class); + $site->getBase()->shouldBeCalled(2)->willReturn(new Uri('https://test-backend3-api.tld')); + $urlUtility = new UrlUtility(null, $resolver->reveal(), $siteFinder->reveal(), null, $headlessMode); $urlUtility = $urlUtility->withSite($site->reveal()); @@ -109,6 +111,7 @@ public function testFrontendUrls(): void self::assertSame('https://test-frontend-api3.tld/headless', $urlUtility->getProxyUrl()); self::assertSame('https://test-frontend-api3.tld/headless/fileadmin', $urlUtility->getStorageProxyUrl()); self::assertSame('https://test-frontend3.tld/sitemap', $urlUtility->resolveKey('SpecialSitemapKey')); + self::assertSame('https://test-frontend-api3.tld/headless', $urlUtility->getFrontendUrlWithSite('https://test-backend3-api.tld', $site->reveal(), 'frontendApiProxy')); self::assertSame('#fragment-123', $urlUtility->getFrontendUrlWithSite('#fragment-123', $site->reveal())); }