From 517affc07838fa7884f963e072d08577ea645e17 Mon Sep 17 00:00:00 2001 From: Rafikooo Date: Tue, 20 Aug 2024 13:16:49 +0200 Subject: [PATCH] [API] Decorate base write state processor to catch messenger exceptions --- phpstan-baseline.neon | 25 ------ .../config/services/data_persisters.xml | 5 -- .../config/services/state_processors.xml | 9 +++ .../Admin/PaymentMethod/RemoveProcessor.php | 6 +- .../Common/MessengerPersistProcessor.php} | 26 +++--- .../MessengerDataPersisterSpec.php | 80 ------------------- .../Common/MessengerPersistProcessorSpec.php | 70 ++++++++++++++++ 7 files changed, 92 insertions(+), 129 deletions(-) rename src/Sylius/Bundle/ApiBundle/{DataPersister/MessengerDataPersister.php => StateProcessor/Common/MessengerPersistProcessor.php} (54%) delete mode 100644 src/Sylius/Bundle/ApiBundle/disabledSpec/DataPersister/MessengerDataPersisterSpec.php create mode 100644 src/Sylius/Bundle/ApiBundle/spec/StateProcessor/Common/MessengerPersistProcessorSpec.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 6a37b2d183..ce0ed897ab 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -575,31 +575,6 @@ parameters: count: 1 path: src/Sylius/Bundle/ApiBundle/DataPersister/CountryDataPersister.php - - - message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\MessengerDataPersister\\:\\:persist\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Sylius/Bundle/ApiBundle/DataPersister/MessengerDataPersister.php - - - - message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\MessengerDataPersister\\:\\:remove\\(\\) has no return type specified\\.$#" - count: 1 - path: src/Sylius/Bundle/ApiBundle/DataPersister/MessengerDataPersister.php - - - - message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\MessengerDataPersister\\:\\:remove\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Sylius/Bundle/ApiBundle/DataPersister/MessengerDataPersister.php - - - - message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\MessengerDataPersister\\:\\:supports\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#" - count: 1 - path: src/Sylius/Bundle/ApiBundle/DataPersister/MessengerDataPersister.php - - - - message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\MessengerDataPersister\\:\\:supports\\(\\) has parameter \\$data with no type specified\\.$#" - count: 1 - path: src/Sylius/Bundle/ApiBundle/DataPersister/MessengerDataPersister.php - - message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataPersister\\\\ProductDataPersister\\:\\:persist\\(\\) has parameter \\$data with no type specified\\.$#" count: 1 diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/services/data_persisters.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/services/data_persisters.xml index 9660c83757..bf71cfe16f 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/services/data_persisters.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/services/data_persisters.xml @@ -18,11 +18,6 @@ - - - - - diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/services/state_processors.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/services/state_processors.xml index e548bb4767..00c9a36e85 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/services/state_processors.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/services/state_processors.xml @@ -112,5 +112,14 @@ + + + + + diff --git a/src/Sylius/Bundle/ApiBundle/StateProcessor/Admin/PaymentMethod/RemoveProcessor.php b/src/Sylius/Bundle/ApiBundle/StateProcessor/Admin/PaymentMethod/RemoveProcessor.php index f73bb1e848..d496688a9f 100644 --- a/src/Sylius/Bundle/ApiBundle/StateProcessor/Admin/PaymentMethod/RemoveProcessor.php +++ b/src/Sylius/Bundle/ApiBundle/StateProcessor/Admin/PaymentMethod/RemoveProcessor.php @@ -19,19 +19,19 @@ use ApiPlatform\State\ProcessorInterface; use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException; use Sylius\Bundle\ApiBundle\Exception\PaymentMethodCannotBeRemoved; use Sylius\Component\Core\Model\PaymentMethodInterface; -use Sylius\Component\Core\Model\ProductInterface; use Webmozart\Assert\Assert; -/** @implements ProcessorInterface */ +/** @implements ProcessorInterface */ final readonly class RemoveProcessor implements ProcessorInterface { + /** @param ProcessorInterface $removeProcessor */ public function __construct( private ProcessorInterface $removeProcessor, ) { } /** - * @param ProductInterface $data + * @param PaymentMethodInterface $data */ public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): void { diff --git a/src/Sylius/Bundle/ApiBundle/DataPersister/MessengerDataPersister.php b/src/Sylius/Bundle/ApiBundle/StateProcessor/Common/MessengerPersistProcessor.php similarity index 54% rename from src/Sylius/Bundle/ApiBundle/DataPersister/MessengerDataPersister.php rename to src/Sylius/Bundle/ApiBundle/StateProcessor/Common/MessengerPersistProcessor.php index b470c15af0..8e17f09a46 100644 --- a/src/Sylius/Bundle/ApiBundle/DataPersister/MessengerDataPersister.php +++ b/src/Sylius/Bundle/ApiBundle/StateProcessor/Common/MessengerPersistProcessor.php @@ -11,27 +11,26 @@ declare(strict_types=1); -namespace Sylius\Bundle\ApiBundle\DataPersister; +namespace Sylius\Bundle\ApiBundle\StateProcessor\Common; -use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface; +use ApiPlatform\Metadata\Operation; +use ApiPlatform\State\ProcessorInterface; use Symfony\Component\Messenger\Exception\DelayedMessageHandlingException; use Symfony\Component\Messenger\Exception\HandlerFailedException; -final class MessengerDataPersister implements ContextAwareDataPersisterInterface +/** @implements ProcessorInterface */ +final readonly class MessengerPersistProcessor implements ProcessorInterface { - public function __construct(private ContextAwareDataPersisterInterface $decoratedDataPersister) + /** @param ProcessorInterface $decoratedProcessor */ + public function __construct(private ProcessorInterface $decoratedProcessor) { } - public function supports($data, array $context = []): bool - { - return $this->decoratedDataPersister->supports($data, $context); - } - - public function persist($data, array $context = []) + /** @throws \Throwable */ + public function process($data, Operation $operation, array $uriVariables = [], array $context = []) { try { - return $this->decoratedDataPersister->persist($data, $context); + return $this->decoratedProcessor->process($data, $operation, $uriVariables, $context); } catch (DelayedMessageHandlingException|HandlerFailedException $e) { while ($e instanceof DelayedMessageHandlingException) { /** @var \Throwable $e */ @@ -45,9 +44,4 @@ final class MessengerDataPersister implements ContextAwareDataPersisterInterface throw $e; } } - - public function remove($data, array $context = []) - { - $this->decoratedDataPersister->remove($data, $context); - } } diff --git a/src/Sylius/Bundle/ApiBundle/disabledSpec/DataPersister/MessengerDataPersisterSpec.php b/src/Sylius/Bundle/ApiBundle/disabledSpec/DataPersister/MessengerDataPersisterSpec.php deleted file mode 100644 index 57d235cb4a..0000000000 --- a/src/Sylius/Bundle/ApiBundle/disabledSpec/DataPersister/MessengerDataPersisterSpec.php +++ /dev/null @@ -1,80 +0,0 @@ -beConstructedWith($decoratedDataPersister); - } - - function it_calls_supports_method_from_decorated_data_presister( - ContextAwareDataPersisterInterface $decoratedDataPersister, - ): void { - $decoratedDataPersister->supports(Argument::any(), [])->shouldBeCalled(); - - $this->supports(Argument::any(), []); - } - - function it_unwraps_delayed_message_handling_exception(ContextAwareDataPersisterInterface $decoratedDataPersister): void - { - $completeOrder = new CompleteOrder('ThankYou'); - $completeOrder->setOrderTokenValue('ORDERTOKEN'); - $envelope = new Envelope($completeOrder); - - if (version_compare(Kernel::VERSION, '6.3.5', '>=')) { - $exception = new DelayedMessageHandlingException([new \RuntimeException('Delayed message exception')], $envelope); - } else { - $exception = new DelayedMessageHandlingException([new \RuntimeException('Delayed message exception')]); - } - - $decoratedDataPersister->persist($envelope, [])->willThrow($exception); - - $this->shouldThrow(new \RuntimeException('Delayed message exception'))->during('persist', [$envelope, []]); - } - - function it_unwraps_handler_failed_exception(ContextAwareDataPersisterInterface $decoratedDataPersister): void - { - $completeOrder = new CompleteOrder('ThankYou'); - $completeOrder->setOrderTokenValue('ORDERTOKEN'); - $envelope = new Envelope($completeOrder); - - $decoratedDataPersister->persist($envelope, [])->willThrow( - new HandlerFailedException( - $envelope, - [new \RuntimeException('Delayed message exception')], - ), - ); - - $this->shouldThrow(new \RuntimeException('Delayed message exception'))->during('persist', [$envelope, []]); - } - - function it_calls_remove_method_from_decorated_data_presister( - ContextAwareDataPersisterInterface $decoratedDataPersister, - ): void { - $decoratedDataPersister->remove(Argument::any(), [])->shouldBeCalled(); - - $this->remove(Argument::any(), []); - } -} diff --git a/src/Sylius/Bundle/ApiBundle/spec/StateProcessor/Common/MessengerPersistProcessorSpec.php b/src/Sylius/Bundle/ApiBundle/spec/StateProcessor/Common/MessengerPersistProcessorSpec.php new file mode 100644 index 0000000000..cf00ef4f58 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/spec/StateProcessor/Common/MessengerPersistProcessorSpec.php @@ -0,0 +1,70 @@ +beConstructedWith($decoratedProcessor); + } + + function it_implements_processor_interface(): void + { + $this->shouldImplement(ProcessorInterface::class); + } + + function it_unwraps_delayed_message_handling_exception(ProcessorInterface $decoratedProcessor): void + { + $command = new CompleteOrder('ThankYou', 'token'); + $envelope = new Envelope($command); + $operation = new Post(); + + $exception = new DelayedMessageHandlingException([new \RuntimeException('Delayed message exception')], $envelope); + + $decoratedProcessor->process($envelope, $operation, [], [])->willThrow($exception); + + $this + ->shouldThrow(new \RuntimeException('Delayed message exception')) + ->during('process', [$envelope, $operation, [], []]) + ; + } + + function it_unwraps_handler_failed_exception(ProcessorInterface $decoratedProcessor): void + { + $command = new CompleteOrder('ThankYou', 'token'); + $envelope = new Envelope($command); + $operation = new Post(); + + $decoratedProcessor->process($envelope, $operation, [], [])->willThrow( + new HandlerFailedException( + $envelope, + [new \RuntimeException('Delayed message exception')], + ), + ); + + $this + ->shouldThrow(new \RuntimeException('Delayed message exception')) + ->during('process', [$envelope, $operation, [], []]) + ; + } +}