143 lines
4.5 KiB
PHP
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;
|
|
}
|
|
}
|