From 8a0ce74d873c596144bb00c3d55d78c845c975a7 Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Wed, 5 Apr 2023 18:27:55 +0200 Subject: [PATCH] Implemented API to REST exception converters --- src/bundle/EventListener/ResponseListener.php | 17 +++++-- .../config/exception/converters.yaml | 11 +++++ src/bundle/Resources/config/services.yml | 11 +++++ .../AggregateRepositoryExceptionConverter.php | 45 +++++++++++++++++++ ...ntentFieldValidationExceptionConverter.php | 30 +++++++++++++ .../RepositoryExceptionConverterInterface.php | 24 ++++++++++ 6 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 src/bundle/Resources/config/exception/converters.yaml create mode 100644 src/lib/Exception/Converter/AggregateRepositoryExceptionConverter.php create mode 100644 src/lib/Exception/Converter/ContentFieldValidationExceptionConverter.php create mode 100644 src/lib/Exception/Converter/RepositoryExceptionConverterInterface.php diff --git a/src/bundle/EventListener/ResponseListener.php b/src/bundle/EventListener/ResponseListener.php index 4719084c..b97731b9 100644 --- a/src/bundle/EventListener/ResponseListener.php +++ b/src/bundle/EventListener/ResponseListener.php @@ -6,6 +6,8 @@ */ namespace Ibexa\Bundle\Rest\EventListener; +use Ibexa\Contracts\Core\Repository\Exceptions\Exception as RepositoryException; +use Ibexa\Rest\Exception\Converter\RepositoryExceptionConverterInterface; use Ibexa\Rest\Server\View\AcceptHeaderVisitorDispatcher; use Psr\Log\LoggerAwareInterface; use Psr\Log\LoggerAwareTrait; @@ -31,12 +33,17 @@ class ResponseListener implements EventSubscriberInterface, LoggerAwareInterface */ private $viewDispatcher; + private RepositoryExceptionConverterInterface $repositoryExceptionConverter; + /** * @param $viewDispatcher AcceptHeaderVisitorDispatcher */ - public function __construct(AcceptHeaderVisitorDispatcher $viewDispatcher) - { + public function __construct( + AcceptHeaderVisitorDispatcher $viewDispatcher, + RepositoryExceptionConverterInterface $repositoryExceptionConverter + ) { $this->viewDispatcher = $viewDispatcher; + $this->repositoryExceptionConverter = $repositoryExceptionConverter; } /** @@ -74,7 +81,7 @@ public function onKernelResultView(ViewEvent $event) * * @throws \Exception */ - public function onKernelExceptionView(ExceptionEvent $event) + public function onKernelExceptionView(ExceptionEvent $event): void { if (!$event->getRequest()->attributes->get('is_rest_request')) { return; @@ -86,7 +93,9 @@ public function onKernelExceptionView(ExceptionEvent $event) $event->setResponse( $this->viewDispatcher->dispatch( $event->getRequest(), - $exception + $exception instanceof RepositoryException + ? $this->repositoryExceptionConverter->convert($exception) + : $exception ) ); } diff --git a/src/bundle/Resources/config/exception/converters.yaml b/src/bundle/Resources/config/exception/converters.yaml new file mode 100644 index 00000000..76d14d00 --- /dev/null +++ b/src/bundle/Resources/config/exception/converters.yaml @@ -0,0 +1,11 @@ +services: + _defaults: + autowire: true + autoconfigure: true + public: false + + _instanceof: + Ibexa\Rest\Exception\Converter\RepositoryExceptionConverterInterface: + tags: [ ibexa.rest.repository_exception.converter ] + + Ibexa\Rest\Exception\Converter\ContentFieldValidationExceptionConverter: ~ diff --git a/src/bundle/Resources/config/services.yml b/src/bundle/Resources/config/services.yml index a49611a7..6c66d847 100644 --- a/src/bundle/Resources/config/services.yml +++ b/src/bundle/Resources/config/services.yml @@ -1,3 +1,6 @@ +imports: + - { resource: exception/converters.yaml } + parameters: ibexa.rest.output.visitor.json.regexps: - '(^application/vnd\.ibexa\.api\.[A-Za-z]+\+json$)' @@ -199,6 +202,7 @@ services: Ibexa\Bundle\Rest\EventListener\ResponseListener: arguments: - '@Ibexa\Rest\Server\View\AcceptHeaderVisitorDispatcher' + - '@Ibexa\Rest\Exception\Converter\RepositoryExceptionConverterInterface' calls: - ['setLogger', ['@?logger']] tags: @@ -369,3 +373,10 @@ services: parent: hautelook.router.template calls: - [ setOption, [ strict_requirements, ~ ] ] + + Ibexa\Rest\Exception\Converter\AggregateRepositoryExceptionConverter: + arguments: + $converters: !tagged_iterator ibexa.rest.repository_exception.converter + + Ibexa\Rest\Exception\Converter\RepositoryExceptionConverterInterface: + alias: Ibexa\Rest\Exception\Converter\AggregateRepositoryExceptionConverter diff --git a/src/lib/Exception/Converter/AggregateRepositoryExceptionConverter.php b/src/lib/Exception/Converter/AggregateRepositoryExceptionConverter.php new file mode 100644 index 00000000..9e461af2 --- /dev/null +++ b/src/lib/Exception/Converter/AggregateRepositoryExceptionConverter.php @@ -0,0 +1,45 @@ + */ + private iterable $converters; + + public function __construct(iterable $converters) + { + $this->converters = $converters; + } + + public function convert(RepositoryException $exception): Throwable + { + foreach ($this->converters as $converter) { + if (!$converter->supports($exception)) { + continue; + } + + return $converter->convert($exception); + } + + return $exception; + } + + public function supports(RepositoryException $exception): bool + { + return true; + } +} diff --git a/src/lib/Exception/Converter/ContentFieldValidationExceptionConverter.php b/src/lib/Exception/Converter/ContentFieldValidationExceptionConverter.php new file mode 100644 index 00000000..c2ac8d15 --- /dev/null +++ b/src/lib/Exception/Converter/ContentFieldValidationExceptionConverter.php @@ -0,0 +1,30 @@ +