DigiComp.FlowTranslationEnd.../Classes/Http/TranslationRequestMiddleware.php
Ferdinand Kuhl ef297fa8e1
All checks were successful
ci/woodpecker/push/code-style Pipeline was successful
ci/woodpecker/push/functional-tests Pipeline was successful
review: consistent naming and methodology
2023-08-08 12:11:46 +02:00

143 lines
4.5 KiB
PHP

<?php
declare(strict_types=1);
namespace DigiComp\FlowTranslationEndpoint\Http;
use GuzzleHttp\Psr7\Response;
use Neos\Cache\Exception as CacheException;
use Neos\Cache\Exception\InvalidDataException;
use Neos\Cache\Frontend\StringFrontend;
use Neos\Flow\I18n\Detector;
use Neos\Flow\I18n\Service;
use Neos\Flow\I18n\Xliff\Service\XliffFileProvider;
use Neos\Utility\Arrays;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
class TranslationRequestMiddleware implements MiddlewareInterface
{
/**
* @var string
*/
protected string $headerName;
/**
* @var Service
*/
protected Service $i18nService;
/**
* @var XliffFileProvider
*/
protected XliffFileProvider $fileProvider;
/**
* @var Detector
*/
protected Detector $detector;
/**
* @var StringFrontend
*/
protected StringFrontend $responseCache;
public function __construct(
string $headerName,
Service $i18nService,
XliffFileProvider $fileProvider,
Detector $detector,
StringFrontend $responseCache
) {
$this->headerName = $headerName;
$this->i18nService = $i18nService;
$this->fileProvider = $fileProvider;
$this->detector = $detector;
$this->responseCache = $responseCache;
}
/**
* @param ServerRequestInterface $request
* @param RequestHandlerInterface $handler
* @return ResponseInterface
* @throws CacheException
* @throws InvalidDataException
* @throws \JsonException
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
if ($request->hasHeader($this->headerName)) {
return $this->createResponse($request);
}
return $handler->handle($request);
}
/**
* @param ServerRequestInterface $request
* @return ResponseInterface
* @throws \JsonException
* @throws CacheException
* @throws InvalidDataException
*/
protected function createResponse(ServerRequestInterface $request): ResponseInterface
{
if ($request->hasHeader('Accept-Language')) {
$wishedLocale = $this->detector->detectLocaleFromHttpHeader($request->getHeader('Accept-Language')[0]);
$bestMatching = $this->i18nService->findBestMatchingLocale($wishedLocale);
$this->i18nService->getConfiguration()->setCurrentLocale($bestMatching);
}
$idPatternList = $request->getHeader($this->headerName)[0] ?? '';
$cacheId = $this->i18nService->getConfiguration()->getCurrentLocale() . '_' . \sha1(\serialize($idPatternList));
if ($this->responseCache->has($cacheId)) {
$response = $this->responseCache->get($cacheId);
} else {
$result = $this->getTranslations(Arrays::trimExplode(',', $idPatternList));
$response = \json_encode($result, \JSON_THROW_ON_ERROR);
$this->responseCache->set($cacheId, $response);
}
return new Response(200, ['Content-Type' => 'application/json'], $response);
}
/**
* @param array $idPatternList
*
* @return array
*/
protected function getTranslations(array $idPatternList): array
{
$result = [];
foreach ($idPatternList as $idPattern) {
$package = 'Neos.Flow:Main';
$parts = \explode('|', $idPattern);
switch (\count($parts)) {
case 2:
[$package, $pattern] = $parts;
break;
case 1:
[$pattern] = $parts;
break;
default:
throw new \InvalidArgumentException('Could not parse idPattern: ' . $idPattern);
}
$translationUnits = $this->fileProvider->getFile(
$package,
$this->i18nService->getConfiguration()->getCurrentLocale()
)->getTranslationUnits();
if (!isset($result[$package])) {
$result[$package] = [];
}
$matchingUnits = \array_filter(
$translationUnits,
static fn($unitId) => \preg_match('~^' . $pattern . '$~', $unitId),
\ARRAY_FILTER_USE_KEY
);
$result[$package] += \array_map(
static fn($value) => $value[0]['target'],
$matchingUnits
);
}
return $result;
}
}