From 5d0cf3b93ca1eb0dce948dfc037590e9d60bcd3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Wolda=C5=84ski?= Date: Fri, 8 May 2026 11:25:55 +0200 Subject: [PATCH] [TASK] improve UrlUtility --- .../HeadlessHreflangGeneratorListener.php | 4 +- .../Form/Finisher/JsonRedirectFinisher.php | 6 +- Classes/Hooks/PreviewUrlHook.php | 4 +- .../ShortcutAndMountPointRedirect.php | 4 +- .../Middleware/SiteBaseRedirectResolver.php | 4 +- Classes/Utility/PluginUtility.php | 2 +- Classes/Utility/UrlUtility.php | 22 ++------ Classes/ViewHelpers/DomainViewHelper.php | 4 +- Classes/XClass/ImageService.php | 6 +- Classes/XClass/Preview/PreviewUriBuilder.php | 8 +-- Classes/XClass/ResourceLocalDriver.php | 8 +-- Configuration/Services.php | 14 ++++- .../RootSiteProcessing/DomainSchemaTest.php | 3 +- .../AfterLinkIsGeneratedListenerTest.php | 5 +- ...terPagePreviewUriGeneratedListenerTest.php | 16 ++++-- ...edirectUrlAdditionalParamsListenerTest.php | 3 +- .../Middleware/CookieDomainPerSiteTest.php | 5 +- .../SiteBaseRedirectResolverTest.php | 5 +- Tests/Unit/Utility/PluginUtilityTest.php | 4 +- Tests/Unit/Utility/UrlUtilityTest.php | 55 ++++++++++--------- 20 files changed, 95 insertions(+), 87 deletions(-) diff --git a/Classes/Event/Listener/HeadlessHreflangGeneratorListener.php b/Classes/Event/Listener/HeadlessHreflangGeneratorListener.php index 6e288d66..91053cfe 100644 --- a/Classes/Event/Listener/HeadlessHreflangGeneratorListener.php +++ b/Classes/Event/Listener/HeadlessHreflangGeneratorListener.php @@ -11,7 +11,7 @@ namespace FriendsOfTYPO3\Headless\Event\Listener; -use FriendsOfTYPO3\Headless\Utility\UrlUtility; +use FriendsOfTYPO3\Headless\Utility\HeadlessFrontendUrlInterface; use TYPO3\CMS\Frontend\Event\ModifyHrefLangTagsEvent; /** @@ -19,7 +19,7 @@ */ class HeadlessHreflangGeneratorListener { - public function __construct(private readonly UrlUtility $urlUtility) {} + public function __construct(private readonly HeadlessFrontendUrlInterface $urlUtility) {} public function __invoke(ModifyHrefLangTagsEvent $event): void { diff --git a/Classes/Form/Finisher/JsonRedirectFinisher.php b/Classes/Form/Finisher/JsonRedirectFinisher.php index 5efccf04..f44c251e 100644 --- a/Classes/Form/Finisher/JsonRedirectFinisher.php +++ b/Classes/Form/Finisher/JsonRedirectFinisher.php @@ -11,7 +11,7 @@ namespace FriendsOfTYPO3\Headless\Form\Finisher; -use FriendsOfTYPO3\Headless\Utility\UrlUtility; +use FriendsOfTYPO3\Headless\Utility\HeadlessFrontendUrlInterface; use JsonException; use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -51,7 +51,7 @@ class JsonRedirectFinisher extends AbstractFinisher * via GeneralUtility::makeInstance($implementationClassName) without args, so DI cannot * honor constructor injection. Resolve via container on first use. */ - private ?UrlUtility $urlUtility = null; + private ?HeadlessFrontendUrlInterface $urlUtility = null; /** * Executes this finisher @@ -101,7 +101,7 @@ protected function prepareRedirect( $serverRequest = $this->request->getAttribute('extbase.request.originalRequest') ?? $GLOBALS['TYPO3_REQUEST']; - $urlUtility = ($this->urlUtility ??= GeneralUtility::makeInstance(UrlUtility::class))->withRequest($serverRequest); + $urlUtility = ($this->urlUtility ??= GeneralUtility::makeInstance(HeadlessFrontendUrlInterface::class))->withRequest($serverRequest); $cObj = $serverRequest->getAttribute('currentContentObject'); if ($cObj === null) { diff --git a/Classes/Hooks/PreviewUrlHook.php b/Classes/Hooks/PreviewUrlHook.php index 78cda82d..6c0074d8 100644 --- a/Classes/Hooks/PreviewUrlHook.php +++ b/Classes/Hooks/PreviewUrlHook.php @@ -11,7 +11,7 @@ namespace FriendsOfTYPO3\Headless\Hooks; -use FriendsOfTYPO3\Headless\Utility\UrlUtility; +use FriendsOfTYPO3\Headless\Utility\HeadlessFrontendUrlInterface; /** * PreviewUrlHook @@ -20,7 +20,7 @@ **/ class PreviewUrlHook { - public function __construct(private readonly UrlUtility $urlUtility) {} + public function __construct(private readonly HeadlessFrontendUrlInterface $urlUtility) {} /** * @param string $previewUrl diff --git a/Classes/Middleware/ShortcutAndMountPointRedirect.php b/Classes/Middleware/ShortcutAndMountPointRedirect.php index 1f172235..007732d8 100644 --- a/Classes/Middleware/ShortcutAndMountPointRedirect.php +++ b/Classes/Middleware/ShortcutAndMountPointRedirect.php @@ -11,8 +11,8 @@ namespace FriendsOfTYPO3\Headless\Middleware; +use FriendsOfTYPO3\Headless\Utility\HeadlessFrontendUrlInterface; use FriendsOfTYPO3\Headless\Utility\HeadlessModeInterface; -use FriendsOfTYPO3\Headless\Utility\UrlUtility; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; @@ -27,7 +27,7 @@ class ShortcutAndMountPointRedirect extends \TYPO3\CMS\Frontend\Middleware\Short { public function __construct( private readonly HeadlessModeInterface $headlessMode, - private readonly UrlUtility $urlUtility, + private readonly HeadlessFrontendUrlInterface $urlUtility, PageTypeLinkResolver $pageTypeLinkResolver, ) { parent::__construct($pageTypeLinkResolver); diff --git a/Classes/Middleware/SiteBaseRedirectResolver.php b/Classes/Middleware/SiteBaseRedirectResolver.php index ed376bff..128d6296 100644 --- a/Classes/Middleware/SiteBaseRedirectResolver.php +++ b/Classes/Middleware/SiteBaseRedirectResolver.php @@ -11,8 +11,8 @@ namespace FriendsOfTYPO3\Headless\Middleware; +use FriendsOfTYPO3\Headless\Utility\HeadlessFrontendUrlInterface; use FriendsOfTYPO3\Headless\Utility\HeadlessModeInterface; -use FriendsOfTYPO3\Headless\Utility\UrlUtility; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; @@ -24,7 +24,7 @@ class SiteBaseRedirectResolver extends \TYPO3\CMS\Frontend\Middleware\SiteBaseRe { public function __construct( private readonly HeadlessModeInterface $headlessMode, - private readonly UrlUtility $urlUtility, + private readonly HeadlessFrontendUrlInterface $urlUtility, ) {} public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface diff --git a/Classes/Utility/PluginUtility.php b/Classes/Utility/PluginUtility.php index 9cc4e7bd..ddccb2a4 100644 --- a/Classes/Utility/PluginUtility.php +++ b/Classes/Utility/PluginUtility.php @@ -17,7 +17,7 @@ class PluginUtility { - public function __construct(private readonly UrlUtility $urlUtility) {} + public function __construct(private readonly HeadlessFrontendUrlInterface $urlUtility) {} public function redirect(ServerRequestInterface $request, string $uri, int $statusCode = 307): never { diff --git a/Classes/Utility/UrlUtility.php b/Classes/Utility/UrlUtility.php index de0ddefb..8299e994 100644 --- a/Classes/Utility/UrlUtility.php +++ b/Classes/Utility/UrlUtility.php @@ -26,6 +26,7 @@ use TYPO3\CMS\Core\Site\SiteFinder; use TYPO3\CMS\Core\Utility\GeneralUtility; + use function array_key_exists; use function array_merge; use function array_unique; @@ -40,29 +41,16 @@ class UrlUtility implements LoggerAwareInterface, HeadlessFrontendUrlInterface { use LoggerAwareTrait; - private Features $features; - private Resolver $resolver; - private SiteFinder $siteFinder; private array $conf = []; private array $variants = []; - private HeadlessModeInterface $headlessMode; private array $frontendDomains = []; public function __construct( - ?Features $features = null, - ?Resolver $resolver = null, - ?SiteFinder $siteFinder = null, - ?ServerRequestInterface $serverRequest = null, - ?HeadlessModeInterface $headlessMode = null + private readonly Features $features, + private readonly Resolver $resolver, + private readonly SiteFinder $siteFinder, + private HeadlessModeInterface $headlessMode, ) { - $this->features = $features ?? GeneralUtility::makeInstance(Features::class); - $this->resolver = $resolver ?? GeneralUtility::makeInstance(Resolver::class, 'site', []); - $this->siteFinder = $siteFinder ?? GeneralUtility::makeInstance(SiteFinder::class); - $this->headlessMode = $headlessMode ?? GeneralUtility::makeInstance(HeadlessModeInterface::class); - - if ($serverRequest instanceof ServerRequestInterface) { - $this->extractConfigurationFromRequest($serverRequest, $this); - } } public function withSite(Site $site): HeadlessFrontendUrlInterface diff --git a/Classes/ViewHelpers/DomainViewHelper.php b/Classes/ViewHelpers/DomainViewHelper.php index ccac3408..34f3d11c 100644 --- a/Classes/ViewHelpers/DomainViewHelper.php +++ b/Classes/ViewHelpers/DomainViewHelper.php @@ -11,12 +11,12 @@ namespace FriendsOfTYPO3\Headless\ViewHelpers; -use FriendsOfTYPO3\Headless\Utility\UrlUtility; +use FriendsOfTYPO3\Headless\Utility\HeadlessFrontendUrlInterface; use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; class DomainViewHelper extends AbstractViewHelper { - public function __construct(private readonly UrlUtility $urlUtility) {} + public function __construct(private readonly HeadlessFrontendUrlInterface $urlUtility) {} public function initializeArguments(): void { diff --git a/Classes/XClass/ImageService.php b/Classes/XClass/ImageService.php index 2ec4b123..afc333c6 100644 --- a/Classes/XClass/ImageService.php +++ b/Classes/XClass/ImageService.php @@ -11,8 +11,8 @@ namespace FriendsOfTYPO3\Headless\XClass; +use FriendsOfTYPO3\Headless\Utility\HeadlessFrontendUrlInterface; use FriendsOfTYPO3\Headless\Utility\HeadlessModeInterface; -use FriendsOfTYPO3\Headless\Utility\UrlUtility; use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Core\Http\ApplicationType; use TYPO3\CMS\Core\Resource\FileInterface; @@ -27,7 +27,7 @@ readonly class ImageService extends \TYPO3\CMS\Extbase\Service\ImageService { private HeadlessModeInterface $headlessMode; - private UrlUtility $urlUtility; + private HeadlessFrontendUrlInterface $urlUtility; /** * Eager init via container in constructor. This XClass is registered through @@ -43,7 +43,7 @@ public function __construct(ResourceFactory $resourceFactory) { parent::__construct($resourceFactory); $this->headlessMode = GeneralUtility::makeInstance(HeadlessModeInterface::class); - $this->urlUtility = GeneralUtility::makeInstance(UrlUtility::class); + $this->urlUtility = GeneralUtility::makeInstance(HeadlessFrontendUrlInterface::class); } /** diff --git a/Classes/XClass/Preview/PreviewUriBuilder.php b/Classes/XClass/Preview/PreviewUriBuilder.php index 369ec14d..06900d4e 100644 --- a/Classes/XClass/Preview/PreviewUriBuilder.php +++ b/Classes/XClass/Preview/PreviewUriBuilder.php @@ -11,8 +11,8 @@ namespace FriendsOfTYPO3\Headless\XClass\Preview; +use FriendsOfTYPO3\Headless\Utility\HeadlessFrontendUrlInterface; use FriendsOfTYPO3\Headless\Utility\HeadlessModeInterface; -use FriendsOfTYPO3\Headless\Utility\UrlUtility; use InvalidArgumentException; use TYPO3\CMS\Core\Exception\SiteNotFoundException; use TYPO3\CMS\Core\Routing\InvalidRouteArgumentsException; @@ -34,7 +34,7 @@ class PreviewUriBuilder extends \TYPO3\CMS\Workspaces\Preview\PreviewUriBuilder */ private ?HeadlessModeInterface $headlessMode = null; private ?SiteFinder $siteFinder = null; - private ?UrlUtility $urlUtility = null; + private ?HeadlessFrontendUrlInterface $urlUtility = null; private function getHeadlessMode(): HeadlessModeInterface { @@ -46,9 +46,9 @@ private function getSiteFinder(): SiteFinder return $this->siteFinder ??= GeneralUtility::makeInstance(SiteFinder::class); } - private function getUrlUtility(): UrlUtility + private function getUrlUtility(): HeadlessFrontendUrlInterface { - return $this->urlUtility ??= GeneralUtility::makeInstance(UrlUtility::class); + return $this->urlUtility ??= GeneralUtility::makeInstance(HeadlessFrontendUrlInterface::class); } /** diff --git a/Classes/XClass/ResourceLocalDriver.php b/Classes/XClass/ResourceLocalDriver.php index a5ca615f..82102880 100644 --- a/Classes/XClass/ResourceLocalDriver.php +++ b/Classes/XClass/ResourceLocalDriver.php @@ -11,8 +11,8 @@ namespace FriendsOfTYPO3\Headless\XClass; +use FriendsOfTYPO3\Headless\Utility\HeadlessFrontendUrlInterface; use FriendsOfTYPO3\Headless\Utility\HeadlessModeInterface; -use FriendsOfTYPO3\Headless\Utility\UrlUtility; use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Core\Http\ApplicationType; use TYPO3\CMS\Core\Http\Uri; @@ -33,16 +33,16 @@ class ResourceLocalDriver extends LocalDriver * is honored for SYS][Objects] XClasses. We resolve via container manually on first use. */ private ?HeadlessModeInterface $headlessMode = null; - private ?UrlUtility $urlUtility = null; + private ?HeadlessFrontendUrlInterface $urlUtility = null; private function getHeadlessMode(): HeadlessModeInterface { return $this->headlessMode ??= GeneralUtility::makeInstance(HeadlessModeInterface::class); } - private function getUrlUtility(): UrlUtility + private function getUrlUtility(): HeadlessFrontendUrlInterface { - return $this->urlUtility ??= GeneralUtility::makeInstance(UrlUtility::class); + return $this->urlUtility ??= GeneralUtility::makeInstance(HeadlessFrontendUrlInterface::class); } protected function determineBaseUrl(): void diff --git a/Configuration/Services.php b/Configuration/Services.php index b3a3492f..b4bedf09 100644 --- a/Configuration/Services.php +++ b/Configuration/Services.php @@ -36,10 +36,13 @@ use FriendsOfTYPO3\Headless\XClass\TemplateView; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; use TYPO3\CMS\Core\Configuration\Features; +use TYPO3\CMS\Core\ExpressionLanguage\Resolver; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Form\Controller\FormFrontendController; use TYPO3\CMS\FrontendLogin\Controller\LoginController; +use function Symfony\Component\DependencyInjection\Loader\Configurator\service; + return static function (ContainerConfigurator $configurator): void { $services = $configurator->services() ->defaults() @@ -80,8 +83,15 @@ $services->set(DomainSchema::class)->public(); $services->set(BackendEditorUrl::class)->public(); $services->set(FileUtility::class)->public(); - $services->set(UrlUtility::class)->autowire(false)->share(false); - $services->set(HeadlessFrontendUrlInterface::class, UrlUtility::class)->autowire(false)->share(false); + $services->set('headless.expression_language.resolver.site', Resolver::class) + ->args(['site', []]); + + $services->set(UrlUtility::class) + ->share(false) + ->arg('$resolver', service('headless.expression_language.resolver.site')); + $services->set(HeadlessFrontendUrlInterface::class, UrlUtility::class) + ->share(false) + ->arg('$resolver', service('headless.expression_language.resolver.site')); $services->set(AfterLinkIsGeneratedListener::class)->tag( 'event.listener', ['identifier' => 'headless/AfterLinkIsGenerated'] diff --git a/Tests/Unit/DataProcessing/RootSiteProcessing/DomainSchemaTest.php b/Tests/Unit/DataProcessing/RootSiteProcessing/DomainSchemaTest.php index 28ba3bf6..24dc4981 100644 --- a/Tests/Unit/DataProcessing/RootSiteProcessing/DomainSchemaTest.php +++ b/Tests/Unit/DataProcessing/RootSiteProcessing/DomainSchemaTest.php @@ -17,6 +17,7 @@ use FriendsOfTYPO3\Headless\Utility\HeadlessMode; use FriendsOfTYPO3\Headless\Utility\UrlUtility; use Psr\Http\Message\UriInterface; +use TYPO3\CMS\Core\Configuration\Features; use TYPO3\CMS\Core\ExpressionLanguage\Resolver; use TYPO3\CMS\Core\Http\ServerRequest; use TYPO3\CMS\Core\Http\Uri; @@ -128,7 +129,7 @@ protected function getUrlUtility($site = null): UrlUtility $dummyRequest = (new ServerRequest())->withAttribute('site', $site); $dummyRequest = $dummyRequest->withAttribute('headless', new Headless()); - return new UrlUtility(null, $resolver, $mock, $dummyRequest, (new HeadlessMode())->withRequest($dummyRequest)); + return (new UrlUtility(new Features(), $resolver, $mock, (new HeadlessMode())->withRequest($dummyRequest)))->withRequest($dummyRequest); } protected function getSiteWithBase(UriInterface $uri, $withLanguage = null) diff --git a/Tests/Unit/Event/Listener/AfterLinkIsGeneratedListenerTest.php b/Tests/Unit/Event/Listener/AfterLinkIsGeneratedListenerTest.php index 79c1a41f..3cc823e9 100644 --- a/Tests/Unit/Event/Listener/AfterLinkIsGeneratedListenerTest.php +++ b/Tests/Unit/Event/Listener/AfterLinkIsGeneratedListenerTest.php @@ -16,6 +16,7 @@ use Psr\EventDispatcher\EventDispatcherInterface; use ReflectionProperty; use Symfony\Component\DependencyInjection\Container; +use TYPO3\CMS\Core\Configuration\Features; use TYPO3\CMS\Core\ExpressionLanguage\Resolver; use TYPO3\CMS\Core\Http\ServerRequest; use TYPO3\CMS\Core\LinkHandling\LinkService; @@ -54,7 +55,7 @@ public function test__construct() $listener = new AfterLinkIsGeneratedListener( $this->createMock(Logger::class), - new UrlUtility(null, $resolver, $siteFinder), + new UrlUtility(new Features(), $resolver, $siteFinder, new HeadlessMode()), $this->createMock(LinkService::class), new TypoLinkCodecService($this->createMock(EventDispatcherInterface::class)), $siteFinder @@ -71,7 +72,7 @@ public function test__invokeNotModifingAnything() $listener = new AfterLinkIsGeneratedListener( $this->createMock(Logger::class), - new UrlUtility(null, $resolver, $siteFinder), + new UrlUtility(new Features(), $resolver, $siteFinder, new HeadlessMode()), $this->createMock(LinkService::class), new TypoLinkCodecService($this->createMock(EventDispatcherInterface::class)), $siteFinder diff --git a/Tests/Unit/Event/Listener/AfterPagePreviewUriGeneratedListenerTest.php b/Tests/Unit/Event/Listener/AfterPagePreviewUriGeneratedListenerTest.php index 30884928..2c176bfd 100644 --- a/Tests/Unit/Event/Listener/AfterPagePreviewUriGeneratedListenerTest.php +++ b/Tests/Unit/Event/Listener/AfterPagePreviewUriGeneratedListenerTest.php @@ -18,6 +18,7 @@ use Symfony\Component\DependencyInjection\Container; use TYPO3\CMS\Backend\Routing\Event\AfterPagePreviewUriGeneratedEvent; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; +use TYPO3\CMS\Core\Configuration\Features; use TYPO3\CMS\Core\Context\Context; use TYPO3\CMS\Core\Exception\SiteNotFoundException; use TYPO3\CMS\Core\ExpressionLanguage\Resolver; @@ -51,9 +52,10 @@ public function test__construct() $siteFinder = $this->createMock(SiteFinder::class); $listener = new AfterPagePreviewUriGeneratedListener(new UrlUtility( - null, + new Features(), $resolver, - $siteFinder + $siteFinder, + new HeadlessMode() ), $siteFinder, new HeadlessMode()); self::assertInstanceOf(AfterPagePreviewUriGeneratedListener::class, $listener); @@ -67,9 +69,10 @@ public function testLink() $siteFinder->method('getSiteByPageId')->willReturn($site = new Site('test', 1, ['headless' => HeadlessModeInterface::MIXED, 'frontendBase' => 'https://front.test.tld', 'base' => 'https://test.tld'])); $listener = new AfterPagePreviewUriGeneratedListener(new UrlUtility( - null, + new Features(), $resolver, - $siteFinder + $siteFinder, + new HeadlessMode() ), $siteFinder, new HeadlessMode()); $event = new AfterPagePreviewUriGeneratedEvent( @@ -101,9 +104,10 @@ public function testSiteNotFound() $siteFinder->method('getSiteByPageId')->willThrowException(new SiteNotFoundException()); $listener = new AfterPagePreviewUriGeneratedListener(new UrlUtility( - null, + new Features(), $resolver, - $siteFinder + $siteFinder, + new HeadlessMode() ), $siteFinder, new HeadlessMode()); $event = new AfterPagePreviewUriGeneratedEvent( diff --git a/Tests/Unit/Event/Listener/RedirectUrlAdditionalParamsListenerTest.php b/Tests/Unit/Event/Listener/RedirectUrlAdditionalParamsListenerTest.php index a53a76e8..14f956a6 100644 --- a/Tests/Unit/Event/Listener/RedirectUrlAdditionalParamsListenerTest.php +++ b/Tests/Unit/Event/Listener/RedirectUrlAdditionalParamsListenerTest.php @@ -21,6 +21,7 @@ use Psr\Http\Message\UriInterface; use ReflectionProperty; use Symfony\Component\DependencyInjection\Container; +use TYPO3\CMS\Core\Configuration\Features; use TYPO3\CMS\Core\ExpressionLanguage\Resolver; use TYPO3\CMS\Core\Http\ServerRequest; use TYPO3\CMS\Core\Http\Uri; @@ -245,7 +246,7 @@ protected function getUrlUtility($site = null): UrlUtility $siteFinder->method('getSiteByPageId')->willReturn($site); - return new UrlUtility(null, $resolver, $siteFinder, null, (new HeadlessMode())->withRequest((new ServerRequest())->withAttribute('headless', new Headless()))); + return new UrlUtility(new Features(), $resolver, $siteFinder, (new HeadlessMode())->withRequest((new ServerRequest())->withAttribute('headless', new Headless()))); } protected function tearDown(): void diff --git a/Tests/Unit/Middleware/CookieDomainPerSiteTest.php b/Tests/Unit/Middleware/CookieDomainPerSiteTest.php index 99c42e96..cc3c395f 100644 --- a/Tests/Unit/Middleware/CookieDomainPerSiteTest.php +++ b/Tests/Unit/Middleware/CookieDomainPerSiteTest.php @@ -19,6 +19,7 @@ use Psr\Log\LoggerInterface; use ReflectionProperty; use Symfony\Component\DependencyInjection\Container; +use TYPO3\CMS\Core\Configuration\Features; use TYPO3\CMS\Core\ExpressionLanguage\Resolver; use TYPO3\CMS\Core\Http\JsonResponse; use TYPO3\CMS\Core\Http\NormalizedParams; @@ -82,7 +83,7 @@ public function emptyCookieDomain() $site, ]); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder); + $urlUtility = new UrlUtility(new Features(), $resolver, $siteFinder, new HeadlessMode()); $urlUtility = $urlUtility->withSite($site); $middleware = new CookieDomainPerSite($urlUtility, $siteFinder, $this->createMock(LoggerInterface::class)); @@ -140,7 +141,7 @@ public function cookieDomainIsSet() $site, ]); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder); + $urlUtility = new UrlUtility(new Features(), $resolver, $siteFinder, new HeadlessMode()); $urlUtility = $urlUtility->withSite($site); $middleware = new CookieDomainPerSite($urlUtility, $siteFinder, $this->createMock(LoggerInterface::class)); diff --git a/Tests/Unit/Middleware/SiteBaseRedirectResolverTest.php b/Tests/Unit/Middleware/SiteBaseRedirectResolverTest.php index 2c696227..b8e1e22d 100644 --- a/Tests/Unit/Middleware/SiteBaseRedirectResolverTest.php +++ b/Tests/Unit/Middleware/SiteBaseRedirectResolverTest.php @@ -19,6 +19,7 @@ use Psr\Http\Server\RequestHandlerInterface; use ReflectionProperty; use Symfony\Component\DependencyInjection\Container; +use TYPO3\CMS\Core\Configuration\Features; use TYPO3\CMS\Core\ExpressionLanguage\Resolver; use TYPO3\CMS\Core\Http\JsonResponse; use TYPO3\CMS\Core\Http\ServerRequest; @@ -66,7 +67,7 @@ public function testJsonRedirect() $container->set(HeadlessModeInterface::class, new HeadlessMode()); GeneralUtility::setContainer($container); - $urlUtility = GeneralUtility::makeInstance(UrlUtility::class, null, $this->createMock(Resolver::class), $siteFinder); + $urlUtility = new UrlUtility(new Features(), $this->createMock(Resolver::class), $siteFinder, new HeadlessMode()); $container->set(UrlUtility::class, $urlUtility); GeneralUtility::setContainer($container); @@ -139,7 +140,7 @@ public function testJsonRedirect() $container = new Container(); $container->set(HeadlessModeInterface::class, new HeadlessMode()); - $urlUtility = GeneralUtility::makeInstance(UrlUtility::class, null, $this->createMock(Resolver::class), $siteFinder); + $urlUtility = new UrlUtility(new Features(), $this->createMock(Resolver::class), $siteFinder, new HeadlessMode()); $container->set(UrlUtility::class, $urlUtility); $errorController = $this->createMock(ErrorController::class); $errorController->method('pageNotFoundAction')->willReturn(new JsonResponse(['ErrorController' => true])); diff --git a/Tests/Unit/Utility/PluginUtilityTest.php b/Tests/Unit/Utility/PluginUtilityTest.php index 44224ee4..e9876455 100644 --- a/Tests/Unit/Utility/PluginUtilityTest.php +++ b/Tests/Unit/Utility/PluginUtilityTest.php @@ -48,7 +48,7 @@ protected function tearDown(): void public function testProperException(): void { - $urlUtility = new UrlUtility(new Features(), $this->createMock(Resolver::class), $this->createMock(SiteFinder::class)); + $urlUtility = new UrlUtility(new Features(), $this->createMock(Resolver::class), $this->createMock(SiteFinder::class), new HeadlessMode()); $pluginRedirect = new PluginUtility($urlUtility); @@ -59,7 +59,7 @@ public function testProperException(): void public function testResponse(): void { - $urlUtility = new UrlUtility(new Features(), $this->createMock(Resolver::class), $this->createMock(SiteFinder::class)); + $urlUtility = new UrlUtility(new Features(), $this->createMock(Resolver::class), $this->createMock(SiteFinder::class), new HeadlessMode()); $pluginRedirect = new PluginUtility($urlUtility); diff --git a/Tests/Unit/Utility/UrlUtilityTest.php b/Tests/Unit/Utility/UrlUtilityTest.php index 089ef46b..e859c796 100644 --- a/Tests/Unit/Utility/UrlUtilityTest.php +++ b/Tests/Unit/Utility/UrlUtilityTest.php @@ -18,6 +18,7 @@ use ReflectionProperty; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\ExpressionLanguage\SyntaxError; +use TYPO3\CMS\Core\Configuration\Features; use TYPO3\CMS\Core\Exception\SiteNotFoundException; use TYPO3\CMS\Core\ExpressionLanguage\Resolver; use TYPO3\CMS\Core\Http\ServerRequest; @@ -95,7 +96,7 @@ public function testFrontendUrls(): void $siteFinder = $this->createMock(SiteFinder::class); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, null, $headlessMode); + $urlUtility = new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode); $urlUtility = $urlUtility->withSite($site); self::assertSame('https://test-frontend.tld', $urlUtility->getFrontendUrl()); @@ -116,7 +117,7 @@ public function testFrontendUrls(): void $siteFinder = $this->createMock(SiteFinder::class); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, null, $headlessMode); + $urlUtility = new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode); $urlUtility = $urlUtility->withSite($site); self::assertSame('https://test-frontend2.tld', $urlUtility->getFrontendUrl()); @@ -143,7 +144,7 @@ public function testFrontendUrls(): void $site->method('getBase')->willReturn(new Uri('https://test-backend3-api.tld/')); $site->method('getLanguages')->willReturn([]); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, null, $headlessMode); + $urlUtility = new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode); $urlUtility = $urlUtility->withSite($site); self::assertSame('https://test-frontend3.tld', $urlUtility->getFrontendUrl()); @@ -179,7 +180,7 @@ public function testFrontendUrlsWithDifferentPaths(): void $siteFinder = $this->createMock(SiteFinder::class); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, null, $headlessMode); + $urlUtility = new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode); $urlUtility = $urlUtility->withSite($site); self::assertSame('https://test-frontend.tld/frontend/content-page', $urlUtility->getFrontendUrlWithSite('https://test-backend-api.tld/dev-path/content-page', $site)); @@ -215,7 +216,7 @@ public function testFrontendUrlsWithBaseProductionAndLocalOverride(): void $headlessMode = $this->createHeadlessMode(); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, null, $headlessMode); + $urlUtility = new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode); $urlUtility = $urlUtility->withSite($site); self::assertSame('https://test-frontend.tld', $urlUtility->getFrontendUrl()); @@ -227,7 +228,7 @@ public function testFrontendUrlsWithBaseProductionAndLocalOverride(): void $resolver = $this->createMock(Resolver::class); $resolver->method('evaluate')->with(self::stringContains('Development'))->willReturn(false); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, null, $headlessMode); + $urlUtility = new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode); $urlUtility = $urlUtility->withSite($site); self::assertSame('https://www.typo3.org', $urlUtility->getFrontendUrl()); @@ -275,7 +276,7 @@ public function testOptimizedUrlsForFrontendApp(): void $siteFinder = $this->createMock(SiteFinder::class); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, null, $headlessMode); + $urlUtility = new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode); $urlUtility = $urlUtility->withSite($site); // same page, so we make it relative @@ -311,7 +312,7 @@ public function testOptimizedUrlsForFrontendApp(): void $siteFinder = $this->createMock(SiteFinder::class); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, null, $headlessMode); + $urlUtility = new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode); $urlUtility = $urlUtility->withSite($site); // same page, so we make it relative @@ -385,7 +386,7 @@ public function testLanguageResolver(): void $siteFinder = $this->createMock(SiteFinder::class); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, null, $headlessMode); + $urlUtility = new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode); $urlUtility = $urlUtility->withSite($site); $urlUtility = $urlUtility->withLanguage(new SiteLanguage(0, 'en', new Uri('/'), [ 'title' => 'English', @@ -434,7 +435,7 @@ public function testLanguageResolver(): void self::assertSame('https://test-frontend-from-lang.tld/headless/fileadmin', $urlUtility->getStorageProxyUrl()); // not overlay site variants if language has not defined variants - $urlUtility = new UrlUtility(null, $resolver, $siteFinder); + $urlUtility = new UrlUtility(new Features(), $resolver, $siteFinder, $this->createHeadlessMode()); $urlUtility = $urlUtility->withSite($site); $urlUtility = $urlUtility->withLanguage(new SiteLanguage(0, 'en', new Uri('/'), [ 'title' => 'English', @@ -466,7 +467,7 @@ public function testLanguageResolver(): void $siteFinder = $this->createMock(SiteFinder::class); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, null, $headlessMode); + $urlUtility = new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode); $urlUtility = $urlUtility->withSite($site); $urlUtility = $urlUtility->withLanguage(new SiteLanguage(0, 'en', new Uri('/'), [ 'title' => 'English', @@ -529,7 +530,7 @@ public function testFrontendUrlForPage(): void $siteFinder->method('getSiteByPageId')->willReturn($site); $headlessMode = $this->createHeadlessMode(HeadlessMode::NONE); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, null, $headlessMode); + $urlUtility = new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode); $urlUtility = $urlUtility->withSite($site); // flag is not existing/disabled @@ -540,7 +541,7 @@ public function testFrontendUrlForPage(): void $headlessMode = $this->createHeadlessMode(HeadlessMode::FULL); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, null, $headlessMode); + $urlUtility = new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode); $urlUtility = $urlUtility->withSite($site); self::assertSame( 'https://test-frontend.tld/test-page', @@ -577,7 +578,7 @@ public function testFrontendUrlForPageWithAlreadyFrontendUrlResolved(): void $headlessMode = $this->createHeadlessMode(); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, null, $headlessMode); + $urlUtility = new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode); $urlUtility = $urlUtility->withSite($site); self::assertSame( @@ -613,7 +614,7 @@ public function testFrontendUrlForPageWithPortsOnFrontendSide(): void $siteFinder->method('getSiteByPageId')->willReturn($site); $headlessMode = $this->createHeadlessMode(HeadlessMode::NONE); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, null, $headlessMode); + $urlUtility = new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode); $urlUtility = $urlUtility->withSite($site); // flag is not existing/disabled @@ -624,7 +625,7 @@ public function testFrontendUrlForPageWithPortsOnFrontendSide(): void // flag is enabled $headlessMode = $this->createHeadlessMode(); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, null, $headlessMode); + $urlUtility = new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode); $urlUtility = $urlUtility->withSite($site); self::assertSame( 'https://test-frontend.tld:3000/test-page', @@ -659,7 +660,7 @@ public function testFrontendUrlForPageWithPortsOnBothSides(): void $siteFinder = $this->createPartialMock(SiteFinder::class, ['getSiteByPageId']); $siteFinder->method('getSiteByPageId')->willReturn($site); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, null, $headlessMode); + $urlUtility = new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode); $urlUtility = $urlUtility->withSite($site); // flag is not existing/disabled @@ -670,7 +671,7 @@ public function testFrontendUrlForPageWithPortsOnBothSides(): void // flag is enabled $headlessMode = $this->createHeadlessMode(); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, null, $headlessMode); + $urlUtility = new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode); $urlUtility = $urlUtility->withSite($site); self::assertSame( 'https://test-frontend.tld:3000/test-page', @@ -703,7 +704,7 @@ public function testEdgeCases() $siteFinder = $this->createPartialMock(SiteFinder::class, ['getSiteByPageId']); $siteFinder->method('getSiteByPageId')->willReturn($site); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, $request, null, $headlessMode); + $urlUtility = (new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode))->withRequest($request); self::assertSame( 'https://test-backend-api.tld:8000/test-page', @@ -712,7 +713,7 @@ public function testEdgeCases() $siteFinder = $this->createPartialMock(SiteFinder::class, ['getSiteByPageId']); $siteFinder->method('getSiteByPageId')->willThrowException(new SiteNotFoundException('test')); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, $request); + $urlUtility = (new UrlUtility(new Features(), $resolver, $siteFinder, $this->createHeadlessMode()))->withRequest($request); self::assertSame( 'https://test-backend-api.tld:8000/test-page', @@ -722,7 +723,7 @@ public function testEdgeCases() $resolver = $this->createPartialMock(Resolver::class, ['evaluate']); $resolver->method('evaluate')->willThrowException(new SyntaxError('test')); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, $request, $headlessMode); + $urlUtility = (new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode))->withRequest($request); self::assertSame('', $urlUtility->getFrontendUrl()); $urlUtility = $urlUtility->withSite($this->createMockSite('https://test-frontend.tld', '', [])); @@ -764,7 +765,7 @@ public function testEdgeCases() $resolver = $this->createMock(Resolver::class); $resolver->method('evaluate')->willReturn(true); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, $request, $headlessMode); + $urlUtility = (new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode))->withRequest($request); self::assertSame('https://test-frontend-from-lang.tld', $urlUtility->getFrontendUrl()); $request = $this->createMock(ServerRequest::class); @@ -794,7 +795,7 @@ public function testEdgeCases() $resolver = $this->createMock(Resolver::class); $resolver->method('evaluate')->willReturn(true); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, $request, $headlessMode); + $urlUtility = (new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode))->withRequest($request); self::assertSame('', $urlUtility->getFrontendUrl()); // configuration on language lvl without variants @@ -829,7 +830,7 @@ public function testEdgeCases() $resolver = $this->createMock(Resolver::class); $resolver->method('evaluate')->willReturn(true); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, $request, $headlessMode); + $urlUtility = (new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode))->withRequest($request); self::assertSame('https://frontend-domain-from-lang.tld', $urlUtility->getFrontendUrl()); self::assertSame('https://frontend-domain-from-lang.tld/headless', $urlUtility->getProxyUrl()); self::assertSame('https://frontend-domain-from-lang.tld/headless/fileadmin', $urlUtility->getStorageProxyUrl()); @@ -876,7 +877,7 @@ public function testEdgeCases() $resolver = $this->createMock(Resolver::class); $resolver->method('evaluate')->willReturn(true); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, $request, $headlessMode); + $urlUtility = (new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode))->withRequest($request); self::assertSame('https://test-frontend-from-when-develop-lang.tld', $urlUtility->getFrontendUrl()); self::assertSame('https://test-frontend-from-when-develop-lang.tld/headless', $urlUtility->getProxyUrl()); self::assertSame('https://test-frontend-from-when-develop-lang.tld/headless/fileadmin', $urlUtility->getStorageProxyUrl()); @@ -918,7 +919,7 @@ public function testEdgeCases() return null; }); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, null, $headlessMode); + $urlUtility = new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode); $urlUtilityWithRequest = $urlUtility->withRequest($manualRequest); self::assertSame('https://test-frontend-from-from-request-lang.tld', $urlUtilityWithRequest->getFrontendUrl()); self::assertSame('https://test-frontend-from-from-request-lang.tld/headless', $urlUtilityWithRequest->getProxyUrl()); @@ -970,7 +971,7 @@ public function testGetFrontendUrlWithSiteDoesNotLeakStateBetweenCalls(): void $siteFinder = $this->createMock(SiteFinder::class); - $urlUtility = new UrlUtility(null, $resolver, $siteFinder, null, $headlessMode); + $urlUtility = new UrlUtility(new Features(), $resolver, $siteFinder, $headlessMode); // First call — site1 $url1 = $urlUtility->getFrontendUrlWithSite('https://backend1.example.com/page1', $site1);