From d081267921156ce73884ef13d96a2e74170856e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1chym=20Tou=C5=A1ek?= Date: Sun, 14 Aug 2022 20:21:28 +0200 Subject: [PATCH] Add HandlerArgumentsStamp --- .../Middleware/HandleMessageMiddleware.php | 18 +++++++- .../Messenger/Stamp/HandlerArgumentsStamp.php | 28 +++++++++++++ .../HandleMessageMiddlewareTest.php | 42 +++++++++++++++++++ 3 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Component/Messenger/Stamp/HandlerArgumentsStamp.php diff --git a/src/Symfony/Component/Messenger/Middleware/HandleMessageMiddleware.php b/src/Symfony/Component/Messenger/Middleware/HandleMessageMiddleware.php index 537c2845826de..5c814d5467e1d 100644 --- a/src/Symfony/Component/Messenger/Middleware/HandleMessageMiddleware.php +++ b/src/Symfony/Component/Messenger/Middleware/HandleMessageMiddleware.php @@ -23,6 +23,7 @@ use Symfony\Component\Messenger\Stamp\AckStamp; use Symfony\Component\Messenger\Stamp\FlushBatchHandlersStamp; use Symfony\Component\Messenger\Stamp\HandledStamp; +use Symfony\Component\Messenger\Stamp\HandlerArgumentsStamp; use Symfony\Component\Messenger\Stamp\NoAutoAckStamp; /** @@ -78,7 +79,7 @@ public function handle(Envelope $envelope, StackInterface $stack): Envelope $ackStamp->ack($envelope, $e); }); - $result = $handler($message, $ack); + $result = $this->callHandler($handler, $message, $ack, $envelope->last(HandlerArgumentsStamp::class)); if (!\is_int($result) || 0 > $result) { throw new LogicException(sprintf('A handler implementing BatchHandlerInterface must return the size of the current batch as a positive integer, "%s" returned from "%s".', \is_int($result) ? $result : get_debug_type($result), get_debug_type($batchHandler))); @@ -92,7 +93,7 @@ public function handle(Envelope $envelope, StackInterface $stack): Envelope $result = $ack->getResult(); } } else { - $result = $handler($message); + $result = $this->callHandler($handler, $message, null, $envelope->last(HandlerArgumentsStamp::class)); } $handledStamp = HandledStamp::fromDescriptor($handlerDescriptor, $result); @@ -142,4 +143,17 @@ private function messageHasAlreadyBeenHandled(Envelope $envelope, HandlerDescrip return false; } + + private function callHandler(callable $handler, object $message, ?Acknowledger $ack, ?HandlerArgumentsStamp $handlerArgumentsStamp): mixed + { + $arguments = [$message]; + if (null !== $ack) { + $arguments[] = $ack; + } + if (null !== $handlerArgumentsStamp) { + $arguments = [...$arguments, ...$handlerArgumentsStamp->getAdditionalArguments()]; + } + + return $handler(...$arguments); + } } diff --git a/src/Symfony/Component/Messenger/Stamp/HandlerArgumentsStamp.php b/src/Symfony/Component/Messenger/Stamp/HandlerArgumentsStamp.php new file mode 100644 index 0000000000000..d8142394508b4 --- /dev/null +++ b/src/Symfony/Component/Messenger/Stamp/HandlerArgumentsStamp.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Messenger\Stamp; + +/** + * @author Jáchym Toušek + */ +final class HandlerArgumentsStamp implements NonSendableStampInterface +{ + public function __construct( + private array $additionalArguments, + ) { + } + + public function getAdditionalArguments() + { + return $this->additionalArguments; + } +} diff --git a/src/Symfony/Component/Messenger/Tests/Middleware/HandleMessageMiddlewareTest.php b/src/Symfony/Component/Messenger/Tests/Middleware/HandleMessageMiddlewareTest.php index 503800e1cd6e1..c36274b12fe0a 100644 --- a/src/Symfony/Component/Messenger/Tests/Middleware/HandleMessageMiddlewareTest.php +++ b/src/Symfony/Component/Messenger/Tests/Middleware/HandleMessageMiddlewareTest.php @@ -24,6 +24,7 @@ use Symfony\Component\Messenger\Middleware\StackMiddleware; use Symfony\Component\Messenger\Stamp\AckStamp; use Symfony\Component\Messenger\Stamp\HandledStamp; +use Symfony\Component\Messenger\Stamp\HandlerArgumentsStamp; use Symfony\Component\Messenger\Stamp\NoAutoAckStamp; use Symfony\Component\Messenger\Test\Middleware\MiddlewareTestCase; use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage; @@ -261,6 +262,40 @@ private function process(array $jobs): void $this->assertSame([$message], $handler->processedMessages); } + + public function testHandlerArgumentsStamp() + { + $message = new DummyMessage('Hey'); + $envelope = new Envelope($message); + $envelope = $envelope->with(new HandlerArgumentsStamp(['additional argument'])); + + $handler = $this->createPartialMock(HandleMessageMiddlewareTestCallable::class, ['__invoke']); + + $middleware = new HandleMessageMiddleware(new HandlersLocator([ + DummyMessage::class => [$handler], + ])); + + $handler->expects($this->once())->method('__invoke')->with($message, 'additional argument'); + + $middleware->handle($envelope, $this->getStackMock()); + } + + public function testHandlerArgumentsStampNamedArgument() + { + $message = new DummyMessage('Hey'); + $envelope = new Envelope($message); + $envelope = $envelope->with(new HandlerArgumentsStamp(['namedArgument' => 'additional named argument'])); + + $handler = $this->createPartialMock(HandleMessageMiddlewareNamedArgumentTestCallable::class, ['__invoke']); + + $middleware = new HandleMessageMiddleware(new HandlersLocator([ + DummyMessage::class => [$handler], + ])); + + $handler->expects($this->once())->method('__invoke')->with($message, 'additional named argument'); + + $middleware->handle($envelope, $this->getStackMock()); + } } class HandleMessageMiddlewareTestCallable @@ -269,3 +304,10 @@ public function __invoke() { } } + +class HandleMessageMiddlewareNamedArgumentTestCallable +{ + public function __invoke(object $message, $namedArgument) + { + } +}