From c36be252a6273a1a1bff37a15cd999bd307dd864 Mon Sep 17 00:00:00 2001 From: Krystian Szymukowicz Date: Sun, 28 Apr 2024 16:30:25 +0200 Subject: [PATCH] Move changing language request set in header X-Locale to earlier stage, before "typo3/cms-frontend/tsfe". Add support for setting language of api request by standard language prefix instead of header X-Locale. --- Classes/Hook/EnrichHashBase.php | 11 +---- .../T3apiRequestLanguageResolver.php | 48 +++++++++++++++++++ Classes/Middleware/T3apiRequestResolver.php | 4 +- Classes/Service/RouteService.php | 37 ++++++++++++-- Configuration/RequestMiddlewares.php | 9 ++++ .../Miscellaneous/Changelog/Index.rst | 1 + 6 files changed, 96 insertions(+), 14 deletions(-) create mode 100644 Classes/Middleware/T3apiRequestLanguageResolver.php diff --git a/Classes/Hook/EnrichHashBase.php b/Classes/Hook/EnrichHashBase.php index ba294ff..a43ea96 100644 --- a/Classes/Hook/EnrichHashBase.php +++ b/Classes/Hook/EnrichHashBase.php @@ -4,8 +4,7 @@ namespace SourceBroker\T3api\Hook; -use SourceBroker\T3api\Routing\Enhancer\ResourceEnhancer; -use TYPO3\CMS\Core\Http\ServerRequest; +use SourceBroker\T3api\Service\RouteService; class EnrichHashBase { @@ -17,13 +16,7 @@ class EnrichHashBase */ public function init(array &$params): void { - /** @var ServerRequest $request */ - $request = $GLOBALS['TYPO3_REQUEST'] ?? null; - if ( - $request instanceof ServerRequest - && is_array($request->getQueryParams()) - && array_key_exists(ResourceEnhancer::PARAMETER_NAME, $request->getQueryParams()) - ) { + if (RouteService::routeHasT3ApiResourceEnhancerQueryParam()) { $params['hashParameters']['t3api_hash_base_random'] = microtime(); } } diff --git a/Classes/Middleware/T3apiRequestLanguageResolver.php b/Classes/Middleware/T3apiRequestLanguageResolver.php new file mode 100644 index 0000000..248bc4a --- /dev/null +++ b/Classes/Middleware/T3apiRequestLanguageResolver.php @@ -0,0 +1,48 @@ +getAttribute('language'); + $t3apiHeaderLanguageUid = $this->getT3apiLanguageUid($request); + + if ($t3apiHeaderLanguageUid !== null + && RouteService::routeHasT3ApiResourceEnhancerQueryParam($request) + && ($language && $language->getLanguageId() !== $t3apiHeaderLanguageUid) + ) { + $request->withAttribute('t3apiHeaderLanguageRequest', true); + $request = $request->withAttribute( + 'language', + $request->getAttribute('site')->getLanguageById($t3apiHeaderLanguageUid) + ); + } + return $handler->handle($request); + } + + protected function getT3apiLanguageUid(ServerRequestInterface $request): ?int + { + $languageHeader = $request->getHeader($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['t3api']['languageHeader']); + return (!empty($languageHeader) ? (int)array_shift($languageHeader) : null); + } +} diff --git a/Classes/Middleware/T3apiRequestResolver.php b/Classes/Middleware/T3apiRequestResolver.php index c22a42c..034510c 100644 --- a/Classes/Middleware/T3apiRequestResolver.php +++ b/Classes/Middleware/T3apiRequestResolver.php @@ -10,6 +10,7 @@ use Psr\Http\Server\RequestHandlerInterface; use SourceBroker\T3api\Dispatcher\Bootstrap; use SourceBroker\T3api\Routing\Enhancer\ResourceEnhancer; +use SourceBroker\T3api\Service\RouteService; use Throwable; /** @@ -29,8 +30,7 @@ public function __construct(Bootstrap $bootstrap) */ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { - if (is_array($request->getQueryParams()) - && array_key_exists(ResourceEnhancer::PARAMETER_NAME, $request->getQueryParams())) { + if (RouteService::routeHasT3ApiResourceEnhancerQueryParam($request)) { return $this->bootstrap->process($this->cleanupRequest($request)); } diff --git a/Classes/Service/RouteService.php b/Classes/Service/RouteService.php index bba916f..a49d6e0 100644 --- a/Classes/Service/RouteService.php +++ b/Classes/Service/RouteService.php @@ -4,9 +4,12 @@ namespace SourceBroker\T3api\Service; +use Psr\Http\Message\ServerRequestInterface; use RuntimeException; use SourceBroker\T3api\Routing\Enhancer\ResourceEnhancer; +use TYPO3\CMS\Core\Http\ServerRequest; use TYPO3\CMS\Core\SingletonInterface; +use TYPO3\CMS\Core\Site\Entity\SiteLanguage; class RouteService implements SingletonInterface { @@ -24,7 +27,7 @@ public static function getApiBasePath(): string */ public static function getFullApiBasePath(): string { - return trim(self::getDefaultLanguageBasePath() . self::getApiBasePath(), '/'); + return trim(self::getLanguageBasePath() . self::getApiBasePath(), '/'); } public static function getFullApiBaseUrl(): string @@ -33,6 +36,13 @@ public static function getFullApiBaseUrl(): string . '/' . ltrim(self::getFullApiBasePath(), '/'); } + public static function routeHasT3ApiResourceEnhancerQueryParam(ServerRequestInterface $request = null): bool + { + $request = $request ?? self::getRequest(); + return $request instanceof ServerRequest && is_array($request->getQueryParams()) + && array_key_exists(ResourceEnhancer::PARAMETER_NAME, $request->getQueryParams()); + } + protected static function getApiRouteEnhancer(): array { static $apiRouteEnhancer; @@ -57,8 +67,29 @@ protected static function getApiRouteEnhancer(): array ); } - protected static function getDefaultLanguageBasePath(): string + /** + * We support for two cases:language set in X-Locale header + * 1) when request has X-Locale header with language (t3apiHeaderLanguageRequest)) + * 2) when request has no X-Locale header and url itself stores language information + */ + protected static function getLanguageBasePath(): string + { + $request = self::getRequest(); + /** @var SiteLanguage $requestLanguage */ + $requestLanguage = $request->getAttribute('language'); + $languagePrefix = $requestLanguage && $request->getAttribute('t3apiHeaderLanguageRequest') !== true ? + $requestLanguage->getBase()->getPath() : + SiteService::getCurrent()->getDefaultLanguage()->getBase()->getPath(); + + if (str_starts_with((string)$request?->getUri()->getPath(), $languagePrefix)) { + return $languagePrefix; + } + + return ''; + } + + protected static function getRequest(): ServerRequestInterface { - return SiteService::getCurrent()->getDefaultLanguage()->getBase()->getPath(); + return $GLOBALS['TYPO3_REQUEST']; } } diff --git a/Configuration/RequestMiddlewares.php b/Configuration/RequestMiddlewares.php index 7bb8412..bfdb0d8 100644 --- a/Configuration/RequestMiddlewares.php +++ b/Configuration/RequestMiddlewares.php @@ -4,6 +4,15 @@ return [ 'frontend' => [ + 'sourcebroker/t3api/prepare-api-request' => [ + 'target' => \SourceBroker\T3api\Middleware\T3apiRequestLanguageResolver::class, + 'after' => [ + 'typo3/cms-frontend/site' + ], + 'before' => [ + 'typo3/cms-frontend/tsfe' + ] + ], 'sourcebroker/t3api/process-api-request' => [ 'target' => \SourceBroker\T3api\Middleware\T3apiRequestResolver::class, 'after' => [ diff --git a/Documentation/Miscellaneous/Changelog/Index.rst b/Documentation/Miscellaneous/Changelog/Index.rst index 2164a0a..55506e3 100644 --- a/Documentation/Miscellaneous/Changelog/Index.rst +++ b/Documentation/Miscellaneous/Changelog/Index.rst @@ -12,6 +12,7 @@ Changelog - Protect against "&cHash empty" error when ``cacheHash.enforceValidation`` is set to ``true`` [`issue `__] - Add testing instance for TYPO3 12, remove testing instance for TYPO3 10. Change PHP to 8.1 for testing instances. - [!!!] Drop TYPO3 10, TYPO3 11 on dependencies. Update dependencies to TYPO3 12. +- Move changing language request set in header X-Locale to earlier stage, before "typo3/cms-frontend/tsfe". Add support for setting language of api request by standard language prefix instead of header X-Locale. 2.0.3 =====