diff --git a/src/Symfony/Component/Messenger/Event/SendMessageToTransportsEvent.php b/src/Symfony/Component/Messenger/Event/SendMessageToTransportsEvent.php new file mode 100644 index 0000000000..a54622e83c --- /dev/null +++ b/src/Symfony/Component/Messenger/Event/SendMessageToTransportsEvent.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Messenger\Event; + +use Symfony\Component\EventDispatcher\Event; +use Symfony\Component\Messenger\Envelope; + +/** + * Event is dispatched before a message is sent to the transport. + * + * The event is *only* dispatched if the message will actually + * be sent to at least one transport. If the message is sent + * to multiple transports, the message is dispatched only one time. + * + * @author Ryan Weaver + */ +class SendMessageToTransportsEvent extends Event +{ + private $envelope; + + public function __construct(Envelope $envelope) + { + $this->envelope = $envelope; + } + + public function getEnvelope(): Envelope + { + return $this->envelope; + } + + public function setEnvelope(Envelope $envelope) + { + $this->envelope = $envelope; + } +} diff --git a/src/Symfony/Component/Messenger/Middleware/SendMessageMiddleware.php b/src/Symfony/Component/Messenger/Middleware/SendMessageMiddleware.php index bc6f71761c..b978a9c1cb 100644 --- a/src/Symfony/Component/Messenger/Middleware/SendMessageMiddleware.php +++ b/src/Symfony/Component/Messenger/Middleware/SendMessageMiddleware.php @@ -13,7 +13,9 @@ namespace Symfony\Component\Messenger\Middleware; use Psr\Log\LoggerAwareTrait; use Psr\Log\NullLogger; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Messenger\Envelope; +use Symfony\Component\Messenger\Event\SendMessageToTransportsEvent; use Symfony\Component\Messenger\Stamp\ReceivedStamp; use Symfony\Component\Messenger\Stamp\RedeliveryStamp; use Symfony\Component\Messenger\Stamp\SentStamp; @@ -30,10 +32,12 @@ class SendMessageMiddleware implements MiddlewareInterface use LoggerAwareTrait; private $sendersLocator; + private $eventDispatcher; - public function __construct(SendersLocatorInterface $sendersLocator) + public function __construct(SendersLocatorInterface $sendersLocator, EventDispatcherInterface $eventDispatcher = null) { $this->sendersLocator = $sendersLocator; + $this->eventDispatcher = $eventDispatcher; $this->logger = new NullLogger(); } @@ -58,7 +62,15 @@ class SendMessageMiddleware implements MiddlewareInterface /** @var RedeliveryStamp|null $redeliveryStamp */ $redeliveryStamp = $envelope->last(RedeliveryStamp::class); - foreach ($this->sendersLocator->getSenders($envelope, $handle) as $alias => $sender) { + $senders = \iterator_to_array($this->sendersLocator->getSenders($envelope, $handle)); + + if (null !== $this->eventDispatcher && \count($senders) > 0) { + $event = new SendMessageToTransportsEvent($envelope); + $this->eventDispatcher->dispatch($event); + $envelope = $event->getEnvelope(); + } + + foreach ($senders as $alias => $sender) { // on redelivery, only deliver to the given sender if (null !== $redeliveryStamp && !$redeliveryStamp->shouldRedeliverToSender(\get_class($sender), $alias)) { continue; diff --git a/src/Symfony/Component/Messenger/Tests/Middleware/SendMessageMiddlewareTest.php b/src/Symfony/Component/Messenger/Tests/Middleware/SendMessageMiddlewareTest.php index be43799bf8..8237838a3a 100644 --- a/src/Symfony/Component/Messenger/Tests/Middleware/SendMessageMiddlewareTest.php +++ b/src/Symfony/Component/Messenger/Tests/Middleware/SendMessageMiddlewareTest.php @@ -11,7 +11,9 @@ namespace Symfony\Component\Messenger\Tests\Middleware; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Messenger\Envelope; +use Symfony\Component\Messenger\Event\SendMessageToTransportsEvent; use Symfony\Component\Messenger\Middleware\SendMessageMiddleware; use Symfony\Component\Messenger\Stamp\ReceivedStamp; use Symfony\Component\Messenger\Stamp\RedeliveryStamp; @@ -202,4 +204,24 @@ class SendMessageMiddlewareTest extends MiddlewareTestCase $this->assertNull($envelope->last(SentStamp::class), 'it does not add sent stamp for received messages'); } + + public function testItDispatchesTheEventOnceTime() + { + $envelope = new Envelope(new DummyMessage('original envelope')); + + $dispatcher = $this->createMock(EventDispatcherInterface::class); + $dispatcher->expects($this->once()) + ->method('dispatch') + ->with(new SendMessageToTransportsEvent($envelope)); + + $sender1 = $this->getMockBuilder(SenderInterface::class)->getMock(); + $sender2 = $this->getMockBuilder(SenderInterface::class)->getMock(); + + $middleware = new SendMessageMiddleware(new SendersLocator([DummyMessage::class => [$sender1, $sender2]]), $dispatcher); + + $sender1->expects($this->once())->method('send')->willReturn($envelope); + $sender2->expects($this->once())->method('send')->willReturn($envelope); + + $middleware->handle($envelope, $this->getStackMock(false)); + } }