From d910fb0b80b41b43e508c850e4c214d4b78bba1a Mon Sep 17 00:00:00 2001 From: Teoh Han Hui Date: Thu, 8 Aug 2019 17:52:35 +0200 Subject: [PATCH] Unwrap Messenger HandlerFailedException at the dispatch call site --- .../PublishMercureUpdatesListener.php | 5 +- .../Symfony/Messenger/DataPersister.php | 6 +- .../Symfony/Messenger/DispatchTrait.php | 55 +++++++++++++++++++ src/EventListener/ExceptionListener.php | 14 ----- tests/EventListener/ExceptionListenerTest.php | 1 - 5 files changed, 61 insertions(+), 20 deletions(-) create mode 100644 src/Bridge/Symfony/Messenger/DispatchTrait.php diff --git a/src/Bridge/Doctrine/EventListener/PublishMercureUpdatesListener.php b/src/Bridge/Doctrine/EventListener/PublishMercureUpdatesListener.php index 0646867af43..d59051fd446 100644 --- a/src/Bridge/Doctrine/EventListener/PublishMercureUpdatesListener.php +++ b/src/Bridge/Doctrine/EventListener/PublishMercureUpdatesListener.php @@ -16,6 +16,7 @@ use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Core\Api\ResourceClassResolverInterface; use ApiPlatform\Core\Api\UrlGeneratorInterface; +use ApiPlatform\Core\Bridge\Symfony\Messenger\DispatchTrait; use ApiPlatform\Core\Exception\InvalidArgumentException; use ApiPlatform\Core\Exception\RuntimeException; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; @@ -35,12 +36,12 @@ */ final class PublishMercureUpdatesListener { + use DispatchTrait; use ResourceClassInfoTrait; private $iriConverter; private $resourceMetadataFactory; private $serializer; - private $messageBus; private $publisher; private $expressionLanguage; private $createdEntities; @@ -180,6 +181,6 @@ private function publishUpdate($entity, array $targets): void } $update = new Update($iri, $data, $targets); - $this->messageBus ? $this->messageBus->dispatch($update) : ($this->publisher)($update); + $this->messageBus ? $this->dispatch($update) : ($this->publisher)($update); } } diff --git a/src/Bridge/Symfony/Messenger/DataPersister.php b/src/Bridge/Symfony/Messenger/DataPersister.php index 6cfefa4e0aa..525cd71b304 100644 --- a/src/Bridge/Symfony/Messenger/DataPersister.php +++ b/src/Bridge/Symfony/Messenger/DataPersister.php @@ -32,9 +32,9 @@ final class DataPersister implements ContextAwareDataPersisterInterface { use ClassInfoTrait; + use DispatchTrait; private $resourceMetadataFactory; - private $messageBus; public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, MessageBusInterface $messageBus) { @@ -75,7 +75,7 @@ public function supports($data, array $context = []): bool */ public function persist($data, array $context = []) { - $envelope = $this->messageBus->dispatch($data); + $envelope = $this->dispatch($data); $handledStamp = $envelope->last(HandledStamp::class); if (!$handledStamp instanceof HandledStamp) { @@ -90,7 +90,7 @@ public function persist($data, array $context = []) */ public function remove($data, array $context = []) { - $this->messageBus->dispatch( + $this->dispatch( (new Envelope($data)) ->with(new RemoveStamp()) ); diff --git a/src/Bridge/Symfony/Messenger/DispatchTrait.php b/src/Bridge/Symfony/Messenger/DispatchTrait.php new file mode 100644 index 00000000000..786c124ba6a --- /dev/null +++ b/src/Bridge/Symfony/Messenger/DispatchTrait.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Core\Bridge\Symfony\Messenger; + +use Symfony\Component\Messenger\Envelope; +use Symfony\Component\Messenger\Exception\HandlerFailedException; +use Symfony\Component\Messenger\MessageBusInterface; + +/** + * @internal + */ +trait DispatchTrait +{ + /** + * @var MessageBusInterface|null + */ + private $messageBus; + + /** + * @param object|Envelope $message + */ + private function dispatch($message) + { + if (!$this->messageBus instanceof MessageBusInterface) { + throw new \InvalidArgumentException('The message bus is not set.'); + } + + if (!class_exists(HandlerFailedException::class)) { + return $this->messageBus->dispatch($message); + } + + try { + return $this->messageBus->dispatch($message); + } catch (HandlerFailedException $e) { + // unwrap the exception thrown in handler for Symfony Messenger >= 4.3 + while ($e instanceof HandlerFailedException) { + /** @var \Throwable $e */ + $e = $e->getPrevious(); + } + + throw $e; + } + } +} diff --git a/src/EventListener/ExceptionListener.php b/src/EventListener/ExceptionListener.php index 35f3f8f7752..b995e003258 100644 --- a/src/EventListener/ExceptionListener.php +++ b/src/EventListener/ExceptionListener.php @@ -17,7 +17,6 @@ use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpKernel\EventListener\ExceptionListener as BaseExceptionListener; -use Symfony\Component\Messenger\Exception\HandlerFailedException; /** * Handles requests errors. @@ -45,19 +44,6 @@ public function onKernelException(GetResponseForExceptionEvent $event): void return; } - $exception = $event->getException(); - - // unwrap the exception thrown in handler for Symfony Messenger >= 4.3 - while ($exception instanceof HandlerFailedException) { - /** @var \Throwable $exception */ - $exception = $exception->getPrevious(); - if (!$exception instanceof \Exception) { - throw $exception; - } - } - - $event->setException($exception); - $this->exceptionListener->onKernelException($event); } } diff --git a/tests/EventListener/ExceptionListenerTest.php b/tests/EventListener/ExceptionListenerTest.php index 0cbbb0e48ed..3862d9caf2d 100644 --- a/tests/EventListener/ExceptionListenerTest.php +++ b/tests/EventListener/ExceptionListenerTest.php @@ -37,7 +37,6 @@ public function testOnKernelException(Request $request) $eventProphecy = $this->prophesize(GetResponseForExceptionEvent::class); $eventProphecy->getRequest()->willReturn($request); $eventProphecy->getException()->willReturn(new \Exception()); - $eventProphecy->setException(Argument::type(\Exception::class))->will(function () {}); $eventProphecy->getKernel()->willReturn($kernel); $eventProphecy->setResponse(Argument::type(Response::class))->shouldBeCalled();