From 5d16e8503b71386332437607617ae552af3ad9bd Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 21 Oct 2018 17:41:21 +0200 Subject: [PATCH 1/2] [Messenger] allow specifying the message topic when calling dispatch() --- .../Controller/ControllerTrait.php | 8 +- .../FrameworkExtension.php | 28 +++---- .../Resources/config/messenger.xml | 4 +- .../Fixtures/php/messenger_multiple_buses.php | 4 +- .../Fixtures/xml/messenger_multiple_buses.xml | 4 +- .../Fixtures/yml/messenger_multiple_buses.yml | 4 +- .../FrameworkExtensionTest.php | 14 ++-- src/Symfony/Component/Messenger/CHANGELOG.md | 7 +- .../DependencyInjection/MessengerPass.php | 74 ++++++++--------- src/Symfony/Component/Messenger/Envelope.php | 22 ++++++ .../Locator/AbstractHandlerLocator.php | 16 ++-- .../Handler/Locator/HandlerLocator.php | 10 +-- .../Locator/HandlerLocatorInterface.php | 4 +- .../Component/Messenger/MessageBus.php | 4 +- .../Messenger/MessageBusInterface.php | 4 +- .../Middleware/HandleMessageMiddleware.php | 2 +- .../Middleware/LoggingMiddleware.php | 8 +- .../Middleware/SendMessageMiddleware.php | 12 +-- .../Component/Messenger/Stamp/TopicStamp.php | 32 ++++++++ .../DependencyInjection/MessengerPassTest.php | 79 ++++--------------- .../Locator/ContainerHandlerLocatorTest.php | 23 ++++-- .../Middleware/SendMessageMiddlewareTest.php | 2 +- .../AmqpExt/Fixtures/long_receiver.php | 5 +- .../Locator/ContainerSenderLocatorTest.php | 30 ++++--- .../Sender/Locator/SenderLocatorTest.php | 7 +- .../Messenger/TraceableMessageBus.php | 6 +- .../Sender/Locator/AbstractSenderLocator.php | 16 ++-- .../Sender/Locator/ContainerSenderLocator.php | 11 ++- .../Sender/Locator/SenderLocator.php | 13 ++- .../Sender/Locator/SenderLocatorInterface.php | 3 +- 30 files changed, 238 insertions(+), 218 deletions(-) create mode 100644 src/Symfony/Component/Messenger/Stamp/TopicStamp.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php index 2ae669b102611..db013bdff7745 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php @@ -391,17 +391,19 @@ protected function isCsrfTokenValid(string $id, ?string $token): bool /** * Dispatches a message to the bus. * - * @param object $message The message to dispatch + * @param object|Envelope $message The message or the message pre-wrapped in an envelope + * @param string|null $topic The topic that senders and/or handlers can subscribe to to get the message; + * if not provided, the topic is the class of the message * * @final */ - protected function dispatchMessage($message): Envelope + protected function dispatchMessage($message, string $topic = null): Envelope { if (!$this->container->has('message_bus')) { throw new \LogicException('The message bus is not enabled in your application. Try running "composer require symfony/messenger".'); } - return $this->container->get('message_bus')->dispatch($message); + return $this->container->get('message_bus')->dispatch($message, $topic); } /** diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index fd242bf8458d0..99542e66d1aae 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1521,7 +1521,7 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder $defaultMiddleware = array( 'before' => array(array('id' => 'logging')), - 'after' => array(array('id' => 'route_messages'), array('id' => 'call_message_handler')), + 'after' => array(array('id' => 'send_message'), array('id' => 'handle_message')), ); foreach ($config['buses'] as $busId => $bus) { $middleware = $bus['middleware']; @@ -1572,31 +1572,27 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder $senderAliases[$name] = $transportId; } - $messageToSenderIdMapping = array(); - $messageToSendAndHandleMapping = array(); - foreach ($config['routing'] as $message => $messageConfiguration) { - if ('*' !== $message && !class_exists($message) && !interface_exists($message, false)) { - throw new LogicException(sprintf('Messenger routing configuration contains a mistake: message "%s" does not exist. It needs to match an existing class or interface.', $message)); - } - - if (1 < \count($messageConfiguration['senders'])) { + $topicToSenderIdMapping = array(); + $topicsToSendAndHandle = array(); + foreach ($config['routing'] as $topic => $topicConfiguration) { + if (1 < \count($topicConfiguration['senders'])) { $senders = array_map(function ($sender) use ($senderAliases) { return new Reference($senderAliases[$sender] ?? $sender); - }, $messageConfiguration['senders']); + }, $topicConfiguration['senders']); $chainSenderDefinition = new Definition(ChainSender::class, array($senders)); $chainSenderDefinition->addTag('messenger.sender'); - $chainSenderId = '.messenger.chain_sender.'.$message; + $chainSenderId = '.messenger.chain_sender.'.$topic; $container->setDefinition($chainSenderId, $chainSenderDefinition); - $messageToSenderIdMapping[$message] = $chainSenderId; + $topicToSenderIdMapping[$topic] = $chainSenderId; } else { - $messageToSenderIdMapping[$message] = $messageConfiguration['senders'][0]; + $topicToSenderIdMapping[$topic] = $topicConfiguration['senders'][0]; } - $messageToSendAndHandleMapping[$message] = $messageConfiguration['send_and_handle']; + $topicsToSendAndHandle[$topic] = $topicConfiguration['send_and_handle']; } - $container->getDefinition('messenger.asynchronous.routing.sender_locator')->replaceArgument(1, $messageToSenderIdMapping); - $container->getDefinition('messenger.middleware.route_messages')->replaceArgument(1, $messageToSendAndHandleMapping); + $container->getDefinition('messenger.asynchronous.routing.sender_locator')->replaceArgument(1, $topicToSenderIdMapping); + $container->getDefinition('messenger.middleware.send_message')->replaceArgument(1, $topicsToSendAndHandle); } private function registerCacheConfiguration(array $config, ContainerBuilder $container) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.xml index 8fc23e18c4df1..0f30194ad180b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.xml @@ -12,7 +12,7 @@ - + @@ -25,7 +25,7 @@ - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_multiple_buses.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_multiple_buses.php index 1e0b402760daa..f500ff9573916 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_multiple_buses.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_multiple_buses.php @@ -13,8 +13,8 @@ 'messenger.bus.queries' => array( 'default_middleware' => false, 'middleware' => array( - 'route_messages', - 'call_message_handler', + 'send_message', + 'handle_message', ), ), ), diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_multiple_buses.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_multiple_buses.xml index e42e4eac30886..db946e45e5ebb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_multiple_buses.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_multiple_buses.xml @@ -18,8 +18,8 @@ - - + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_multiple_buses.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_multiple_buses.yml index 23894ac01b441..0e67039733272 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_multiple_buses.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_multiple_buses.yml @@ -9,5 +9,5 @@ framework: messenger.bus.queries: default_middleware: false middleware: - - "route_messages" - - "call_message_handler" + - "send_message" + - "handle_message" diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index bbe53dbf69403..a8bcc6f628dda 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -564,7 +564,7 @@ public function testMessengerRouting() { $container = $this->createContainerFromFile('messenger_routing'); $senderLocatorDefinition = $container->getDefinition('messenger.asynchronous.routing.sender_locator'); - $sendMessageMiddlewareDefinition = $container->getDefinition('messenger.middleware.route_messages'); + $sendMessageMiddlewareDefinition = $container->getDefinition('messenger.middleware.send_message'); $messageToSenderIdsMapping = array( DummyMessage::class => '.messenger.chain_sender.'.DummyMessage::class, @@ -619,22 +619,22 @@ public function testMessengerWithMultipleBuses() $this->assertSame(array(), $container->getDefinition('messenger.bus.commands')->getArgument(0)); $this->assertEquals(array( array('id' => 'logging'), - array('id' => 'route_messages'), - array('id' => 'call_message_handler'), + array('id' => 'send_message'), + array('id' => 'handle_message'), ), $container->getParameter('messenger.bus.commands.middleware')); $this->assertTrue($container->has('messenger.bus.events')); $this->assertSame(array(), $container->getDefinition('messenger.bus.events')->getArgument(0)); $this->assertEquals(array( array('id' => 'logging'), array('id' => 'with_factory', 'arguments' => array('foo', true, array('bar' => 'baz'))), - array('id' => 'route_messages'), - array('id' => 'call_message_handler'), + array('id' => 'send_message'), + array('id' => 'handle_message'), ), $container->getParameter('messenger.bus.events.middleware')); $this->assertTrue($container->has('messenger.bus.queries')); $this->assertSame(array(), $container->getDefinition('messenger.bus.queries')->getArgument(0)); $this->assertEquals(array( - array('id' => 'route_messages', 'arguments' => array()), - array('id' => 'call_message_handler', 'arguments' => array()), + array('id' => 'send_message', 'arguments' => array()), + array('id' => 'handle_message', 'arguments' => array()), ), $container->getParameter('messenger.bus.queries.middleware')); $this->assertTrue($container->hasAlias('message_bus')); diff --git a/src/Symfony/Component/Messenger/CHANGELOG.md b/src/Symfony/Component/Messenger/CHANGELOG.md index 366d0f519651a..1226cce2ee1cf 100644 --- a/src/Symfony/Component/Messenger/CHANGELOG.md +++ b/src/Symfony/Component/Messenger/CHANGELOG.md @@ -7,6 +7,7 @@ CHANGELOG * The component is not experimental anymore * All the changes below are BC BREAKS * `MessageBusInterface::dispatch()`, `MiddlewareInterface::handle()` and `SenderInterface::send()` return `Envelope` + * `MessageBusInterface::dispatch()` now takes a second `string $topic = null` argument * `MiddlewareInterface::handle()` now require an `Envelope` as first argument and a `StackInterface` as second * `EnvelopeAwareInterface` has been removed * The signature of `Amqp*` classes changed to take a `Connection` as a first argument and an optional @@ -21,16 +22,14 @@ CHANGELOG as first constructor argument * The `EncoderInterface` and `DecoderInterface` have been replaced by a unified `Symfony\Component\Messenger\Transport\Serialization\SerializerInterface`. * The locator passed to `ContainerHandlerLocator` should not prefix its keys by "handler." anymore - * The `AbstractHandlerLocator::getHandler()` method uses `?callable` as return type * Renamed `EnvelopeItemInterface` to `StampInterface` * `Envelope`'s constructor and `with()` method now accept `StampInterface` objects as variadic parameters * Renamed and moved `ReceivedMessage`, `ValidationConfiguration` and `SerializerConfiguration` in the `Stamp` namespace * Removed the `WrapIntoReceivedMessage` - * `SenderLocatorInterface::getSenderForMessage()` has been replaced by `getSender(Envelope $envelope)` * `MessengerDataCollector::getMessages()` returns an iterable, not just an array anymore * `AbstractHandlerLocator` is now internal - * `HandlerLocatorInterface::resolve()` has been replaced by `getHandler(Envelope $envelope): ?callable` and shouldn't throw when no handlers are found - * `SenderLocatorInterface::getSenderForMessage()` has been replaced by `getSender(Envelope $envelope)` + * `HandlerLocatorInterface::resolve()` has been replaced by `getHandler(string $topic): ?callable` and shouldn't throw when no handlers are found + * `SenderLocatorInterface::getSenderForMessage()` has been replaced by `getSender(string $topic): ?SenderInterface` * Classes in the `Middleware\Enhancers` sub-namespace have been moved to the `Middleware` one * Classes in the `Asynchronous\Routing` sub-namespace have been moved to the `Transport\Sender\Locator` sub-namespace * The `Asynchronous/Middleware/SendMessageMiddleware` class has been moved to the `Middleware` namespace diff --git a/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php b/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php index f29d7d1af3401..0b06cf34c0844 100644 --- a/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php +++ b/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php @@ -80,7 +80,7 @@ public function process(ContainerBuilder $container) private function registerHandlers(ContainerBuilder $container, array $busIds) { $definitions = array(); - $handlersByBusAndMessage = array(); + $handlersByBusAndTopic = array(); foreach ($container->findTaggedServiceIds($this->handlerTag, true) as $serviceId => $tags) { foreach ($tags as $tag) { @@ -96,47 +96,37 @@ private function registerHandlers(ContainerBuilder $container, array $busIds) $handles = $this->guessHandledClasses($r, $serviceId); } - $priority = $tag['priority'] ?? 0; + $topic = null; $handlerBuses = (array) ($tag['bus'] ?? $busIds); - foreach ($handles as $messageClass => $method) { + foreach ($handles as $topic => $method) { $buses = $handlerBuses; - if (\is_int($messageClass)) { - $messageClass = $method; + if (\is_int($topic)) { + $topic = $method; $method = '__invoke'; } - if (\is_array($messageClass)) { - $messagePriority = $messageClass[1]; - $messageClass = $messageClass[0]; + if (\is_array($topic)) { + list($topic, $priority) = $topic; } else { - $messagePriority = $priority; + $priority = $tag['priority'] ?? 0; } if (\is_array($method)) { if (isset($method['bus'])) { if (!\in_array($method['bus'], $busIds)) { - $messageClassLocation = isset($tag['handles']) ? 'declared in your tag attribute "handles"' : $r->implementsInterface(MessageSubscriberInterface::class) ? sprintf('returned by method "%s::getHandledMessages()"', $r->getName()) : sprintf('used as argument type in method "%s::%s()"', $r->getName(), $method); + $topicLocation = isset($tag['handles']) ? 'declared in your tag attribute "handles"' : $r->implementsInterface(MessageSubscriberInterface::class) ? sprintf('returned by method "%s::getHandledMessages()"', $r->getName()) : sprintf('used as argument type in method "%s::%s()"', $r->getName(), $method); - throw new RuntimeException(sprintf('Invalid configuration %s for message "%s": bus "%s" does not exist.', $messageClassLocation, $messageClass, $method['bus'])); + throw new RuntimeException(sprintf('Invalid configuration %s for message "%s": bus "%s" does not exist.', $topicLocation, $topic, $method['bus'])); } $buses = array($method['bus']); } - if (isset($method['priority'])) { - $messagePriority = $method['priority']; - } - + $priority = $method['priority'] ?? $priority; $method = $method['method'] ?? '__invoke'; } - if (!\class_exists($messageClass) && !\interface_exists($messageClass, false)) { - $messageClassLocation = isset($tag['handles']) ? 'declared in your tag attribute "handles"' : $r->implementsInterface(MessageSubscriberInterface::class) ? sprintf('returned by method "%s::getHandledMessages()"', $r->getName()) : sprintf('used as argument type in method "%s::%s()"', $r->getName(), $method); - - throw new RuntimeException(sprintf('Invalid handler service "%s": message class "%s" %s does not exist.', $serviceId, $messageClass, $messageClassLocation)); - } - if (!$r->hasMethod($method)) { throw new RuntimeException(sprintf('Invalid handler service "%s": method "%s::%s()" does not exist.', $serviceId, $r->getName(), $method)); } @@ -144,56 +134,60 @@ private function registerHandlers(ContainerBuilder $container, array $busIds) if ('__invoke' !== $method) { $wrapperDefinition = (new Definition('callable'))->addArgument(array(new Reference($serviceId), $method))->setFactory('Closure::fromCallable'); - $definitions[$definitionId = '.messenger.method_on_object_wrapper.'.ContainerBuilder::hash($messageClass.':'.$messagePriority.':'.$serviceId.':'.$method)] = $wrapperDefinition; + $definitions[$definitionId = '.messenger.method_on_object_wrapper.'.ContainerBuilder::hash($topic.':'.$priority.':'.$serviceId.':'.$method)] = $wrapperDefinition; } else { $definitionId = $serviceId; } foreach ($buses as $handlerBus) { - $handlersByBusAndMessage[$handlerBus][$messageClass][$messagePriority][] = $definitionId; + $handlersByBusAndTopic[$handlerBus][$topic][$priority][] = $definitionId; } } + + if (null === $topic) { + throw new RuntimeException(sprintf('Invalid handler service "%s": method "%s::getHandledMessages()" must return one or more messages.', $serviceId, $r->getName())); + } } } - foreach ($handlersByBusAndMessage as $bus => $handlersByMessage) { - foreach ($handlersByMessage as $message => $handlersByPriority) { + foreach ($handlersByBusAndTopic as $bus => $handlersByTopic) { + foreach ($handlersByTopic as $topic => $handlersByPriority) { krsort($handlersByPriority); - $handlersByBusAndMessage[$bus][$message] = array_unique(array_merge(...$handlersByPriority)); + $handlersByBusAndTopic[$bus][$topic] = array_unique(array_merge(...$handlersByPriority)); } } $handlersLocatorMappingByBus = array(); - foreach ($handlersByBusAndMessage as $bus => $handlersByMessage) { - foreach ($handlersByMessage as $message => $handlersIds) { + foreach ($handlersByBusAndTopic as $bus => $handlersByTopic) { + foreach ($handlersByTopic as $topic => $handlersIds) { if (1 === \count($handlersIds)) { - $handlersLocatorMappingByBus[$bus][$message] = new Reference(current($handlersIds)); + $handlersLocatorMappingByBus[$bus][$topic] = new Reference(current($handlersIds)); } else { $chainHandler = new Definition(ChainHandler::class, array(array_map(function (string $handlerId): Reference { return new Reference($handlerId); }, $handlersIds))); $chainHandler->setPrivate(true); - $serviceId = '.messenger.chain_handler.'.ContainerBuilder::hash($bus.$message); + $serviceId = '.messenger.chain_handler.'.$bus.'.'.$topic; $definitions[$serviceId] = $chainHandler; - $handlersLocatorMappingByBus[$bus][$message] = new Reference($serviceId); + $handlersLocatorMappingByBus[$bus][$topic] = new Reference($serviceId); } } } $container->addDefinitions($definitions); foreach ($busIds as $bus) { - $container->register($resolverName = "$bus.messenger.handler_resolver", ContainerHandlerLocator::class) + $container->register($locatorId = ".$bus.messenger.handler_locator", ContainerHandlerLocator::class) ->setArgument(0, ServiceLocatorTagPass::register($container, $handlersLocatorMappingByBus[$bus] ?? array())) ; - if ($container->has($callMessageHandlerId = "$bus.middleware.call_message_handler")) { + if ($container->has($callMessageHandlerId = ".$bus.middleware.handle_message")) { $container->getDefinition($callMessageHandlerId) - ->replaceArgument(0, new Reference($resolverName)) + ->replaceArgument(0, new Reference($locatorId)) ; } } if ($container->hasDefinition('console.command.messenger_debug')) { - $debugCommandMapping = $handlersByBusAndMessage; + $debugCommandMapping = $handlersByBusAndTopic; foreach ($busIds as $bus) { if (!isset($debugCommandMapping[$bus])) { $debugCommandMapping[$bus] = array(); @@ -206,11 +200,7 @@ private function registerHandlers(ContainerBuilder $container, array $busIds) private function guessHandledClasses(\ReflectionClass $handlerClass, string $serviceId): iterable { if ($handlerClass->implementsInterface(MessageSubscriberInterface::class)) { - if (!$handledMessages = $handlerClass->getName()::getHandledMessages()) { - throw new RuntimeException(sprintf('Invalid handler service "%s": method "%s::getHandledMessages()" must return one or more messages.', $serviceId, $handlerClass->getName())); - } - - return $handledMessages; + return $handlerClass->getName()::getHandledMessages(); } try { @@ -297,7 +287,7 @@ private function registerSenders(ContainerBuilder $container) private function registerBusToCollector(ContainerBuilder $container, string $busId) { $container->setDefinition( - $tracedBusId = 'debug.traced.'.$busId, + $tracedBusId = '.debug.traced.'.$busId, (new Definition(TraceableMessageBus::class, array(new Reference($tracedBusId.'.inner'))))->setDecoratedService($busId) ); @@ -328,7 +318,7 @@ private function registerBusMiddleware(ContainerBuilder $container, string $busI $key < $count ? $childDefinition->replaceArgument($key, $argument) : $childDefinition->addArgument($argument); } - $container->setDefinition($messengerMiddlewareId = $busId.'.middleware.'.$id, $childDefinition); + $container->setDefinition($messengerMiddlewareId = ".$busId.middleware.$id", $childDefinition); } elseif ($arguments) { throw new RuntimeException(sprintf('Invalid middleware factory "%s": a middleware factory must be an abstract definition.', $id)); } diff --git a/src/Symfony/Component/Messenger/Envelope.php b/src/Symfony/Component/Messenger/Envelope.php index 6441eb7d5dbe1..ad6a222095782 100644 --- a/src/Symfony/Component/Messenger/Envelope.php +++ b/src/Symfony/Component/Messenger/Envelope.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Messenger; use Symfony\Component\Messenger\Stamp\StampInterface; +use Symfony\Component\Messenger\Stamp\TopicStamp; /** * A message wrapped in an envelope with stamps (configurations, markers, ...). @@ -38,6 +39,18 @@ public function __construct($message, StampInterface ...$stamps) } } + /** + * Wraps a message into an envelope if not already wrapped. + * + * @param Envelope|object $message + */ + public static function wrap($message, ?string $topic): self + { + $envelope = $message instanceof self ? $message : new self($message); + + return null !== $topic ? $envelope->with(new TopicStamp($topic)) : $envelope; + } + /** * @return Envelope a new Envelope instance with additional stamp */ @@ -72,4 +85,13 @@ public function getMessage() { return $this->message; } + + public function getTopic(): string + { + if (null !== $topic = $this->stamps[TopicStamp::class] ?? null) { + return $topic->getName(); + } + + return \get_class($this->message); + } } diff --git a/src/Symfony/Component/Messenger/Handler/Locator/AbstractHandlerLocator.php b/src/Symfony/Component/Messenger/Handler/Locator/AbstractHandlerLocator.php index 95fb50c7160c7..b564158770257 100644 --- a/src/Symfony/Component/Messenger/Handler/Locator/AbstractHandlerLocator.php +++ b/src/Symfony/Component/Messenger/Handler/Locator/AbstractHandlerLocator.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Messenger\Handler\Locator; -use Symfony\Component\Messenger\Envelope; - /** * @author Miha Vrhovnik * @author Samuel Roze @@ -21,21 +19,23 @@ */ abstract class AbstractHandlerLocator implements HandlerLocatorInterface { - public function getHandler(Envelope $envelope): ?callable + public function getHandler(string $topic): ?callable { - $class = \get_class($envelope->getMessage()); - - if ($handler = $this->getHandlerByName($class)) { + if ($handler = $this->getHandlerByName($topic)) { return $handler; } - foreach (class_parents($class) as $name) { + if (!class_exists($topic) && !interface_exists($topic, false)) { + return null; + } + + foreach (class_parents($topic) as $name) { if ($handler = $this->getHandlerByName($name)) { return $handler; } } - foreach (class_implements($class) as $name) { + foreach (class_implements($topic) as $name) { if ($handler = $this->getHandlerByName($name)) { return $handler; } diff --git a/src/Symfony/Component/Messenger/Handler/Locator/HandlerLocator.php b/src/Symfony/Component/Messenger/Handler/Locator/HandlerLocator.php index 4042ca682bcbf..8b4b9615a28af 100644 --- a/src/Symfony/Component/Messenger/Handler/Locator/HandlerLocator.php +++ b/src/Symfony/Component/Messenger/Handler/Locator/HandlerLocator.php @@ -17,13 +17,13 @@ class HandlerLocator extends AbstractHandlerLocator { /** - * Maps a message (its class) to a given handler. + * Maps a topic to a given handler. */ - private $messageToHandlerMapping; + private $topicToHandlerMapping; - public function __construct(array $messageToHandlerMapping = array()) + public function __construct(array $topicToHandlerMapping = array()) { - $this->messageToHandlerMapping = $messageToHandlerMapping; + $this->topicToHandlerMapping = $topicToHandlerMapping; } /** @@ -31,6 +31,6 @@ public function __construct(array $messageToHandlerMapping = array()) */ protected function getHandlerByName(string $name): ?callable { - return $this->messageToHandlerMapping[$name] ?? null; + return $this->topicToHandlerMapping[$name] ?? null; } } diff --git a/src/Symfony/Component/Messenger/Handler/Locator/HandlerLocatorInterface.php b/src/Symfony/Component/Messenger/Handler/Locator/HandlerLocatorInterface.php index 43735dc3d2e80..3c90d234bf4d4 100644 --- a/src/Symfony/Component/Messenger/Handler/Locator/HandlerLocatorInterface.php +++ b/src/Symfony/Component/Messenger/Handler/Locator/HandlerLocatorInterface.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Messenger\Handler\Locator; -use Symfony\Component\Messenger\Envelope; - /** * @author Samuel Roze */ @@ -21,5 +19,5 @@ interface HandlerLocatorInterface /** * Returns the handler for the given message. */ - public function getHandler(Envelope $envelope): ?callable; + public function getHandler(string $topic): ?callable; } diff --git a/src/Symfony/Component/Messenger/MessageBus.php b/src/Symfony/Component/Messenger/MessageBus.php index 2e4b3daa9a3c2..5ffc8047e943e 100644 --- a/src/Symfony/Component/Messenger/MessageBus.php +++ b/src/Symfony/Component/Messenger/MessageBus.php @@ -50,12 +50,12 @@ public function getIterator() /** * {@inheritdoc} */ - public function dispatch($message): Envelope + public function dispatch($message, string $topic = null): Envelope { if (!\is_object($message)) { throw new \TypeError(sprintf('Invalid argument provided to "%s()": expected object, but got %s.', __METHOD__, \gettype($message))); } - $envelope = $message instanceof Envelope ? $message : new Envelope($message); + $envelope = Envelope::wrap($message, $topic); $middlewareIterator = $this->middlewareAggregate->getIterator(); while ($middlewareIterator instanceof \IteratorAggregate) { diff --git a/src/Symfony/Component/Messenger/MessageBusInterface.php b/src/Symfony/Component/Messenger/MessageBusInterface.php index ae7930883abba..35acae767a691 100644 --- a/src/Symfony/Component/Messenger/MessageBusInterface.php +++ b/src/Symfony/Component/Messenger/MessageBusInterface.php @@ -20,6 +20,8 @@ interface MessageBusInterface * Dispatches the given message. * * @param object|Envelope $message The message or the message pre-wrapped in an envelope + * @param string|null $topic The topic that senders and/or handlers can subscribe to to get the message; + * if not provided, the topic is the class of the message */ - public function dispatch($message): Envelope; + public function dispatch($message, string $topic = null): Envelope; } diff --git a/src/Symfony/Component/Messenger/Middleware/HandleMessageMiddleware.php b/src/Symfony/Component/Messenger/Middleware/HandleMessageMiddleware.php index 11d86b6107ebe..7acced68ece89 100644 --- a/src/Symfony/Component/Messenger/Middleware/HandleMessageMiddleware.php +++ b/src/Symfony/Component/Messenger/Middleware/HandleMessageMiddleware.php @@ -36,7 +36,7 @@ public function __construct(HandlerLocatorInterface $messageHandlerLocator, bool */ public function handle(Envelope $envelope, StackInterface $stack): Envelope { - if (null !== $handler = $this->messageHandlerLocator->getHandler($envelope)) { + if (null !== $handler = $this->messageHandlerLocator->getHandler($envelope->getTopic())) { $handler($envelope->getMessage()); } elseif (!$this->allowNoHandlers) { throw new NoHandlerForMessageException(sprintf('No handler for message "%s".', \get_class($envelope->getMessage()))); diff --git a/src/Symfony/Component/Messenger/Middleware/LoggingMiddleware.php b/src/Symfony/Component/Messenger/Middleware/LoggingMiddleware.php index a5af35dd0591d..74915af439266 100644 --- a/src/Symfony/Component/Messenger/Middleware/LoggingMiddleware.php +++ b/src/Symfony/Component/Messenger/Middleware/LoggingMiddleware.php @@ -34,20 +34,20 @@ public function handle(Envelope $envelope, StackInterface $stack): Envelope $message = $envelope->getMessage(); $context = array( 'message' => $message, - 'name' => \get_class($message), + 'topic' => $envelope->getTopic(), ); - $this->logger->debug('Starting handling message {name}', $context); + $this->logger->debug('Starting handling message "{topic}"', $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 "{topic}"', $context); throw $e; } - $this->logger->debug('Finished handling message {name}', $context); + $this->logger->debug('Finished handling message "{topic}"', $context); return $envelope; } diff --git a/src/Symfony/Component/Messenger/Middleware/SendMessageMiddleware.php b/src/Symfony/Component/Messenger/Middleware/SendMessageMiddleware.php index f927592976c49..cb04aad75a7f7 100644 --- a/src/Symfony/Component/Messenger/Middleware/SendMessageMiddleware.php +++ b/src/Symfony/Component/Messenger/Middleware/SendMessageMiddleware.php @@ -23,12 +23,12 @@ class SendMessageMiddleware implements MiddlewareInterface { private $senderLocator; - private $messagesToSendAndHandleMapping; + private $topicsToSendAndHandle; - public function __construct(SenderLocatorInterface $senderLocator, array $messagesToSendAndHandleMapping = array()) + public function __construct(SenderLocatorInterface $senderLocator, array $topicsToSendAndHandle = array()) { $this->senderLocator = $senderLocator; - $this->messagesToSendAndHandleMapping = $messagesToSendAndHandleMapping; + $this->topicsToSendAndHandle = $topicsToSendAndHandle; } /** @@ -41,13 +41,13 @@ public function handle(Envelope $envelope, StackInterface $stack): Envelope return $stack->next()->handle($envelope, $stack); } - $sender = $this->senderLocator->getSender($envelope); + $sender = $this->senderLocator->getSender($envelope->getTopic()); if ($sender) { $envelope = $sender->send($envelope); - if (!AbstractSenderLocator::getValueFromMessageRouting($this->messagesToSendAndHandleMapping, $envelope)) { - // message has no corresponding handler + if (!AbstractSenderLocator::getValueFromMessageRouting($this->topicsToSendAndHandle, $envelope->getTopic())) { + // message should only be sent and be not handled by the next middleware return $envelope; } } diff --git a/src/Symfony/Component/Messenger/Stamp/TopicStamp.php b/src/Symfony/Component/Messenger/Stamp/TopicStamp.php new file mode 100644 index 0000000000000..0bae9ebf32709 --- /dev/null +++ b/src/Symfony/Component/Messenger/Stamp/TopicStamp.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Messenger\Stamp; + +/** + * A stamp that defines the topic that senders and/or handlers can subscribe to to get a message. + * + * @author Nicolas Grekas + */ +final class TopicStamp implements StampInterface +{ + private $name; + + public function __construct(string $name) + { + $this->name = $name; + } + + public function getName() + { + return $this->name; + } +} diff --git a/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php b/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php index 2c4d60602a99b..e371e67294608 100644 --- a/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php +++ b/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php @@ -65,7 +65,7 @@ public function testProcess() $this->assertFalse($container->hasDefinition('messenger.middleware.debug.logging')); - $handlerLocatorDefinition = $container->getDefinition($container->getDefinition("$busId.messenger.handler_resolver")->getArgument(0)); + $handlerLocatorDefinition = $container->getDefinition($container->getDefinition(".$busId.messenger.handler_locator")->getArgument(0)); $this->assertSame(ServiceLocator::class, $handlerLocatorDefinition->getClass()); $this->assertEquals( array( @@ -85,12 +85,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); @@ -105,7 +105,7 @@ public function testProcessHandlersByBus() (new ResolveClassPass())->process($container); (new MessengerPass())->process($container); - $commandBusHandlerLocatorDefinition = $container->getDefinition($container->getDefinition("$commandBusId.messenger.handler_resolver")->getArgument(0)); + $commandBusHandlerLocatorDefinition = $container->getDefinition($container->getDefinition(".$commandBusId.messenger.handler_locator")->getArgument(0)); $this->assertSame(ServiceLocator::class, $commandBusHandlerLocatorDefinition->getClass()); $this->assertEquals( array( @@ -115,7 +115,7 @@ public function testProcessHandlersByBus() $commandBusHandlerLocatorDefinition->getArgument(0) ); - $queryBusHandlerLocatorDefinition = $container->getDefinition($container->getDefinition("$queryBusId.messenger.handler_resolver")->getArgument(0)); + $queryBusHandlerLocatorDefinition = $container->getDefinition($container->getDefinition(".$queryBusId.messenger.handler_locator")->getArgument(0)); $this->assertSame(ServiceLocator::class, $queryBusHandlerLocatorDefinition->getClass()); $this->assertEquals( array( @@ -154,7 +154,7 @@ public function testGetClassesFromTheHandlerSubscriberInterface() (new MessengerPass())->process($container); - $handlerLocatorDefinition = $container->getDefinition($container->getDefinition("$busId.messenger.handler_resolver")->getArgument(0)); + $handlerLocatorDefinition = $container->getDefinition($container->getDefinition(".$busId.messenger.handler_locator")->getArgument(0)); $handlerMapping = $handlerLocatorDefinition->getArgument(0); $this->assertArrayHasKey(DummyMessage::class, $handlerMapping); @@ -182,7 +182,7 @@ public function testGetClassesAndMethodsAndPrioritiesFromTheSubscriber() (new MessengerPass())->process($container); - $handlerLocatorDefinition = $container->getDefinition($container->getDefinition("$busId.messenger.handler_resolver")->getArgument(0)); + $handlerLocatorDefinition = $container->getDefinition($container->getDefinition(".$busId.messenger.handler_locator")->getArgument(0)); $handlerMapping = $handlerLocatorDefinition->getArgument(0); $this->assertArrayHasKey(DummyMessage::class, $handlerMapping); @@ -288,7 +288,7 @@ public function testItShouldNotThrowIfGeneratorIsReturnedInsteadOfArray() (new MessengerPass())->process($container); - $handlerLocatorDefinition = $container->getDefinition($container->getDefinition("$busId.messenger.handler_resolver")->getArgument(0)); + $handlerLocatorDefinition = $container->getDefinition($container->getDefinition(".$busId.messenger.handler_locator")->getArgument(0)); $handlerMapping = $handlerLocatorDefinition->getArgument(0); $this->assertArrayHasKey(DummyMessage::class, $handlerMapping); @@ -312,14 +312,14 @@ public function testItRegistersHandlersOnDifferentBuses() (new MessengerPass())->process($container); - $eventsHandlerLocatorDefinition = $container->getDefinition($container->getDefinition($eventsBusId.'.messenger.handler_resolver')->getArgument(0)); + $eventsHandlerLocatorDefinition = $container->getDefinition($container->getDefinition(".$eventsBusId.messenger.handler_locator")->getArgument(0)); $eventsHandlerMapping = $eventsHandlerLocatorDefinition->getArgument(0); $this->assertEquals(array(DummyMessage::class), array_keys($eventsHandlerMapping)); $firstReference = $eventsHandlerMapping[DummyMessage::class]->getValues()[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)); + $commandsHandlerLocatorDefinition = $container->getDefinition($container->getDefinition(".$commandsBusId.messenger.handler_locator")->getArgument(0)); $commandsHandlerMapping = $commandsHandlerLocatorDefinition->getArgument(0); $this->assertEquals(array(DummyMessage::class), array_keys($commandsHandlerMapping)); @@ -355,51 +355,6 @@ public function testItDoesNotRegisterInvalidSender() (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. - */ - public function testUndefinedMessageClassForHandler() - { - $container = $this->getContainerBuilder(); - $container - ->register(UndefinedMessageHandler::class, UndefinedMessageHandler::class) - ->addTag('messenger.message_handler') - ; - - (new MessengerPass())->process($container); - } - - /** - * @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. - */ - public function testUndefinedMessageClassForHandlerImplementingMessageHandlerInterface() - { - $container = $this->getContainerBuilder(); - $container - ->register(UndefinedMessageHandlerViaHandlerInterface::class, UndefinedMessageHandlerViaHandlerInterface::class) - ->addTag('messenger.message_handler') - ; - - (new MessengerPass())->process($container); - } - - /** - * @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. - */ - public function testUndefinedMessageClassForHandlerImplementingMessageSubscriberInterface() - { - $container = $this->getContainerBuilder(); - $container - ->register(UndefinedMessageHandlerViaSubscriberInterface::class, UndefinedMessageHandlerViaSubscriberInterface::class) - ->addTag('messenger.message_handler') - ; - - (new MessengerPass())->process($container); - } - /** * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException * @expectedExceptionMessage Invalid handler service "Symfony\Component\Messenger\Tests\DependencyInjection\NotInvokableHandler": class "Symfony\Component\Messenger\Tests\DependencyInjection\NotInvokableHandler" must have an "__invoke()" method. @@ -485,7 +440,7 @@ public function testRegistersTraceableBusesToCollector() (new MessengerPass())->process($container); - $this->assertTrue($container->hasDefinition($debuggedFooBusId = 'debug.traced.'.$fooBusId)); + $this->assertTrue($container->hasDefinition($debuggedFooBusId = '.debug.traced.'.$fooBusId)); $this->assertSame(array($fooBusId, null, 0), $container->getDefinition($debuggedFooBusId)->getDecoratedService()); $this->assertEquals(array(array('registerBus', array($fooBusId, new Reference($debuggedFooBusId)))), $container->getDefinition('data_collector.messenger')->getMethodCalls()); } @@ -506,14 +461,14 @@ public function testRegistersMiddlewareFromServices() (new MessengerPass())->process($container); (new ResolveChildDefinitionsPass())->process($container); - $this->assertTrue($container->hasDefinition($factoryChildMiddlewareId = $fooBusId.'.middleware.middleware_with_factory')); + $this->assertTrue($container->hasDefinition($factoryChildMiddlewareId = ".$fooBusId.middleware.middleware_with_factory")); $this->assertEquals( array('foo', 'bar'), $container->getDefinition($factoryChildMiddlewareId)->getArguments(), 'parent default argument is overridden, and next ones appended' ); - $this->assertTrue($container->hasDefinition($factoryWithDefaultChildMiddlewareId = $fooBusId.'.middleware.middleware_with_factory_using_default')); + $this->assertTrue($container->hasDefinition($factoryWithDefaultChildMiddlewareId = ".$fooBusId.middleware.middleware_with_factory_using_default")); $this->assertEquals( array('some_default'), $container->getDefinition($factoryWithDefaultChildMiddlewareId)->getArguments(), @@ -582,9 +537,9 @@ public function testDecoratesWithTraceableMiddlewareOnDebug() null, ), $concreteDef->getArguments()); - $this->assertNotNull($abstractDef = $container->getDefinition(".messenger.debug.traced.$busId.middleware.abstract_middleware")); + $this->assertNotNull($abstractDef = $container->getDefinition(".messenger.debug.traced..$busId.middleware.abstract_middleware")); $this->assertEquals(array( - new Reference(".messenger.debug.traced.$busId.middleware.abstract_middleware.inner"), + new Reference(".messenger.debug.traced..$busId.middleware.abstract_middleware.inner"), new Reference('debug.stopwatch'), $busId, ), $abstractDef->getArguments()); @@ -595,14 +550,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); diff --git a/src/Symfony/Component/Messenger/Tests/Handler/Locator/ContainerHandlerLocatorTest.php b/src/Symfony/Component/Messenger/Tests/Handler/Locator/ContainerHandlerLocatorTest.php index e9147e50b7b57..3fd8562df91c1 100644 --- a/src/Symfony/Component/Messenger/Tests/Handler/Locator/ContainerHandlerLocatorTest.php +++ b/src/Symfony/Component/Messenger/Tests/Handler/Locator/ContainerHandlerLocatorTest.php @@ -4,7 +4,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Handler\Locator\ContainerHandlerLocator; use Symfony\Component\Messenger\Tests\Fixtures\ChildDummyMessage; use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage; @@ -20,7 +19,7 @@ public function testItLocatesHandlerUsingTheMessageClass() $container->set(DummyMessage::class, $handler); $locator = new ContainerHandlerLocator($container); - $resolvedHandler = $locator->getHandler(new Envelope(new DummyMessage('Hey'))); + $resolvedHandler = $locator->getHandler(DummyMessage::class); $this->assertSame($handler, $resolvedHandler); } @@ -28,7 +27,7 @@ public function testItLocatesHandlerUsingTheMessageClass() public function testNoHandlersReturnsNull() { $locator = new ContainerHandlerLocator(new Container()); - $this->assertNull($locator->getHandler(new Envelope(new DummyMessage('Hey')))); + $this->assertNull($locator->getHandler(DummyMessage::class)); } public function testGetHandlerViaInterface() @@ -39,7 +38,7 @@ public function testGetHandlerViaInterface() $container->set(DummyMessageInterface::class, $handler); $locator = new ContainerHandlerLocator($container); - $resolvedHandler = $locator->getHandler(new Envelope(new DummyMessage('Hey'))); + $resolvedHandler = $locator->getHandler(DummyMessage::class); $this->assertSame($handler, $resolvedHandler); } @@ -52,8 +51,22 @@ public function testGetHandlerViaParentClass() $container->set(DummyMessage::class, $handler); $locator = new ContainerHandlerLocator($container); - $resolvedHandler = $locator->getHandler(new Envelope(new ChildDummyMessage('Hey'))); + $resolvedHandler = $locator->getHandler(ChildDummyMessage::class); $this->assertSame($handler, $resolvedHandler); } + + public function testGetHandlerViaTopic() + { + $handler1 = function () {}; + $handler2 = function () {}; + + $container = new Container(); + $locator = new ContainerHandlerLocator($container); + $container->set(DummyMessage::class, $handler1); + $container->set('foo', $handler2); + + $resolvedHandler = $locator->getHandler('foo'); + $this->assertSame($handler2, $resolvedHandler); + } } diff --git a/src/Symfony/Component/Messenger/Tests/Middleware/SendMessageMiddlewareTest.php b/src/Symfony/Component/Messenger/Tests/Middleware/SendMessageMiddlewareTest.php index ddfa381b03129..3ba359e3ddbec 100644 --- a/src/Symfony/Component/Messenger/Tests/Middleware/SendMessageMiddlewareTest.php +++ b/src/Symfony/Component/Messenger/Tests/Middleware/SendMessageMiddlewareTest.php @@ -142,7 +142,7 @@ public function __construct(?SenderInterface $sender) $this->sender = $sender; } - public function getSender(Envelope $envelope): ?SenderInterface + public function getSender(string $topic): ?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..a1953007fe226 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 @@ -30,9 +30,10 @@ $receiver = new AmqpReceiver($connection, $serializer); $worker = new Worker($receiver, new class() implements MessageBusInterface { - public function dispatch($envelope): Envelope + public function dispatch($message, string $topic = null): Envelope { - echo 'Get envelope with message: '.get_class($envelope->getMessage())."\n"; + $envelope = Envelope::wrap($message, $topic); + echo 'Get envelope with message: '.$envelope->getTopic()."\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 index 49525e2ac69f4..8998121d8789d 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Sender/Locator/ContainerSenderLocatorTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Sender/Locator/ContainerSenderLocatorTest.php @@ -13,7 +13,6 @@ 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; @@ -33,8 +32,8 @@ public function testItReturnsTheSenderBasedOnTheMessageClass() DummyMessage::class => 'my_amqp_sender', )); - $this->assertSame($sender, $locator->getSender(new Envelope(new DummyMessage('Hello')))); - $this->assertNull($locator->getSender(new Envelope(new SecondMessage()))); + $this->assertSame($sender, $locator->getSender(DummyMessage::class)); + $this->assertNull($locator->getSender(SecondMessage::class)); } public function testItReturnsTheSenderBasedOnTheMessageParentClass() @@ -52,8 +51,8 @@ public function testItReturnsTheSenderBasedOnTheMessageParentClass() DummyMessage::class => 'my_amqp_sender', )); - $this->assertSame($sender, $locator->getSender(new Envelope(new ChildDummyMessage('Hello')))); - $this->assertNull($locator->getSender(new Envelope(new SecondMessage()))); + $this->assertSame($sender, $locator->getSender(ChildDummyMessage::class)); + $this->assertNull($locator->getSender(SecondMessage::class)); } public function testItReturnsTheSenderBasedOnTheMessageInterface() @@ -67,8 +66,21 @@ public function testItReturnsTheSenderBasedOnTheMessageInterface() DummyMessageInterface::class => 'my_amqp_sender', )); - $this->assertSame($sender, $locator->getSender(new Envelope(new DummyMessage('Hello')))); - $this->assertNull($locator->getSender(new Envelope(new SecondMessage()))); + $this->assertSame($sender, $locator->getSender(DummyMessage::class)); + $this->assertNull($locator->getSender(SecondMessage::class)); + } + + public function testItReturnsTheSenderBasedOnTheTopic() + { + $container = new Container(); + $container->set('my_amqp_sender1', $sender1 = $this->getMockBuilder(SenderInterface::class)->getMock()); + $container->set('my_amqp_sender2', $sender2 = $this->getMockBuilder(SenderInterface::class)->getMock()); + + $locator = new ContainerSenderLocator($container, array( + DummyMessageInterface::class => 'my_amqp_sender1', + 'foo' => 'my_amqp_sender2', + )); + $this->assertSame($sender2, $locator->getSender('foo')); } public function testItSupportsAWildcardInsteadOfTheMessageClass() @@ -86,7 +98,7 @@ public function testItSupportsAWildcardInsteadOfTheMessageClass() '*' => 'my_api_sender', )); - $this->assertSame($sender, $locator->getSender(new Envelope(new DummyMessage('Hello')))); - $this->assertSame($apiSender, $locator->getSender(new Envelope(new SecondMessage()))); + $this->assertSame($sender, $locator->getSender(DummyMessage::class)); + $this->assertSame($apiSender, $locator->getSender(SecondMessage::class)); } } diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Sender/Locator/SenderLocatorTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Sender/Locator/SenderLocatorTest.php index 0063a603b3651..b16ae0337aba8 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Sender/Locator/SenderLocatorTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Sender/Locator/SenderLocatorTest.php @@ -12,7 +12,6 @@ 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; @@ -28,8 +27,8 @@ public function testItReturnsTheSenderBasedOnTheMessageClass() DummyMessage::class => $sender, )); - $this->assertSame($sender, $locator->getSender(new Envelope(new DummyMessage('Hello')))); - $this->assertNull($locator->getSender(new Envelope(new SecondMessage()))); + $this->assertSame($sender, $locator->getSender(DummyMessage::class)); + $this->assertNull($locator->getSender(SecondMessage::class)); } public function testItThrowsExceptionIfConfigurationIsWrong() @@ -39,6 +38,6 @@ public function testItThrowsExceptionIfConfigurationIsWrong() )); $this->expectException(RuntimeException::class); - $locator->getSender(new Envelope(new DummyMessage('Hello'))); + $locator->getSender(DummyMessage::class); } } diff --git a/src/Symfony/Component/Messenger/TraceableMessageBus.php b/src/Symfony/Component/Messenger/TraceableMessageBus.php index b030cef498266..646a6d3efaf76 100644 --- a/src/Symfony/Component/Messenger/TraceableMessageBus.php +++ b/src/Symfony/Component/Messenger/TraceableMessageBus.php @@ -27,9 +27,9 @@ public function __construct(MessageBusInterface $decoratedBus) /** * {@inheritdoc} */ - public function dispatch($message): Envelope + public function dispatch($message, string $topic = null): Envelope { - $envelope = $message instanceof Envelope ? $message : new Envelope($message); + $envelope = Envelope::wrap($message, $topic); $context = array( 'stamps' => array_values($envelope->all()), 'message' => $envelope->getMessage(), @@ -38,7 +38,7 @@ public function dispatch($message): Envelope ); try { - return $this->decoratedBus->dispatch($message); + return $this->decoratedBus->dispatch($message, $topic); } catch (\Throwable $e) { $context['exception'] = $e; diff --git a/src/Symfony/Component/Messenger/Transport/Sender/Locator/AbstractSenderLocator.php b/src/Symfony/Component/Messenger/Transport/Sender/Locator/AbstractSenderLocator.php index 1d0e4bc5fda1c..c59ae62a7203f 100644 --- a/src/Symfony/Component/Messenger/Transport/Sender/Locator/AbstractSenderLocator.php +++ b/src/Symfony/Component/Messenger/Transport/Sender/Locator/AbstractSenderLocator.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Messenger\Transport\Sender\Locator; -use Symfony\Component\Messenger\Envelope; - /** * @author Samuel Roze * @@ -20,19 +18,23 @@ */ abstract class AbstractSenderLocator implements SenderLocatorInterface { - public static function getValueFromMessageRouting(array $mapping, Envelope $envelope) + public static function getValueFromMessageRouting(array $mapping, string $topic) { - if (isset($mapping[$class = \get_class($envelope->getMessage())])) { - return $mapping[$class]; + if (isset($mapping[$topic])) { + return $mapping[$topic]; + } + + if (!class_exists($topic) && !interface_exists($topic, false)) { + return $mapping['*'] ?? null; } - foreach (class_parents($class) as $name) { + foreach (class_parents($topic) as $name) { if (isset($mapping[$name])) { return $mapping[$name]; } } - foreach (class_implements($class) as $name) { + foreach (class_implements($topic) as $name) { if (isset($mapping[$name])) { return $mapping[$name]; } diff --git a/src/Symfony/Component/Messenger/Transport/Sender/Locator/ContainerSenderLocator.php b/src/Symfony/Component/Messenger/Transport/Sender/Locator/ContainerSenderLocator.php index ca2418d39fa54..34b0a12673d28 100644 --- a/src/Symfony/Component/Messenger/Transport/Sender/Locator/ContainerSenderLocator.php +++ b/src/Symfony/Component/Messenger/Transport/Sender/Locator/ContainerSenderLocator.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Messenger\Transport\Sender\Locator; use Psr\Container\ContainerInterface; -use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Transport\Sender\SenderInterface; /** @@ -21,20 +20,20 @@ class ContainerSenderLocator extends AbstractSenderLocator { private $senderServiceLocator; - private $messageToSenderIdMapping; + private $topicToSenderIdMapping; - public function __construct(ContainerInterface $senderServiceLocator, array $messageToSenderIdMapping) + public function __construct(ContainerInterface $senderServiceLocator, array $topicToSenderIdMapping) { $this->senderServiceLocator = $senderServiceLocator; - $this->messageToSenderIdMapping = $messageToSenderIdMapping; + $this->topicToSenderIdMapping = $topicToSenderIdMapping; } /** * {@inheritdoc} */ - public function getSender(Envelope $envelope): ?SenderInterface + public function getSender(string $topic): ?SenderInterface { - $senderId = self::getValueFromMessageRouting($this->messageToSenderIdMapping, $envelope); + $senderId = self::getValueFromMessageRouting($this->topicToSenderIdMapping, $topic); 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 index 3fa5932b9ebbb..776c21902c82f 100644 --- a/src/Symfony/Component/Messenger/Transport/Sender/Locator/SenderLocator.php +++ b/src/Symfony/Component/Messenger/Transport/Sender/Locator/SenderLocator.php @@ -11,7 +11,6 @@ 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; @@ -20,25 +19,25 @@ */ class SenderLocator extends AbstractSenderLocator { - private $messageToSenderMapping; + private $topicToSenderMapping; - public function __construct(array $messageToSenderMapping) + public function __construct(array $topicToSenderMapping) { - $this->messageToSenderMapping = $messageToSenderMapping; + $this->topicToSenderMapping = $topicToSenderMapping; } /** * {@inheritdoc} */ - public function getSender(Envelope $envelope): ?SenderInterface + public function getSender(string $topic): ?SenderInterface { - $sender = self::getValueFromMessageRouting($this->messageToSenderMapping, $envelope); + $sender = self::getValueFromMessageRouting($this->topicToSenderMapping, $topic); 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))); + throw new RuntimeException(sprintf('The sender instance provided for message "%s" should be of type "%s" but got "%s".', $topic, 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 index bb0216cda0e5e..95943f3bb0c20 100644 --- a/src/Symfony/Component/Messenger/Transport/Sender/Locator/SenderLocatorInterface.php +++ b/src/Symfony/Component/Messenger/Transport/Sender/Locator/SenderLocatorInterface.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Messenger\Transport\Sender\Locator; -use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Transport\Sender\SenderInterface; /** @@ -23,5 +22,5 @@ interface SenderLocatorInterface /** * Gets the sender (if applicable) for the given message object. */ - public function getSender(Envelope $envelope): ?SenderInterface; + public function getSender(string $topic): ?SenderInterface; } From f93676419923014d1cfd65aa850c500fcd06a467 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 26 Oct 2018 14:13:10 +0200 Subject: [PATCH 2/2] [Messenger] remove interfaces/parent classes-based message subcription in favor of topic-based subscription --- src/Symfony/Component/Messenger/CHANGELOG.md | 3 +- .../Locator/AbstractHandlerLocator.php | 48 ------------------- .../Locator/ContainerHandlerLocator.php | 6 +-- .../Handler/Locator/HandlerLocator.php | 6 +-- .../Middleware/SendMessageMiddleware.php | 3 +- .../Locator/ContainerHandlerLocatorTest.php | 28 ----------- .../Middleware/SendMessageMiddlewareTest.php | 32 ------------- .../Locator/ContainerSenderLocatorTest.php | 35 -------------- .../Sender/Locator/AbstractSenderLocator.php | 45 ----------------- .../Sender/Locator/ContainerSenderLocator.php | 6 +-- .../Sender/Locator/SenderLocator.php | 5 +- 11 files changed, 14 insertions(+), 203 deletions(-) delete mode 100644 src/Symfony/Component/Messenger/Handler/Locator/AbstractHandlerLocator.php delete mode 100644 src/Symfony/Component/Messenger/Transport/Sender/Locator/AbstractSenderLocator.php diff --git a/src/Symfony/Component/Messenger/CHANGELOG.md b/src/Symfony/Component/Messenger/CHANGELOG.md index 1226cce2ee1cf..78a56db23f706 100644 --- a/src/Symfony/Component/Messenger/CHANGELOG.md +++ b/src/Symfony/Component/Messenger/CHANGELOG.md @@ -6,6 +6,7 @@ CHANGELOG * The component is not experimental anymore * All the changes below are BC BREAKS + * subscribing to messages based on their interfaces or parent classes has been removed in favor of topic-based subscription * `MessageBusInterface::dispatch()`, `MiddlewareInterface::handle()` and `SenderInterface::send()` return `Envelope` * `MessageBusInterface::dispatch()` now takes a second `string $topic = null` argument * `MiddlewareInterface::handle()` now require an `Envelope` as first argument and a `StackInterface` as second @@ -27,7 +28,7 @@ CHANGELOG * Renamed and moved `ReceivedMessage`, `ValidationConfiguration` and `SerializerConfiguration` in the `Stamp` namespace * Removed the `WrapIntoReceivedMessage` * `MessengerDataCollector::getMessages()` returns an iterable, not just an array anymore - * `AbstractHandlerLocator` is now internal + * The `AbstractHandlerLocator` and `AbstractSenderLocator` classes have been removed * `HandlerLocatorInterface::resolve()` has been replaced by `getHandler(string $topic): ?callable` and shouldn't throw when no handlers are found * `SenderLocatorInterface::getSenderForMessage()` has been replaced by `getSender(string $topic): ?SenderInterface` * Classes in the `Middleware\Enhancers` sub-namespace have been moved to the `Middleware` one 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 b564158770257..0000000000000 --- a/src/Symfony/Component/Messenger/Handler/Locator/AbstractHandlerLocator.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\Handler\Locator; - -/** - * @author Miha Vrhovnik - * @author Samuel Roze - * - * @internal - */ -abstract class AbstractHandlerLocator implements HandlerLocatorInterface -{ - public function getHandler(string $topic): ?callable - { - if ($handler = $this->getHandlerByName($topic)) { - return $handler; - } - - if (!class_exists($topic) && !interface_exists($topic, false)) { - return null; - } - - foreach (class_parents($topic) as $name) { - if ($handler = $this->getHandlerByName($name)) { - return $handler; - } - } - - foreach (class_implements($topic) 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 index 0e1837f896abe..c3691f75c5434 100644 --- a/src/Symfony/Component/Messenger/Handler/Locator/ContainerHandlerLocator.php +++ b/src/Symfony/Component/Messenger/Handler/Locator/ContainerHandlerLocator.php @@ -17,7 +17,7 @@ * @author Miha Vrhovnik * @author Samuel Roze */ -class ContainerHandlerLocator extends AbstractHandlerLocator +class ContainerHandlerLocator implements HandlerLocatorInterface { private $container; @@ -29,8 +29,8 @@ public function __construct(ContainerInterface $container) /** * {@inheritdoc} */ - protected function getHandlerByName(string $name): ?callable + public function getHandler(string $topic): ?callable { - return $this->container->has($name) ? $this->container->get($name) : null; + return $this->container->has($topic) ? $this->container->get($topic) : null; } } diff --git a/src/Symfony/Component/Messenger/Handler/Locator/HandlerLocator.php b/src/Symfony/Component/Messenger/Handler/Locator/HandlerLocator.php index 8b4b9615a28af..cce944dd509c9 100644 --- a/src/Symfony/Component/Messenger/Handler/Locator/HandlerLocator.php +++ b/src/Symfony/Component/Messenger/Handler/Locator/HandlerLocator.php @@ -14,7 +14,7 @@ /** * @author Samuel Roze */ -class HandlerLocator extends AbstractHandlerLocator +class HandlerLocator implements HandlerLocatorInterface { /** * Maps a topic to a given handler. @@ -29,8 +29,8 @@ public function __construct(array $topicToHandlerMapping = array()) /** * {@inheritdoc} */ - protected function getHandlerByName(string $name): ?callable + public function getHandler(string $topic): ?callable { - return $this->topicToHandlerMapping[$name] ?? null; + return $this->topicToHandlerMapping[$topic] ?? null; } } diff --git a/src/Symfony/Component/Messenger/Middleware/SendMessageMiddleware.php b/src/Symfony/Component/Messenger/Middleware/SendMessageMiddleware.php index cb04aad75a7f7..f3e3508056fdb 100644 --- a/src/Symfony/Component/Messenger/Middleware/SendMessageMiddleware.php +++ b/src/Symfony/Component/Messenger/Middleware/SendMessageMiddleware.php @@ -13,7 +13,6 @@ 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; /** @@ -46,7 +45,7 @@ public function handle(Envelope $envelope, StackInterface $stack): Envelope if ($sender) { $envelope = $sender->send($envelope); - if (!AbstractSenderLocator::getValueFromMessageRouting($this->topicsToSendAndHandle, $envelope->getTopic())) { + if (!($this->topicsToSendAndHandle[$envelope->getTopic()] ?? $this->topicsToSendAndHandle['*'] ?? false)) { // message should only be sent and be not handled by the next middleware return $envelope; } diff --git a/src/Symfony/Component/Messenger/Tests/Handler/Locator/ContainerHandlerLocatorTest.php b/src/Symfony/Component/Messenger/Tests/Handler/Locator/ContainerHandlerLocatorTest.php index 3fd8562df91c1..a23cbeb07855c 100644 --- a/src/Symfony/Component/Messenger/Tests/Handler/Locator/ContainerHandlerLocatorTest.php +++ b/src/Symfony/Component/Messenger/Tests/Handler/Locator/ContainerHandlerLocatorTest.php @@ -5,9 +5,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\Messenger\Handler\Locator\ContainerHandlerLocator; -use Symfony\Component\Messenger\Tests\Fixtures\ChildDummyMessage; use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage; -use Symfony\Component\Messenger\Tests\Fixtures\DummyMessageInterface; class ContainerHandlerLocatorTest extends TestCase { @@ -30,32 +28,6 @@ public function testNoHandlersReturnsNull() $this->assertNull($locator->getHandler(DummyMessage::class)); } - public function testGetHandlerViaInterface() - { - $handler = function () {}; - - $container = new Container(); - $container->set(DummyMessageInterface::class, $handler); - - $locator = new ContainerHandlerLocator($container); - $resolvedHandler = $locator->getHandler(DummyMessage::class); - - $this->assertSame($handler, $resolvedHandler); - } - - public function testGetHandlerViaParentClass() - { - $handler = function () {}; - - $container = new Container(); - $container->set(DummyMessage::class, $handler); - - $locator = new ContainerHandlerLocator($container); - $resolvedHandler = $locator->getHandler(ChildDummyMessage::class); - - $this->assertSame($handler, $resolvedHandler); - } - public function testGetHandlerViaTopic() { $handler1 = function () {}; diff --git a/src/Symfony/Component/Messenger/Tests/Middleware/SendMessageMiddlewareTest.php b/src/Symfony/Component/Messenger/Tests/Middleware/SendMessageMiddlewareTest.php index 3ba359e3ddbec..c71d7eb50c0c4 100644 --- a/src/Symfony/Component/Messenger/Tests/Middleware/SendMessageMiddlewareTest.php +++ b/src/Symfony/Component/Messenger/Tests/Middleware/SendMessageMiddlewareTest.php @@ -15,9 +15,7 @@ use Symfony\Component\Messenger\Middleware\MiddlewareInterface; use Symfony\Component\Messenger\Middleware\SendMessageMiddleware; use Symfony\Component\Messenger\Stamp\ReceivedStamp; -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; @@ -63,36 +61,6 @@ public function testItAlsoCallsTheNextMiddlewareBasedOnTheMessageClass() $middleware->handle($envelope, $this->getStackMock()); } - public function testItAlsoCallsTheNextMiddlewareBasedOnTheMessageParentClass() - { - $message = new ChildDummyMessage('Hey'); - $envelope = new Envelope($message); - $sender = $this->getMockBuilder(SenderInterface::class)->getMock(); - - $middleware = new SendMessageMiddleware(new InMemorySenderLocator($sender), array( - DummyMessage::class => true, - )); - - $sender->expects($this->once())->method('send')->with($envelope)->willReturn($envelope); - - $middleware->handle($envelope, $this->getStackMock()); - } - - public function testItAlsoCallsTheNextMiddlewareBasedOnTheMessageInterface() - { - $message = new DummyMessage('Hey'); - $envelope = new Envelope($message); - $sender = $this->getMockBuilder(SenderInterface::class)->getMock(); - - $middleware = new SendMessageMiddleware(new InMemorySenderLocator($sender), array( - DummyMessageInterface::class => true, - )); - - $sender->expects($this->once())->method('send')->with($envelope)->willReturn($envelope); - - $middleware->handle($envelope, $this->getStackMock()); - } - public function testItAlsoCallsTheNextMiddlewareBasedOnWildcard() { $message = new DummyMessage('Hey'); diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Sender/Locator/ContainerSenderLocatorTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Sender/Locator/ContainerSenderLocatorTest.php index 8998121d8789d..489cb716b7f36 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Sender/Locator/ContainerSenderLocatorTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Sender/Locator/ContainerSenderLocatorTest.php @@ -13,7 +13,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Container; -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; @@ -36,40 +35,6 @@ public function testItReturnsTheSenderBasedOnTheMessageClass() $this->assertNull($locator->getSender(SecondMessage::class)); } - 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(ChildDummyMessage::class)); - $this->assertNull($locator->getSender(SecondMessage::class)); - } - - 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(DummyMessage::class)); - $this->assertNull($locator->getSender(SecondMessage::class)); - } - public function testItReturnsTheSenderBasedOnTheTopic() { $container = new Container(); 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 c59ae62a7203f..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; - -/** - * @author Samuel Roze - * - * @internal - */ -abstract class AbstractSenderLocator implements SenderLocatorInterface -{ - public static function getValueFromMessageRouting(array $mapping, string $topic) - { - if (isset($mapping[$topic])) { - return $mapping[$topic]; - } - - if (!class_exists($topic) && !interface_exists($topic, false)) { - return $mapping['*'] ?? null; - } - - foreach (class_parents($topic) as $name) { - if (isset($mapping[$name])) { - return $mapping[$name]; - } - } - - foreach (class_implements($topic) 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 index 34b0a12673d28..6eb130caeedf1 100644 --- a/src/Symfony/Component/Messenger/Transport/Sender/Locator/ContainerSenderLocator.php +++ b/src/Symfony/Component/Messenger/Transport/Sender/Locator/ContainerSenderLocator.php @@ -17,7 +17,7 @@ /** * @author Samuel Roze */ -class ContainerSenderLocator extends AbstractSenderLocator +class ContainerSenderLocator implements SenderLocatorInterface { private $senderServiceLocator; private $topicToSenderIdMapping; @@ -33,8 +33,8 @@ public function __construct(ContainerInterface $senderServiceLocator, array $top */ public function getSender(string $topic): ?SenderInterface { - $senderId = self::getValueFromMessageRouting($this->topicToSenderIdMapping, $topic); + $senderId = $this->topicToSenderIdMapping[$topic] ?? $this->topicToSenderIdMapping['*'] ?? null; - return $senderId ? $this->senderServiceLocator->get($senderId) : null; + return null !== $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 index 776c21902c82f..5e195170afd34 100644 --- a/src/Symfony/Component/Messenger/Transport/Sender/Locator/SenderLocator.php +++ b/src/Symfony/Component/Messenger/Transport/Sender/Locator/SenderLocator.php @@ -17,7 +17,7 @@ /** * @author Fabien Potencier */ -class SenderLocator extends AbstractSenderLocator +class SenderLocator implements SenderLocatorInterface { private $topicToSenderMapping; @@ -31,8 +31,7 @@ public function __construct(array $topicToSenderMapping) */ public function getSender(string $topic): ?SenderInterface { - $sender = self::getValueFromMessageRouting($this->topicToSenderMapping, $topic); - if (null === $sender) { + if (null === $sender = $this->topicToSenderMapping[$topic] ?? $this->topicToSenderMapping['*'] ?? null) { return null; }