- *
- * @experimental in 4.2
- */
-class ChainHandler
-{
- /**
- * @var callable[]
- */
- private $handlers;
-
- /**
- * @param callable[] $handlers
- */
- public function __construct(array $handlers)
- {
- if (!$handlers) {
- throw new InvalidArgumentException('A collection of message handlers requires at least one handler.');
- }
-
- $this->handlers = $handlers;
- }
-
- public function __invoke($message)
- {
- foreach ($this->handlers as $handler) {
- $handler($message);
- }
- }
-}
diff --git a/src/Symfony/Component/Messenger/Handler/HandlersLocator.php b/src/Symfony/Component/Messenger/Handler/HandlersLocator.php
new file mode 100644
index 0000000000000..ffed08d7d2a08
--- /dev/null
+++ b/src/Symfony/Component/Messenger/Handler/HandlersLocator.php
@@ -0,0 +1,63 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Messenger\Handler;
+
+/**
+ * Maps a message to a list of handlers.
+ *
+ * @author Nicolas Grekas
+ *
+ * @experimental in 4.2
+ */
+class HandlersLocator implements HandlersLocatorInterface
+{
+ private $handlers;
+
+ /**
+ * @param callable[][] $handlers
+ */
+ public function __construct(array $handlers)
+ {
+ $this->handlers = $handlers;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getHandlers(string $name): iterable
+ {
+ $seen = array();
+
+ foreach (self::listTypes($name) as $type) {
+ foreach ($this->handlers[$type] ?? array() as $handler) {
+ if (!\in_array($handler, $seen, true)) {
+ yield $seen[] = $handler;
+ }
+ }
+ }
+ }
+
+ /**
+ * @internal
+ */
+ public static function listTypes(string $class): array
+ {
+ if (!class_exists($class, false)) {
+ return array($class => $class, '*' => '*');
+ }
+
+ return array($class => $class)
+ + class_parents($class)
+ + class_implements($class)
+ + array('*' => '*');
+ }
+}
diff --git a/src/Symfony/Component/Messenger/Handler/HandlersLocatorInterface.php b/src/Symfony/Component/Messenger/Handler/HandlersLocatorInterface.php
new file mode 100644
index 0000000000000..4f9b8e2bd45ae
--- /dev/null
+++ b/src/Symfony/Component/Messenger/Handler/HandlersLocatorInterface.php
@@ -0,0 +1,29 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Messenger\Handler;
+
+/**
+ * Maps a message to a list of handlers.
+ *
+ * @author Nicolas Grekas
+ *
+ * @experimental in 4.2
+ */
+interface HandlersLocatorInterface
+{
+ /**
+ * Returns the handlers for the given message name.
+ *
+ * @return iterable|callable[]
+ */
+ public function getHandlers(string $name): iterable;
+}
diff --git a/src/Symfony/Component/Messenger/Handler/Locator/AbstractHandlerLocator.php b/src/Symfony/Component/Messenger/Handler/Locator/AbstractHandlerLocator.php
deleted file mode 100644
index 0a96037e021f1..0000000000000
--- a/src/Symfony/Component/Messenger/Handler/Locator/AbstractHandlerLocator.php
+++ /dev/null
@@ -1,50 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Messenger\Handler\Locator;
-
-use Symfony\Component\Messenger\Envelope;
-
-/**
- * @author Miha Vrhovnik
- * @author Samuel Roze
- *
- * @internal
- *
- * @experimental in 4.2
- */
-abstract class AbstractHandlerLocator implements HandlerLocatorInterface
-{
- public function getHandler(Envelope $envelope): ?callable
- {
- $class = \get_class($envelope->getMessage());
-
- if ($handler = $this->getHandlerByName($class)) {
- return $handler;
- }
-
- foreach (class_parents($class) as $name) {
- if ($handler = $this->getHandlerByName($name)) {
- return $handler;
- }
- }
-
- foreach (class_implements($class) as $name) {
- if ($handler = $this->getHandlerByName($name)) {
- return $handler;
- }
- }
-
- return null;
- }
-
- abstract protected function getHandlerByName(string $name): ?callable;
-}
diff --git a/src/Symfony/Component/Messenger/Handler/Locator/ContainerHandlerLocator.php b/src/Symfony/Component/Messenger/Handler/Locator/ContainerHandlerLocator.php
deleted file mode 100644
index d94bbc482cc77..0000000000000
--- a/src/Symfony/Component/Messenger/Handler/Locator/ContainerHandlerLocator.php
+++ /dev/null
@@ -1,38 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Messenger\Handler\Locator;
-
-use Psr\Container\ContainerInterface;
-
-/**
- * @author Miha Vrhovnik
- * @author Samuel Roze
- *
- * @experimental in 4.2
- */
-class ContainerHandlerLocator extends AbstractHandlerLocator
-{
- private $container;
-
- public function __construct(ContainerInterface $container)
- {
- $this->container = $container;
- }
-
- /**
- * {@inheritdoc}
- */
- protected function getHandlerByName(string $name): ?callable
- {
- return $this->container->has($name) ? $this->container->get($name) : null;
- }
-}
diff --git a/src/Symfony/Component/Messenger/Handler/Locator/HandlerLocator.php b/src/Symfony/Component/Messenger/Handler/Locator/HandlerLocator.php
deleted file mode 100644
index 59ae29a4c4e78..0000000000000
--- a/src/Symfony/Component/Messenger/Handler/Locator/HandlerLocator.php
+++ /dev/null
@@ -1,38 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Messenger\Handler\Locator;
-
-/**
- * @author Samuel Roze
- *
- * @experimental in 4.2
- */
-class HandlerLocator extends AbstractHandlerLocator
-{
- /**
- * Maps a message (its class) to a given handler.
- */
- private $messageToHandlerMapping;
-
- public function __construct(array $messageToHandlerMapping = array())
- {
- $this->messageToHandlerMapping = $messageToHandlerMapping;
- }
-
- /**
- * {@inheritdoc}
- */
- protected function getHandlerByName(string $name): ?callable
- {
- return $this->messageToHandlerMapping[$name] ?? null;
- }
-}
diff --git a/src/Symfony/Component/Messenger/Handler/Locator/HandlerLocatorInterface.php b/src/Symfony/Component/Messenger/Handler/Locator/HandlerLocatorInterface.php
deleted file mode 100644
index e902d39079e80..0000000000000
--- a/src/Symfony/Component/Messenger/Handler/Locator/HandlerLocatorInterface.php
+++ /dev/null
@@ -1,27 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Messenger\Handler\Locator;
-
-use Symfony\Component\Messenger\Envelope;
-
-/**
- * @author Samuel Roze
- *
- * @experimental in 4.2
- */
-interface HandlerLocatorInterface
-{
- /**
- * Returns the handler for the given message.
- */
- public function getHandler(Envelope $envelope): ?callable;
-}
diff --git a/src/Symfony/Component/Messenger/Middleware/HandleMessageMiddleware.php b/src/Symfony/Component/Messenger/Middleware/HandleMessageMiddleware.php
index 510631c466cd2..8096020c15c50 100644
--- a/src/Symfony/Component/Messenger/Middleware/HandleMessageMiddleware.php
+++ b/src/Symfony/Component/Messenger/Middleware/HandleMessageMiddleware.php
@@ -13,7 +13,7 @@
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Exception\NoHandlerForMessageException;
-use Symfony\Component\Messenger\Handler\Locator\HandlerLocatorInterface;
+use Symfony\Component\Messenger\Handler\HandlersLocatorInterface;
/**
* @author Samuel Roze
@@ -22,12 +22,12 @@
*/
class HandleMessageMiddleware implements MiddlewareInterface
{
- private $messageHandlerLocator;
+ private $handlersLocator;
private $allowNoHandlers;
- public function __construct(HandlerLocatorInterface $messageHandlerLocator, bool $allowNoHandlers = false)
+ public function __construct(HandlersLocatorInterface $handlersLocator, bool $allowNoHandlers = false)
{
- $this->messageHandlerLocator = $messageHandlerLocator;
+ $this->handlersLocator = $handlersLocator;
$this->allowNoHandlers = $allowNoHandlers;
}
@@ -38,10 +38,14 @@ public function __construct(HandlerLocatorInterface $messageHandlerLocator, bool
*/
public function handle(Envelope $envelope, StackInterface $stack): Envelope
{
- if (null !== $handler = $this->messageHandlerLocator->getHandler($envelope)) {
- $handler($envelope->getMessage());
- } elseif (!$this->allowNoHandlers) {
- throw new NoHandlerForMessageException(sprintf('No handler for message "%s".', \get_class($envelope->getMessage())));
+ $handler = null;
+ $message = $envelope->getMessage();
+ $name = $envelope->getMessageName();
+ foreach ($this->handlersLocator->getHandlers($name) as $handler) {
+ $handler($message);
+ }
+ if (null === $handler && !$this->allowNoHandlers) {
+ throw new NoHandlerForMessageException(sprintf('No handler for message "%s".', $name));
}
return $stack->next()->handle($envelope, $stack);
diff --git a/src/Symfony/Component/Messenger/Middleware/LoggingMiddleware.php b/src/Symfony/Component/Messenger/Middleware/LoggingMiddleware.php
index 16010b3be546d..37b03ea703246 100644
--- a/src/Symfony/Component/Messenger/Middleware/LoggingMiddleware.php
+++ b/src/Symfony/Component/Messenger/Middleware/LoggingMiddleware.php
@@ -36,20 +36,20 @@ public function handle(Envelope $envelope, StackInterface $stack): Envelope
$message = $envelope->getMessage();
$context = array(
'message' => $message,
- 'name' => \get_class($message),
+ 'name' => $envelope->getMessageName(),
);
- $this->logger->debug('Starting handling message {name}', $context);
+ $this->logger->debug('Starting handling message "{name}"', $context);
try {
$envelope = $stack->next()->handle($envelope, $stack);
} catch (\Throwable $e) {
$context['exception'] = $e;
- $this->logger->warning('An exception occurred while handling message {name}', $context);
+ $this->logger->warning('An exception occurred while handling message "{name}"', $context);
throw $e;
}
- $this->logger->debug('Finished handling message {name}', $context);
+ $this->logger->debug('Finished handling message "{name}"', $context);
return $envelope;
}
diff --git a/src/Symfony/Component/Messenger/Middleware/SendMessageMiddleware.php b/src/Symfony/Component/Messenger/Middleware/SendMessageMiddleware.php
index 64608d2d5a189..f5e7a90a53fbb 100644
--- a/src/Symfony/Component/Messenger/Middleware/SendMessageMiddleware.php
+++ b/src/Symfony/Component/Messenger/Middleware/SendMessageMiddleware.php
@@ -13,8 +13,7 @@
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Stamp\ReceivedStamp;
-use Symfony\Component\Messenger\Transport\Sender\Locator\AbstractSenderLocator;
-use Symfony\Component\Messenger\Transport\Sender\Locator\SenderLocatorInterface;
+use Symfony\Component\Messenger\Transport\Sender\SendersLocatorInterface;
/**
* @author Samuel Roze
@@ -24,13 +23,11 @@
*/
class SendMessageMiddleware implements MiddlewareInterface
{
- private $senderLocator;
- private $messagesToSendAndHandleMapping;
+ private $sendersLocator;
- public function __construct(SenderLocatorInterface $senderLocator, array $messagesToSendAndHandleMapping = array())
+ public function __construct(SendersLocatorInterface $sendersLocator)
{
- $this->senderLocator = $senderLocator;
- $this->messagesToSendAndHandleMapping = $messagesToSendAndHandleMapping;
+ $this->sendersLocator = $sendersLocator;
}
/**
@@ -39,21 +36,21 @@ public function __construct(SenderLocatorInterface $senderLocator, array $messag
public function handle(Envelope $envelope, StackInterface $stack): Envelope
{
if ($envelope->get(ReceivedStamp::class)) {
- // It's a received message. Do not send it back:
+ // it's a received message, do not send it back
return $stack->next()->handle($envelope, $stack);
}
+ $handle = false;
+ $sender = null;
- $sender = $this->senderLocator->getSender($envelope);
-
- if ($sender) {
+ foreach ($this->sendersLocator->getSenders($envelope->getMessageName(), $handle) as $sender) {
$envelope = $sender->send($envelope);
+ }
- if (!AbstractSenderLocator::getValueFromMessageRouting($this->messagesToSendAndHandleMapping, $envelope)) {
- // message has no corresponding handler
- return $envelope;
- }
+ if (null === $sender || $handle) {
+ return $stack->next()->handle($envelope, $stack);
}
- return $stack->next()->handle($envelope, $stack);
+ // message should only be sent and not be handled by the next middleware
+ return $envelope;
}
}
diff --git a/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php b/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php
index 0795b2b179c33..7e89ba0991afd 100644
--- a/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php
+++ b/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php
@@ -12,7 +12,7 @@
namespace Symfony\Component\Messenger\Tests\DependencyInjection;
use PHPUnit\Framework\TestCase;
-use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
+use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use Symfony\Component\DependencyInjection\Compiler\ResolveChildDefinitionsPass;
use Symfony\Component\DependencyInjection\Compiler\ResolveClassPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -23,7 +23,7 @@
use Symfony\Component\Messenger\DataCollector\MessengerDataCollector;
use Symfony\Component\Messenger\DependencyInjection\MessengerPass;
use Symfony\Component\Messenger\Envelope;
-use Symfony\Component\Messenger\Handler\ChainHandler;
+use Symfony\Component\Messenger\Handler\HandlersLocator;
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;
use Symfony\Component\Messenger\Handler\MessageSubscriberInterface;
use Symfony\Component\Messenger\MessageBusInterface;
@@ -39,7 +39,6 @@
use Symfony\Component\Messenger\Tests\Fixtures\MultipleBusesMessageHandler;
use Symfony\Component\Messenger\Tests\Fixtures\SecondMessage;
use Symfony\Component\Messenger\Transport\AmqpExt\AmqpReceiver;
-use Symfony\Component\Messenger\Transport\AmqpExt\AmqpSender;
use Symfony\Component\Messenger\Transport\Receiver\ReceiverInterface;
class MessengerPassTest extends TestCase
@@ -64,14 +63,14 @@ public function testProcess()
$this->assertFalse($container->hasDefinition('messenger.middleware.debug.logging'));
- $handlerLocatorDefinition = $container->getDefinition($container->getDefinition("$busId.messenger.handler_resolver")->getArgument(0));
- $this->assertSame(ServiceLocator::class, $handlerLocatorDefinition->getClass());
+ $handlersLocatorDefinition = $container->getDefinition($busId.'.messenger.handlers_locator');
+ $this->assertSame(HandlersLocator::class, $handlersLocatorDefinition->getClass());
$this->assertEquals(
array(
- DummyMessage::class => new ServiceClosureArgument(new Reference(DummyHandler::class)),
- SecondMessage::class => new ServiceClosureArgument(new Reference(MissingArgumentTypeHandler::class)),
+ DummyMessage::class => new Reference("messenger.handlers.$busId.".DummyMessage::class),
+ SecondMessage::class => new Reference("messenger.handlers.$busId.".SecondMessage::class),
),
- $handlerLocatorDefinition->getArgument(0)
+ $handlersLocatorDefinition->getArgument(0)
);
$this->assertEquals(
@@ -84,12 +83,12 @@ public function testProcessHandlersByBus()
{
$container = $this->getContainerBuilder($commandBusId = 'command_bus');
$container->register($queryBusId = 'query_bus', MessageBusInterface::class)->setArgument(0, array())->addTag('messenger.bus');
- $container->register('messenger.middleware.call_message_handler', HandleMessageMiddleware::class)
+ $container->register('messenger.middleware.handle_message', HandleMessageMiddleware::class)
->addArgument(null)
->setAbstract(true)
;
- $middlewareHandlers = array(array('id' => 'call_message_handler'));
+ $middlewareHandlers = array(array('id' => 'handle_message'));
$container->setParameter($commandBusId.'.middleware', $middlewareHandlers);
$container->setParameter($queryBusId.'.middleware', $middlewareHandlers);
@@ -104,24 +103,24 @@ public function testProcessHandlersByBus()
(new ResolveClassPass())->process($container);
(new MessengerPass())->process($container);
- $commandBusHandlerLocatorDefinition = $container->getDefinition($container->getDefinition("$commandBusId.messenger.handler_resolver")->getArgument(0));
- $this->assertSame(ServiceLocator::class, $commandBusHandlerLocatorDefinition->getClass());
+ $commandBusHandlersLocatorDefinition = $container->getDefinition($commandBusId.'.messenger.handlers_locator');
+ $this->assertSame(HandlersLocator::class, $commandBusHandlersLocatorDefinition->getClass());
$this->assertEquals(
array(
- DummyCommand::class => new ServiceClosureArgument(new Reference(DummyCommandHandler::class)),
- MultipleBusesMessage::class => new ServiceClosureArgument(new Reference(MultipleBusesMessageHandler::class)),
+ MultipleBusesMessage::class => new Reference("messenger.handlers.$commandBusId.".MultipleBusesMessage::class),
+ DummyCommand::class => new Reference("messenger.handlers.$commandBusId.".DummyCommand::class),
),
- $commandBusHandlerLocatorDefinition->getArgument(0)
+ $commandBusHandlersLocatorDefinition->getArgument(0)
);
- $queryBusHandlerLocatorDefinition = $container->getDefinition($container->getDefinition("$queryBusId.messenger.handler_resolver")->getArgument(0));
- $this->assertSame(ServiceLocator::class, $queryBusHandlerLocatorDefinition->getClass());
+ $queryBusHandlersLocatorDefinition = $container->getDefinition($queryBusId.'.messenger.handlers_locator');
+ $this->assertSame(HandlersLocator::class, $queryBusHandlersLocatorDefinition->getClass());
$this->assertEquals(
array(
- DummyQuery::class => new ServiceClosureArgument(new Reference(DummyQueryHandler::class)),
- MultipleBusesMessage::class => new ServiceClosureArgument(new Reference(MultipleBusesMessageHandler::class)),
+ DummyQuery::class => new Reference("messenger.handlers.$queryBusId.".DummyQuery::class),
+ MultipleBusesMessage::class => new Reference("messenger.handlers.$queryBusId.".MultipleBusesMessage::class),
),
- $queryBusHandlerLocatorDefinition->getArgument(0)
+ $queryBusHandlersLocatorDefinition->getArgument(0)
);
}
@@ -153,18 +152,16 @@ public function testGetClassesFromTheHandlerSubscriberInterface()
(new MessengerPass())->process($container);
- $handlerLocatorDefinition = $container->getDefinition($container->getDefinition("$busId.messenger.handler_resolver")->getArgument(0));
- $handlerMapping = $handlerLocatorDefinition->getArgument(0);
+ $handlersMapping = $container->getDefinition($busId.'.messenger.handlers_locator')->getArgument(0);
- $this->assertArrayHasKey(DummyMessage::class, $handlerMapping);
- $this->assertEquals(new ServiceClosureArgument(new Reference(HandlerWithMultipleMessages::class)), $handlerMapping[DummyMessage::class]);
+ $this->assertArrayHasKey(DummyMessage::class, $handlersMapping);
+ $this->assertEquals(new Reference("messenger.handlers.$busId.".DummyMessage::class), $handlersMapping[DummyMessage::class]);
- $this->assertArrayHasKey(SecondMessage::class, $handlerMapping);
- $handlerReference = (string) $handlerMapping[SecondMessage::class]->getValues()[0];
- $definition = $container->getDefinition($handlerReference);
+ $this->assertArrayHasKey(SecondMessage::class, $handlersMapping);
+ $handlersDefinition = $container->getDefinition($handlersMapping[SecondMessage::class]);
- $this->assertSame(ChainHandler::class, $definition->getClass());
- $this->assertEquals(array(new Reference(PrioritizedHandler::class), new Reference(HandlerWithMultipleMessages::class)), $definition->getArgument(0));
+ $this->assertSame(RewindableGenerator::class, $handlersDefinition->getClass());
+ $this->assertEquals(array(new Reference(PrioritizedHandler::class), new Reference(HandlerWithMultipleMessages::class)), $handlersDefinition->getArgument(0)[0]);
}
public function testGetClassesAndMethodsAndPrioritiesFromTheSubscriber()
@@ -181,22 +178,20 @@ public function testGetClassesAndMethodsAndPrioritiesFromTheSubscriber()
(new MessengerPass())->process($container);
- $handlerLocatorDefinition = $container->getDefinition($container->getDefinition("$busId.messenger.handler_resolver")->getArgument(0));
- $handlerMapping = $handlerLocatorDefinition->getArgument(0);
+ $handlersMapping = $container->getDefinition($busId.'.messenger.handlers_locator')->getArgument(0);
- $this->assertArrayHasKey(DummyMessage::class, $handlerMapping);
- $this->assertArrayHasKey(SecondMessage::class, $handlerMapping);
+ $this->assertArrayHasKey(DummyMessage::class, $handlersMapping);
+ $this->assertArrayHasKey(SecondMessage::class, $handlersMapping);
- $dummyHandlerReference = (string) $handlerMapping[DummyMessage::class]->getValues()[0];
+ $dummyHandlerReference = $container->getDefinition($handlersMapping[DummyMessage::class])->getArgument(0)[0][0];
$dummyHandlerDefinition = $container->getDefinition($dummyHandlerReference);
$this->assertSame('callable', $dummyHandlerDefinition->getClass());
$this->assertEquals(array(new Reference(HandlerMappingMethods::class), 'dummyMethod'), $dummyHandlerDefinition->getArgument(0));
$this->assertSame(array('Closure', 'fromCallable'), $dummyHandlerDefinition->getFactory());
- $secondHandlerReference = (string) $handlerMapping[SecondMessage::class]->getValues()[0];
+ $secondHandlerReference = $container->getDefinition($handlersMapping[SecondMessage::class])->getArgument(0)[0][1];
$secondHandlerDefinition = $container->getDefinition($secondHandlerReference);
- $this->assertSame(ChainHandler::class, $secondHandlerDefinition->getClass());
- $this->assertEquals(new Reference(PrioritizedHandler::class), $secondHandlerDefinition->getArgument(0)[1]);
+ $this->assertSame(PrioritizedHandler::class, $secondHandlerDefinition->getClass());
}
/**
@@ -257,26 +252,6 @@ public function testItRegistersMultipleReceiversAndSetsTheReceiverNamesOnTheComm
$this->assertSame(array('message_bus'), $container->getDefinition('console.command.messenger_consume_messages')->getArgument(4));
}
- public function testItRegistersSenders()
- {
- $container = $this->getContainerBuilder();
- $container->register(AmqpSender::class, AmqpSender::class)->addTag('messenger.sender', array('alias' => 'amqp'));
-
- (new MessengerPass())->process($container);
-
- $this->assertEquals(array('amqp' => new Reference(AmqpSender::class), AmqpSender::class => new Reference(AmqpSender::class)), $container->getDefinition('messenger.sender_locator')->getArgument(0));
- }
-
- public function testItRegistersSenderWithoutTagName()
- {
- $container = $this->getContainerBuilder();
- $container->register(AmqpSender::class, AmqpSender::class)->addTag('messenger.sender');
-
- (new MessengerPass())->process($container);
-
- $this->assertEquals(array(AmqpSender::class => new Reference(AmqpSender::class)), $container->getDefinition('messenger.sender_locator')->getArgument(0));
- }
-
public function testItShouldNotThrowIfGeneratorIsReturnedInsteadOfArray()
{
$container = $this->getContainerBuilder($busId = 'message_bus');
@@ -287,15 +262,14 @@ public function testItShouldNotThrowIfGeneratorIsReturnedInsteadOfArray()
(new MessengerPass())->process($container);
- $handlerLocatorDefinition = $container->getDefinition($container->getDefinition("$busId.messenger.handler_resolver")->getArgument(0));
- $handlerMapping = $handlerLocatorDefinition->getArgument(0);
+ $handlersMapping = $container->getDefinition($busId.'.messenger.handlers_locator')->getArgument(0);
- $this->assertArrayHasKey(DummyMessage::class, $handlerMapping);
- $firstReference = $handlerMapping[DummyMessage::class]->getValues()[0];
+ $this->assertArrayHasKey(DummyMessage::class, $handlersMapping);
+ $firstReference = $container->getDefinition($handlersMapping[DummyMessage::class])->getArgument(0)[0][0];
$this->assertEquals(array(new Reference(HandlerWithGenerators::class), 'dummyMethod'), $container->getDefinition($firstReference)->getArgument(0));
- $this->assertArrayHasKey(SecondMessage::class, $handlerMapping);
- $secondReference = $handlerMapping[SecondMessage::class]->getValues()[0];
+ $this->assertArrayHasKey(SecondMessage::class, $handlersMapping);
+ $secondReference = $container->getDefinition($handlersMapping[SecondMessage::class])->getArgument(0)[0][0];
$this->assertEquals(array(new Reference(HandlerWithGenerators::class), 'secondMessage'), $container->getDefinition($secondReference)->getArgument(0));
}
@@ -311,18 +285,16 @@ public function testItRegistersHandlersOnDifferentBuses()
(new MessengerPass())->process($container);
- $eventsHandlerLocatorDefinition = $container->getDefinition($container->getDefinition($eventsBusId.'.messenger.handler_resolver')->getArgument(0));
- $eventsHandlerMapping = $eventsHandlerLocatorDefinition->getArgument(0);
+ $eventsHandlerMapping = $container->getDefinition($eventsBusId.'.messenger.handlers_locator')->getArgument(0);
$this->assertEquals(array(DummyMessage::class), array_keys($eventsHandlerMapping));
- $firstReference = $eventsHandlerMapping[DummyMessage::class]->getValues()[0];
+ $firstReference = $container->getDefinition($eventsHandlerMapping[DummyMessage::class])->getArgument(0)[0][0];
$this->assertEquals(array(new Reference(HandlerOnSpecificBuses::class), 'dummyMethodForEvents'), $container->getDefinition($firstReference)->getArgument(0));
- $commandsHandlerLocatorDefinition = $container->getDefinition($container->getDefinition($commandsBusId.'.messenger.handler_resolver')->getArgument(0));
- $commandsHandlerMapping = $commandsHandlerLocatorDefinition->getArgument(0);
+ $commandsHandlerMapping = $container->getDefinition($commandsBusId.'.messenger.handlers_locator')->getArgument(0);
$this->assertEquals(array(DummyMessage::class), array_keys($commandsHandlerMapping));
- $firstReference = $commandsHandlerMapping[DummyMessage::class]->getValues()[0];
+ $firstReference = $container->getDefinition($commandsHandlerMapping[DummyMessage::class])->getArgument(0)[0][0];
$this->assertEquals(array(new Reference(HandlerOnSpecificBuses::class), 'dummyMethodForCommands'), $container->getDefinition($firstReference)->getArgument(0));
}
@@ -343,20 +315,7 @@ public function testItThrowsAnExceptionOnUnknownBus()
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
- * @expectedExceptionMessage Invalid sender "app.messenger.sender": class "Symfony\Component\Messenger\Tests\DependencyInjection\InvalidSender" must implement interface "Symfony\Component\Messenger\Transport\Sender\SenderInterface".
- */
- public function testItDoesNotRegisterInvalidSender()
- {
- $container = $this->getContainerBuilder();
- $container->register('app.messenger.sender', InvalidSender::class)
- ->addTag('messenger.sender');
-
- (new MessengerPass())->process($container);
- }
-
- /**
- * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
- * @expectedExceptionMessage Invalid handler service "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessageHandler": message class "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessage" used as argument type in method "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessageHandler::__invoke()" does not exist.
+ * @expectedExceptionMessage Invalid handler service "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessageHandler": class or interface "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessage" used as argument type in method "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessageHandler::__invoke()" not found.
*/
public function testUndefinedMessageClassForHandler()
{
@@ -371,7 +330,7 @@ public function testUndefinedMessageClassForHandler()
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
- * @expectedExceptionMessage Invalid handler service "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessageHandlerViaHandlerInterface": message class "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessage" used as argument type in method "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessageHandlerViaHandlerInterface::__invoke()" does not exist.
+ * @expectedExceptionMessage Invalid handler service "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessageHandlerViaHandlerInterface": class or interface "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessage" used as argument type in method "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessageHandlerViaHandlerInterface::__invoke()" not found.
*/
public function testUndefinedMessageClassForHandlerImplementingMessageHandlerInterface()
{
@@ -386,7 +345,7 @@ public function testUndefinedMessageClassForHandlerImplementingMessageHandlerInt
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
- * @expectedExceptionMessage Invalid handler service "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessageHandlerViaSubscriberInterface": message class "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessage" returned by method "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessageHandlerViaSubscriberInterface::getHandledMessages()" does not exist.
+ * @expectedExceptionMessage Invalid handler service "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessageHandlerViaSubscriberInterface": class or interface "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessage" returned by method "Symfony\Component\Messenger\Tests\DependencyInjection\UndefinedMessageHandlerViaSubscriberInterface::getHandledMessages()" not found.
*/
public function testUndefinedMessageClassForHandlerImplementingMessageSubscriberInterface()
{
@@ -498,7 +457,7 @@ public function testRegistersMiddlewareFromServices()
$container->setParameter($middlewareParameter = $fooBusId.'.middleware', array(
array('id' => UselessMiddleware::class),
- array('id' => 'middleware_with_factory', 'arguments' => array('foo', 'bar')),
+ array('id' => 'middleware_with_factory', 'arguments' => array('index_0' => 'foo', 'bar')),
array('id' => 'middleware_with_factory_using_default'),
));
@@ -529,7 +488,7 @@ public function testRegistersMiddlewareFromServices()
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
- * @expectedExceptionMessage Invalid middleware "not_defined_middleware": define such service to be able to use it.
+ * @expectedExceptionMessage Invalid middleware: service "not_defined_middleware" not found.
*/
public function testCannotRegistersAnUndefinedMiddleware()
{
@@ -561,14 +520,14 @@ public function testItRegistersTheDebugCommand()
$container = $this->getContainerBuilder($commandBusId = 'command_bus');
$container->register($queryBusId = 'query_bus', MessageBusInterface::class)->setArgument(0, array())->addTag('messenger.bus');
$container->register($emptyBus = 'empty_bus', MessageBusInterface::class)->setArgument(0, array())->addTag('messenger.bus');
- $container->register('messenger.middleware.call_message_handler', HandleMessageMiddleware::class)
+ $container->register('messenger.middleware.handle_message', HandleMessageMiddleware::class)
->addArgument(null)
->setAbstract(true)
;
$container->register('console.command.messenger_debug', DebugCommand::class)->addArgument(array());
- $middlewareHandlers = array(array('id' => 'call_message_handler'));
+ $middlewareHandlers = array(array('id' => 'handle_message'));
$container->setParameter($commandBusId.'.middleware', $middlewareHandlers);
$container->setParameter($queryBusId.'.middleware', $middlewareHandlers);
@@ -606,11 +565,6 @@ private function getContainerBuilder(string $busId = 'message_bus'): ContainerBu
$container->setAlias('message_bus', $busId);
}
- $container
- ->register('messenger.sender_locator', ServiceLocator::class)
- ->addArgument(new Reference('service_container'))
- ;
-
$container->register('messenger.receiver_locator', ServiceLocator::class)
->addArgument(new Reference('service_container'))
;
diff --git a/src/Symfony/Component/Messenger/Tests/Handler/ChainHandlerTest.php b/src/Symfony/Component/Messenger/Tests/Handler/ChainHandlerTest.php
deleted file mode 100644
index 5dc293e7e26b4..0000000000000
--- a/src/Symfony/Component/Messenger/Tests/Handler/ChainHandlerTest.php
+++ /dev/null
@@ -1,48 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Messenger\Tests\Handler;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Messenger\Handler\ChainHandler;
-use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
-
-class ChainHandlerTest extends TestCase
-{
- public function testItCallsTheHandlers()
- {
- $message = new DummyMessage('Hey');
-
- $handler1 = $this->createPartialMock(\stdClass::class, array('__invoke'));
- $handler1
- ->expects($this->once())
- ->method('__invoke')
- ->with($message)
- ;
- $handler2 = $this->createPartialMock(\stdClass::class, array('__invoke'));
- $handler2
- ->expects($this->once())
- ->method('__invoke')
- ->with($message)
- ;
-
- (new ChainHandler(array($handler1, $handler2)))($message);
- }
-
- /**
- * @expectedException \InvalidArgumentException
- * @expectedExceptionMessage A collection of message handlers requires at least one handler.
- */
- public function testInvalidArgumentExceptionOnEmptyHandlers()
- {
- new ChainHandler(array());
- }
-}
diff --git a/src/Symfony/Component/Messenger/Tests/Handler/Locator/ContainerHandlerLocatorTest.php b/src/Symfony/Component/Messenger/Tests/Handler/Locator/ContainerHandlerLocatorTest.php
deleted file mode 100644
index e9147e50b7b57..0000000000000
--- a/src/Symfony/Component/Messenger/Tests/Handler/Locator/ContainerHandlerLocatorTest.php
+++ /dev/null
@@ -1,59 +0,0 @@
-set(DummyMessage::class, $handler);
-
- $locator = new ContainerHandlerLocator($container);
- $resolvedHandler = $locator->getHandler(new Envelope(new DummyMessage('Hey')));
-
- $this->assertSame($handler, $resolvedHandler);
- }
-
- public function testNoHandlersReturnsNull()
- {
- $locator = new ContainerHandlerLocator(new Container());
- $this->assertNull($locator->getHandler(new Envelope(new DummyMessage('Hey'))));
- }
-
- public function testGetHandlerViaInterface()
- {
- $handler = function () {};
-
- $container = new Container();
- $container->set(DummyMessageInterface::class, $handler);
-
- $locator = new ContainerHandlerLocator($container);
- $resolvedHandler = $locator->getHandler(new Envelope(new DummyMessage('Hey')));
-
- $this->assertSame($handler, $resolvedHandler);
- }
-
- public function testGetHandlerViaParentClass()
- {
- $handler = function () {};
-
- $container = new Container();
- $container->set(DummyMessage::class, $handler);
-
- $locator = new ContainerHandlerLocator($container);
- $resolvedHandler = $locator->getHandler(new Envelope(new ChildDummyMessage('Hey')));
-
- $this->assertSame($handler, $resolvedHandler);
- }
-}
diff --git a/src/Symfony/Component/Messenger/Tests/Middleware/HandleMessageMiddlewareTest.php b/src/Symfony/Component/Messenger/Tests/Middleware/HandleMessageMiddlewareTest.php
index b4ea0d5b37d0f..92512c9b8ce99 100644
--- a/src/Symfony/Component/Messenger/Tests/Middleware/HandleMessageMiddlewareTest.php
+++ b/src/Symfony/Component/Messenger/Tests/Middleware/HandleMessageMiddlewareTest.php
@@ -12,7 +12,7 @@
namespace Symfony\Component\Messenger\Tests\Middleware;
use Symfony\Component\Messenger\Envelope;
-use Symfony\Component\Messenger\Handler\Locator\HandlerLocator;
+use Symfony\Component\Messenger\Handler\HandlersLocator;
use Symfony\Component\Messenger\Middleware\HandleMessageMiddleware;
use Symfony\Component\Messenger\Middleware\StackMiddleware;
use Symfony\Component\Messenger\Test\Middleware\MiddlewareTestCase;
@@ -27,8 +27,8 @@ public function testItCallsTheHandlerAndNextMiddleware()
$handler = $this->createPartialMock(\stdClass::class, array('__invoke'));
- $middleware = new HandleMessageMiddleware(new HandlerLocator(array(
- DummyMessage::class => $handler,
+ $middleware = new HandleMessageMiddleware(new HandlersLocator(array(
+ DummyMessage::class => array($handler),
)));
$handler->expects($this->once())->method('__invoke')->with($message);
@@ -42,14 +42,14 @@ public function testItCallsTheHandlerAndNextMiddleware()
*/
public function testThrowsNoHandlerException()
{
- $middleware = new HandleMessageMiddleware(new HandlerLocator(array()));
+ $middleware = new HandleMessageMiddleware(new HandlersLocator(array()));
$middleware->handle(new Envelope(new DummyMessage('Hey')), new StackMiddleware());
}
public function testAllowNoHandlers()
{
- $middleware = new HandleMessageMiddleware(new HandlerLocator(array()), true);
+ $middleware = new HandleMessageMiddleware(new HandlersLocator(array()), true);
$this->assertInstanceOf(Envelope::class, $middleware->handle(new Envelope(new DummyMessage('Hey')), new StackMiddleware()));
}
diff --git a/src/Symfony/Component/Messenger/Tests/Middleware/SendMessageMiddlewareTest.php b/src/Symfony/Component/Messenger/Tests/Middleware/SendMessageMiddlewareTest.php
index da377dfb950f6..50c14617e87f5 100644
--- a/src/Symfony/Component/Messenger/Tests/Middleware/SendMessageMiddlewareTest.php
+++ b/src/Symfony/Component/Messenger/Tests/Middleware/SendMessageMiddlewareTest.php
@@ -18,8 +18,8 @@
use Symfony\Component\Messenger\Tests\Fixtures\ChildDummyMessage;
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessageInterface;
-use Symfony\Component\Messenger\Transport\Sender\Locator\SenderLocatorInterface;
use Symfony\Component\Messenger\Transport\Sender\SenderInterface;
+use Symfony\Component\Messenger\Transport\Sender\SendersLocator;
class SendMessageMiddlewareTest extends MiddlewareTestCase
{
@@ -29,7 +29,7 @@ public function testItSendsTheMessageToAssignedSender()
$envelope = new Envelope($message);
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();
- $middleware = new SendMessageMiddleware(new InMemorySenderLocator($sender));
+ $middleware = new SendMessageMiddleware(new SendersLocator(array(DummyMessage::class => array($sender))));
$sender->expects($this->once())->method('send')->with($envelope)->willReturn($envelope);
@@ -38,10 +38,10 @@ public function testItSendsTheMessageToAssignedSender()
public function testItSendsTheMessageToAssignedSenderWithPreWrappedMessage()
{
- $envelope = new Envelope(new DummyMessage('Hey'));
+ $envelope = new Envelope(new ChildDummyMessage('Hey'));
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();
- $middleware = new SendMessageMiddleware(new InMemorySenderLocator($sender));
+ $middleware = new SendMessageMiddleware(new SendersLocator(array(DummyMessage::class => array($sender))));
$sender->expects($this->once())->method('send')->with($envelope)->willReturn($envelope);
@@ -54,9 +54,9 @@ public function testItAlsoCallsTheNextMiddlewareBasedOnTheMessageClass()
$envelope = new Envelope($message);
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();
- $middleware = new SendMessageMiddleware(new InMemorySenderLocator($sender), array(
+ $middleware = new SendMessageMiddleware(new SendersLocator(array('*' => array($sender)), array(
DummyMessage::class => true,
- ));
+ )));
$sender->expects($this->once())->method('send')->with($envelope)->willReturn($envelope);
@@ -69,9 +69,9 @@ public function testItAlsoCallsTheNextMiddlewareBasedOnTheMessageParentClass()
$envelope = new Envelope($message);
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();
- $middleware = new SendMessageMiddleware(new InMemorySenderLocator($sender), array(
+ $middleware = new SendMessageMiddleware(new SendersLocator(array('*' => array($sender)), array(
DummyMessage::class => true,
- ));
+ )));
$sender->expects($this->once())->method('send')->with($envelope)->willReturn($envelope);
@@ -84,9 +84,9 @@ public function testItAlsoCallsTheNextMiddlewareBasedOnTheMessageInterface()
$envelope = new Envelope($message);
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();
- $middleware = new SendMessageMiddleware(new InMemorySenderLocator($sender), array(
+ $middleware = new SendMessageMiddleware(new SendersLocator(array('*' => array($sender)), array(
DummyMessageInterface::class => true,
- ));
+ )));
$sender->expects($this->once())->method('send')->with($envelope)->willReturn($envelope);
@@ -99,9 +99,9 @@ public function testItAlsoCallsTheNextMiddlewareBasedOnWildcard()
$envelope = new Envelope($message);
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();
- $middleware = new SendMessageMiddleware(new InMemorySenderLocator($sender), array(
+ $middleware = new SendMessageMiddleware(new SendersLocator(array('*' => array($sender)), array(
'*' => true,
- ));
+ )));
$sender->expects($this->once())->method('send')->with($envelope)->willReturn($envelope);
@@ -113,7 +113,7 @@ public function testItCallsTheNextMiddlewareWhenNoSenderForThisMessage()
$message = new DummyMessage('Hey');
$envelope = new Envelope($message);
- $middleware = new SendMessageMiddleware(new InMemorySenderLocator(null));
+ $middleware = new SendMessageMiddleware(new SendersLocator(array()));
$middleware->handle($envelope, $this->getStackMock());
}
@@ -124,25 +124,10 @@ public function testItSkipsReceivedMessages()
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();
- $middleware = new SendMessageMiddleware(new InMemorySenderLocator($sender));
+ $middleware = new SendMessageMiddleware(new SendersLocator(array('*' => array($sender))));
$sender->expects($this->never())->method('send');
$middleware->handle($envelope, $this->getStackMock());
}
}
-
-class InMemorySenderLocator implements SenderLocatorInterface
-{
- private $sender;
-
- public function __construct(?SenderInterface $sender)
- {
- $this->sender = $sender;
- }
-
- public function getSender(Envelope $envelope): ?SenderInterface
- {
- return $this->sender;
- }
-}
diff --git a/src/Symfony/Component/Messenger/Tests/Transport/AmqpExt/Fixtures/long_receiver.php b/src/Symfony/Component/Messenger/Tests/Transport/AmqpExt/Fixtures/long_receiver.php
index 3f8612262e068..4e6937744d4b4 100644
--- a/src/Symfony/Component/Messenger/Tests/Transport/AmqpExt/Fixtures/long_receiver.php
+++ b/src/Symfony/Component/Messenger/Tests/Transport/AmqpExt/Fixtures/long_receiver.php
@@ -32,7 +32,7 @@
$worker = new Worker($receiver, new class() implements MessageBusInterface {
public function dispatch($envelope): Envelope
{
- echo 'Get envelope with message: '.get_class($envelope->getMessage())."\n";
+ echo 'Get envelope with message: '.$envelope->getMessageName()."\n";
echo sprintf("with stamps: %s\n", json_encode(array_keys($envelope->all()), JSON_PRETTY_PRINT));
sleep(30);
diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Sender/Locator/ContainerSenderLocatorTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Sender/Locator/ContainerSenderLocatorTest.php
deleted file mode 100644
index 49525e2ac69f4..0000000000000
--- a/src/Symfony/Component/Messenger/Tests/Transport/Sender/Locator/ContainerSenderLocatorTest.php
+++ /dev/null
@@ -1,92 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Messenger\Tests\Transport\Sender\Locator;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\DependencyInjection\Container;
-use Symfony\Component\Messenger\Envelope;
-use Symfony\Component\Messenger\Tests\Fixtures\ChildDummyMessage;
-use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
-use Symfony\Component\Messenger\Tests\Fixtures\DummyMessageInterface;
-use Symfony\Component\Messenger\Tests\Fixtures\SecondMessage;
-use Symfony\Component\Messenger\Transport\Sender\Locator\ContainerSenderLocator;
-use Symfony\Component\Messenger\Transport\Sender\SenderInterface;
-
-class ContainerSenderLocatorTest extends TestCase
-{
- public function testItReturnsTheSenderBasedOnTheMessageClass()
- {
- $sender = $this->getMockBuilder(SenderInterface::class)->getMock();
- $container = new Container();
- $container->set('my_amqp_sender', $sender);
-
- $locator = new ContainerSenderLocator($container, array(
- DummyMessage::class => 'my_amqp_sender',
- ));
-
- $this->assertSame($sender, $locator->getSender(new Envelope(new DummyMessage('Hello'))));
- $this->assertNull($locator->getSender(new Envelope(new SecondMessage())));
- }
-
- public function testItReturnsTheSenderBasedOnTheMessageParentClass()
- {
- $container = new Container();
-
- $sender = $this->getMockBuilder(SenderInterface::class)->getMock();
- $container->set('my_amqp_sender', $sender);
-
- $apiSender = $this->getMockBuilder(SenderInterface::class)->getMock();
- $container->set('my_api_sender', $apiSender);
-
- $locator = new ContainerSenderLocator($container, array(
- DummyMessageInterface::class => 'my_api_sender',
- DummyMessage::class => 'my_amqp_sender',
- ));
-
- $this->assertSame($sender, $locator->getSender(new Envelope(new ChildDummyMessage('Hello'))));
- $this->assertNull($locator->getSender(new Envelope(new SecondMessage())));
- }
-
- public function testItReturnsTheSenderBasedOnTheMessageInterface()
- {
- $container = new Container();
-
- $sender = $this->getMockBuilder(SenderInterface::class)->getMock();
- $container->set('my_amqp_sender', $sender);
-
- $locator = new ContainerSenderLocator($container, array(
- DummyMessageInterface::class => 'my_amqp_sender',
- ));
-
- $this->assertSame($sender, $locator->getSender(new Envelope(new DummyMessage('Hello'))));
- $this->assertNull($locator->getSender(new Envelope(new SecondMessage())));
- }
-
- public function testItSupportsAWildcardInsteadOfTheMessageClass()
- {
- $container = new Container();
-
- $sender = $this->getMockBuilder(SenderInterface::class)->getMock();
- $container->set('my_amqp_sender', $sender);
-
- $apiSender = $this->getMockBuilder(SenderInterface::class)->getMock();
- $container->set('my_api_sender', $apiSender);
-
- $locator = new ContainerSenderLocator($container, array(
- DummyMessage::class => 'my_amqp_sender',
- '*' => 'my_api_sender',
- ));
-
- $this->assertSame($sender, $locator->getSender(new Envelope(new DummyMessage('Hello'))));
- $this->assertSame($apiSender, $locator->getSender(new Envelope(new SecondMessage())));
- }
-}
diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Sender/Locator/SenderLocatorTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Sender/Locator/SenderLocatorTest.php
deleted file mode 100644
index 0063a603b3651..0000000000000
--- a/src/Symfony/Component/Messenger/Tests/Transport/Sender/Locator/SenderLocatorTest.php
+++ /dev/null
@@ -1,44 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Messenger\Tests\Transport\Sender\Locator;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Messenger\Envelope;
-use Symfony\Component\Messenger\Exception\RuntimeException;
-use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
-use Symfony\Component\Messenger\Tests\Fixtures\SecondMessage;
-use Symfony\Component\Messenger\Transport\Sender\Locator\SenderLocator;
-use Symfony\Component\Messenger\Transport\Sender\SenderInterface;
-
-class SenderLocatorTest extends TestCase
-{
- public function testItReturnsTheSenderBasedOnTheMessageClass()
- {
- $sender = $this->getMockBuilder(SenderInterface::class)->getMock();
- $locator = new SenderLocator(array(
- DummyMessage::class => $sender,
- ));
-
- $this->assertSame($sender, $locator->getSender(new Envelope(new DummyMessage('Hello'))));
- $this->assertNull($locator->getSender(new Envelope(new SecondMessage())));
- }
-
- public function testItThrowsExceptionIfConfigurationIsWrong()
- {
- $locator = new SenderLocator(array(
- DummyMessage::class => 'amqp',
- ));
-
- $this->expectException(RuntimeException::class);
- $locator->getSender(new Envelope(new DummyMessage('Hello')));
- }
-}
diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php
new file mode 100644
index 0000000000000..504461052d2b9
--- /dev/null
+++ b/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php
@@ -0,0 +1,33 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Messenger\Tests\Transport\Sender;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Messenger\Exception\RuntimeException;
+use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
+use Symfony\Component\Messenger\Tests\Fixtures\SecondMessage;
+use Symfony\Component\Messenger\Transport\Sender\SendersLocator;
+use Symfony\Component\Messenger\Transport\Sender\SenderInterface;
+
+class SendersLocatorTest extends TestCase
+{
+ public function testItReturnsTheSenderBasedOnTheMessageClass()
+ {
+ $sender = $this->getMockBuilder(SenderInterface::class)->getMock();
+ $locator = new SendersLocator(array(
+ DummyMessage::class => array($sender),
+ ));
+
+ $this->assertSame(array($sender), iterator_to_array($locator->getSenders(DummyMessage::class)));
+ $this->assertSame(array(), iterator_to_array($locator->getSenders(SecondMessage::class)));
+ }
+}
diff --git a/src/Symfony/Component/Messenger/Transport/Sender/ChainSender.php b/src/Symfony/Component/Messenger/Transport/Sender/ChainSender.php
deleted file mode 100644
index 3db0fac7bf82d..0000000000000
--- a/src/Symfony/Component/Messenger/Transport/Sender/ChainSender.php
+++ /dev/null
@@ -1,44 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Messenger\Transport\Sender;
-
-use Symfony\Component\Messenger\Envelope;
-
-/**
- * @author Tobias Schultze
- *
- * @experimental in 4.2
- */
-class ChainSender implements SenderInterface
-{
- private $senders;
-
- /**
- * @param SenderInterface[] $senders
- */
- public function __construct(iterable $senders)
- {
- $this->senders = $senders;
- }
-
- /**
- * {@inheritdoc}
- */
- public function send(Envelope $envelope): Envelope
- {
- foreach ($this->senders as $sender) {
- $envelope = $sender->send($envelope);
- }
-
- return $envelope;
- }
-}
diff --git a/src/Symfony/Component/Messenger/Transport/Sender/Locator/AbstractSenderLocator.php b/src/Symfony/Component/Messenger/Transport/Sender/Locator/AbstractSenderLocator.php
deleted file mode 100644
index cb734c8b1db71..0000000000000
--- a/src/Symfony/Component/Messenger/Transport/Sender/Locator/AbstractSenderLocator.php
+++ /dev/null
@@ -1,45 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Messenger\Transport\Sender\Locator;
-
-use Symfony\Component\Messenger\Envelope;
-
-/**
- * @author Samuel Roze
- *
- * @internal
- *
- * @experimental in 4.2
- */
-abstract class AbstractSenderLocator implements SenderLocatorInterface
-{
- public static function getValueFromMessageRouting(array $mapping, Envelope $envelope)
- {
- if (isset($mapping[$class = \get_class($envelope->getMessage())])) {
- return $mapping[$class];
- }
-
- foreach (class_parents($class) as $name) {
- if (isset($mapping[$name])) {
- return $mapping[$name];
- }
- }
-
- foreach (class_implements($class) as $name) {
- if (isset($mapping[$name])) {
- return $mapping[$name];
- }
- }
-
- return $mapping['*'] ?? null;
- }
-}
diff --git a/src/Symfony/Component/Messenger/Transport/Sender/Locator/ContainerSenderLocator.php b/src/Symfony/Component/Messenger/Transport/Sender/Locator/ContainerSenderLocator.php
deleted file mode 100644
index b5904b3ced7ea..0000000000000
--- a/src/Symfony/Component/Messenger/Transport/Sender/Locator/ContainerSenderLocator.php
+++ /dev/null
@@ -1,43 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Messenger\Transport\Sender\Locator;
-
-use Psr\Container\ContainerInterface;
-use Symfony\Component\Messenger\Envelope;
-use Symfony\Component\Messenger\Transport\Sender\SenderInterface;
-
-/**
- * @author Samuel Roze
- *
- * @experimental in 4.2
- */
-class ContainerSenderLocator extends AbstractSenderLocator
-{
- private $senderServiceLocator;
- private $messageToSenderIdMapping;
-
- public function __construct(ContainerInterface $senderServiceLocator, array $messageToSenderIdMapping)
- {
- $this->senderServiceLocator = $senderServiceLocator;
- $this->messageToSenderIdMapping = $messageToSenderIdMapping;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getSender(Envelope $envelope): ?SenderInterface
- {
- $senderId = self::getValueFromMessageRouting($this->messageToSenderIdMapping, $envelope);
-
- return $senderId ? $this->senderServiceLocator->get($senderId) : null;
- }
-}
diff --git a/src/Symfony/Component/Messenger/Transport/Sender/Locator/SenderLocator.php b/src/Symfony/Component/Messenger/Transport/Sender/Locator/SenderLocator.php
deleted file mode 100644
index b902756267cd1..0000000000000
--- a/src/Symfony/Component/Messenger/Transport/Sender/Locator/SenderLocator.php
+++ /dev/null
@@ -1,48 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Messenger\Transport\Sender\Locator;
-
-use Symfony\Component\Messenger\Envelope;
-use Symfony\Component\Messenger\Exception\RuntimeException;
-use Symfony\Component\Messenger\Transport\Sender\SenderInterface;
-
-/**
- * @author Fabien Potencier
- *
- * @experimental in 4.2
- */
-class SenderLocator extends AbstractSenderLocator
-{
- private $messageToSenderMapping;
-
- public function __construct(array $messageToSenderMapping)
- {
- $this->messageToSenderMapping = $messageToSenderMapping;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getSender(Envelope $envelope): ?SenderInterface
- {
- $sender = self::getValueFromMessageRouting($this->messageToSenderMapping, $envelope);
- if (null === $sender) {
- return null;
- }
-
- if (!$sender instanceof SenderInterface) {
- throw new RuntimeException(sprintf('The sender instance provided for message "%s" should be of type "%s" but got "%s".', \get_class($envelope->getMessage()), SenderInterface::class, \is_object($sender) ? \get_class($sender) : \gettype($sender)));
- }
-
- return $sender;
- }
-}
diff --git a/src/Symfony/Component/Messenger/Transport/Sender/Locator/SenderLocatorInterface.php b/src/Symfony/Component/Messenger/Transport/Sender/Locator/SenderLocatorInterface.php
deleted file mode 100644
index c60943edf3d7e..0000000000000
--- a/src/Symfony/Component/Messenger/Transport/Sender/Locator/SenderLocatorInterface.php
+++ /dev/null
@@ -1,29 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Messenger\Transport\Sender\Locator;
-
-use Symfony\Component\Messenger\Envelope;
-use Symfony\Component\Messenger\Transport\Sender\SenderInterface;
-
-/**
- * @author Samuel Roze
- * @author Tobias Schultze
- *
- * @experimental in 4.2
- */
-interface SenderLocatorInterface
-{
- /**
- * Gets the sender (if applicable) for the given message object.
- */
- public function getSender(Envelope $envelope): ?SenderInterface;
-}
diff --git a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php
new file mode 100644
index 0000000000000..a3e2d2bad7981
--- /dev/null
+++ b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php
@@ -0,0 +1,60 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Messenger\Transport\Sender;
+
+use Symfony\Component\Messenger\Exception\RuntimeException;
+use Symfony\Component\Messenger\Handler\HandlersLocator;
+use Symfony\Component\Messenger\Transport\Sender\SenderInterface;
+
+/**
+ * Maps a message to a list of senders.
+ *
+ * @author Fabien Potencier
+ *
+ * @experimental in 4.2
+ */
+class SendersLocator implements SendersLocatorInterface
+{
+ private $senders;
+ private $sendAndHandle;
+
+ /**
+ * @param SenderInterface[][] $senders
+ * @param bool[] $sendAndHandle
+ */
+ public function __construct(array $senders, array $sendAndHandle = array())
+ {
+ $this->senders = $senders;
+ $this->sendAndHandle = $sendAndHandle;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getSenders(string $name, ?bool &$handle = false): iterable
+ {
+ $handle = false;
+ $sender = null;
+ $seen = array();
+
+ foreach (HandlersLocator::listTypes($name) as $type) {
+ foreach ($this->senders[$type] ?? array() as $sender) {
+ if (!\in_array($sender, $seen, true)) {
+ yield $seen[] = $sender;
+ }
+ }
+ $handle = $handle ?: $this->sendAndHandle[$type] ?? false;
+ }
+
+ $handle = $handle || null === $sender;
+ }
+}
diff --git a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocatorInterface.php b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocatorInterface.php
new file mode 100644
index 0000000000000..d61dea2248b45
--- /dev/null
+++ b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocatorInterface.php
@@ -0,0 +1,35 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Messenger\Transport\Sender;
+
+use Symfony\Component\Messenger\Transport\Sender\SenderInterface;
+
+/**
+ * Maps a message to a list of senders.
+ *
+ * @author Samuel Roze
+ * @author Tobias Schultze
+ *
+ * @experimental in 4.2
+ */
+interface SendersLocatorInterface
+{
+ /**
+ * Gets the senders for the given message name.
+ *
+ * @param bool|null &$handle True after calling the method when the next middleware
+ * should also get the message; false otherwise
+ *
+ * @return iterable|SenderInterface[]
+ */
+ public function getSenders(string $name, ?bool &$handle = false): iterable;
+}