From dece03dc3f933e4b83c755bacceeb0ea0d24b1ec Mon Sep 17 00:00:00 2001 From: Daniel Subiabre Date: Wed, 15 Jan 2025 13:19:58 +0100 Subject: [PATCH] Process localized content as described in the api spec --- src/State/EntityStateProcessor.php | 85 +++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 7 deletions(-) diff --git a/src/State/EntityStateProcessor.php b/src/State/EntityStateProcessor.php index 6c9c564..ef17608 100644 --- a/src/State/EntityStateProcessor.php +++ b/src/State/EntityStateProcessor.php @@ -9,8 +9,9 @@ use ApiPlatform\Metadata\Operation; use ApiPlatform\State\ProcessorInterface; use App\Entity\Interface\LocalizedContentInterface; use App\Service\LocalizationService; +use Doctrine\ORM\EntityManagerInterface; +use Gedmo\Translatable\Entity\Translation; use Symfony\Component\DependencyInjection\Attribute\Autowire; -use Symfony\Component\HttpFoundation\Request; class EntityStateProcessor implements ProcessorInterface { @@ -20,6 +21,7 @@ class EntityStateProcessor implements ProcessorInterface #[Autowire(service: PersistProcessor::class)] private ProcessorInterface $persistProcessor, private LocalizationService $localizationService, + private EntityManagerInterface $entityManager, ) {} /** @@ -28,12 +30,7 @@ class EntityStateProcessor implements ProcessorInterface public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []) { if ($data instanceof LocalizedContentInterface) { - /** @var Request */ - $request = $context['request']; - - $data->setTranslatableLocale($this->localizationService->getLanguage( - $request->headers->get('Content-Language'), - )); + return $this->processLocalizedContent($data, $operation, $uriVariables, $context); } if ($operation instanceof DeleteOperationInterface) { @@ -42,4 +39,78 @@ class EntityStateProcessor implements ProcessorInterface return $this->persistProcessor->process($data, $operation, $uriVariables, $context); } + + private function processLocalizedContent( + LocalizedContentInterface $data, + Operation $operation, + array $uriVariables = [], + array $context = [], + ): mixed { + $languages = $this->getContextLanguages($context); + + if ($operation instanceof DeleteOperationInterface) { + if ($languages === null) { + return $this->deleteProcessor->process($data, $operation, $uriVariables, $context); + } + + return $this->deleteLocalizedContent($data, $operation, $uriVariables, $context, $languages); + } + + $language = $languages ? $languages[0] : $this->localizationService->getDefaultLanguage(); + + $data->setTranslatableLocale($language); + + return $this->persistProcessor->process($data, $operation, $uriVariables, $context); + } + + private function getContextLanguages(array $context): ?array + { + $tags = $context['request']->headers->get('Content-Language', ''); + + if (empty($tags)) { + return null; + } + + return $this->localizationService->getLanguages($tags); + } + + private function deleteLocalizedContent( + LocalizedContentInterface $data, + Operation $operation, + array $uriVariables = [], + array $context = [], + array $languages = [] + ) { + $translationRepository = $this->entityManager->getRepository(Translation::class); + + if (!\array_diff($data->getLocales(), $languages)) { + throw new \Exception("Cannot leave empty resource. Must have at least one available localization."); + } + + $nonLocalizedLanguages = \array_diff($languages, $data->getLocales()); + if (!empty($nonLocalizedLanguages)) { + throw new \Exception(\sprintf( + "Could not find requested localizations '%s' of the resource.", + \join(', ', $nonLocalizedLanguages) + )); + } + + foreach ($languages as $language) { + $translations = $translationRepository->findBy([ + 'locale' => $language, + 'objectClass' => $data::class, + 'foreignKey' => $data->getId() + ]); + + foreach ($translations as $translation) { + $this->entityManager->remove($translation); + } + + $data->removeLocale($language); + } + + $this->entityManager->flush(); + + return $this->persistProcessor->process($data, $operation, $uriVariables, $context); + } }