diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/MessengerCommandsPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/MessengerCommandsPass.php new file mode 100644 index 000000000000..202a7ab893ef --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/MessengerCommandsPass.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\Messenger\DependencyInjection\MessengerPass; + +/** + * @author Samuel Roze + */ +class MessengerCommandsPass implements CompilerPassInterface +{ + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('console.command.messenger_consume_messages')) { + return; + } + + $buses = array(); + foreach ($container->findTaggedServiceIds('messenger.bus') as $busId => $tags) { + $buses[$busId] = new Reference($busId); + } + + $container + ->getDefinition('console.command.messenger_consume_messages') + ->replaceArgument(3, $this->findReceiverNames($container)) + ; + } + + private function findReceiverNames(ContainerBuilder $container) + { + $receiverNames = array(); + foreach (MessengerPass::findReceivers($container, 'messenger.receiver') as $name => $reference) { + $receiverNames[(string) $reference] = $name; + } + + return array_values($receiverNames); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 506644d5fa32..96e3283063ac 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -21,6 +21,7 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilderDebugDumpPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\DataCollectorTranslatorPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\MessengerCommandsPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TemplatingPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TestServiceContainerRealRefPass; @@ -119,6 +120,7 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new TestServiceContainerWeakRefPass(), PassConfig::TYPE_BEFORE_REMOVING, -32); $container->addCompilerPass(new TestServiceContainerRealRefPass(), PassConfig::TYPE_AFTER_REMOVING); $this->addCompilerPassIfExists($container, MessengerPass::class); + $container->addCompilerPass(new MessengerCommandsPass()); if ($container->getParameter('kernel.debug')) { $container->addCompilerPass(new AddDebugLogProcessorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/MessengerCommandsPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/MessengerCommandsPassTest.php new file mode 100644 index 000000000000..056d7edac981 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/MessengerCommandsPassTest.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; + +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\MessengerCommandsPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\Messenger\Command\ConsumeMessagesCommand; +use Symfony\Component\Messenger\MessageBusInterface; +use Symfony\Component\Messenger\Tests\Fixtures\DummyReceiver; +use Symfony\Component\Messenger\Transport\AmqpExt\AmqpReceiver; + +class MessengerCommandsPassTest extends TestCase +{ + public function testItRegistersMultipleReceiversAndSetsTheReceiverNamesOnTheCommand() + { + $container = new ContainerBuilder(); + $container->register('my_bus_name', MessageBusInterface::class)->addTag('messenger.bus')->setArgument(0, array()); + $container->register('console.command.messenger_consume_messages', ConsumeMessagesCommand::class)->setArguments(array( + null, + new Reference('messenger.receiver_locator'), + null, + null, + null, + )); + + $container->register(AmqpReceiver::class, AmqpReceiver::class)->addTag('messenger.receiver', array('alias' => 'amqp')); + $container->register(DummyReceiver::class, DummyReceiver::class)->addTag('messenger.receiver', array('alias' => 'dummy')); + + (new MessengerCommandsPass())->process($container); + + $this->assertSame(array('amqp', 'dummy'), $container->getDefinition('console.command.messenger_consume_messages')->getArgument(3)); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index de0fe10f9122..2f96e36435b1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -67,6 +67,7 @@ "symfony/asset": "<3.4", "symfony/console": "<3.4", "symfony/form": "<4.1", + "symfony/messenger": "<4.1.5", "symfony/property-info": "<3.4", "symfony/serializer": "<4.1", "symfony/stopwatch": "<3.4", diff --git a/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php b/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php index 2de3289a5169..15f3fbf973bd 100644 --- a/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php +++ b/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php @@ -220,30 +220,7 @@ private function guessHandledClasses(\ReflectionClass $handlerClass, string $ser private function registerReceivers(ContainerBuilder $container) { - $receiverMapping = array(); - - foreach ($container->findTaggedServiceIds($this->receiverTag) as $id => $tags) { - $receiverClass = $container->findDefinition($id)->getClass(); - if (!is_subclass_of($receiverClass, ReceiverInterface::class)) { - throw new RuntimeException(sprintf('Invalid receiver "%s": class "%s" must implement interface "%s".', $id, $receiverClass, ReceiverInterface::class)); - } - - $receiverMapping[$id] = new Reference($id); - - foreach ($tags as $tag) { - if (isset($tag['alias'])) { - $receiverMapping[$tag['alias']] = $receiverMapping[$id]; - } - } - } - - if ($container->hasDefinition('console.command.messenger_consume_messages')) { - $receiverNames = array(); - foreach ($receiverMapping as $name => $reference) { - $receiverNames[(string) $reference] = $name; - } - $container->getDefinition('console.command.messenger_consume_messages')->replaceArgument(3, array_values($receiverNames)); - } + $receiverMapping = self::findReceivers($container, $this->receiverTag); $container->getDefinition('messenger.receiver_locator')->replaceArgument(0, $receiverMapping); } @@ -312,4 +289,29 @@ private function registerBusMiddleware(ContainerBuilder $container, string $busI $container->getDefinition($busId)->replaceArgument(0, $middlewareReferences); } + + /** + * @internal + */ + public static function findReceivers(ContainerBuilder $container, string $receiverTag) + { + $receiverMapping = array(); + + foreach ($container->findTaggedServiceIds($receiverTag) as $id => $tags) { + $receiverClass = $container->findDefinition($id)->getClass(); + if (!is_subclass_of($receiverClass, ReceiverInterface::class)) { + throw new RuntimeException(sprintf('Invalid receiver "%s": class "%s" must implement interface "%s".', $id, $receiverClass, ReceiverInterface::class)); + } + + $receiverMapping[$id] = new Reference($id); + + foreach ($tags as $tag) { + if (isset($tag['alias'])) { + $receiverMapping[$tag['alias']] = $receiverMapping[$id]; + } + } + } + + return $receiverMapping; + } } diff --git a/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php b/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php index f3fc76baa386..e4fbef43820f 100644 --- a/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php +++ b/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php @@ -18,11 +18,9 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ServiceLocator; -use Symfony\Component\Messenger\Command\ConsumeMessagesCommand; use Symfony\Component\Messenger\Command\DebugCommand; 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\MessageHandlerInterface; use Symfony\Component\Messenger\Handler\MessageSubscriberInterface; @@ -35,12 +33,12 @@ use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage; use Symfony\Component\Messenger\Tests\Fixtures\DummyQuery; use Symfony\Component\Messenger\Tests\Fixtures\DummyQueryHandler; +use Symfony\Component\Messenger\Tests\Fixtures\DummyReceiver; use Symfony\Component\Messenger\Tests\Fixtures\MultipleBusesMessage; 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\ReceiverInterface; class MessengerPassTest extends TestCase { @@ -237,24 +235,6 @@ public function testItRegistersReceiversWithoutTagName() $this->assertEquals(array(AmqpReceiver::class => new Reference(AmqpReceiver::class)), $container->getDefinition('messenger.receiver_locator')->getArgument(0)); } - public function testItRegistersMultipleReceiversAndSetsTheReceiverNamesOnTheCommand() - { - $container = $this->getContainerBuilder(); - $container->register('console.command.messenger_consume_messages', ConsumeMessagesCommand::class)->setArguments(array( - new Reference('message_bus'), - new Reference('messenger.receiver_locator'), - null, - null, - )); - - $container->register(AmqpReceiver::class, AmqpReceiver::class)->addTag('messenger.receiver', array('alias' => 'amqp')); - $container->register(DummyReceiver::class, DummyReceiver::class)->addTag('messenger.receiver', array('alias' => 'dummy')); - - (new MessengerPass())->process($container); - - $this->assertSame(array('amqp', 'dummy'), $container->getDefinition('console.command.messenger_consume_messages')->getArgument(3)); - } - public function testItRegistersSenders() { $container = $this->getContainerBuilder(); @@ -587,20 +567,6 @@ public function __invoke(DummyMessage $message): void } } -class DummyReceiver implements ReceiverInterface -{ - public function receive(callable $handler): void - { - for ($i = 0; $i < 3; ++$i) { - $handler(Envelope::wrap(new DummyMessage("Dummy $i"))); - } - } - - public function stop(): void - { - } -} - class InvalidReceiver { } diff --git a/src/Symfony/Component/Messenger/Tests/Fixtures/DummyReceiver.php b/src/Symfony/Component/Messenger/Tests/Fixtures/DummyReceiver.php new file mode 100644 index 000000000000..86638aa22ae1 --- /dev/null +++ b/src/Symfony/Component/Messenger/Tests/Fixtures/DummyReceiver.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\Tests\Fixtures; + +use Symfony\Component\Messenger\Envelope; +use Symfony\Component\Messenger\Transport\ReceiverInterface; + +class DummyReceiver implements ReceiverInterface +{ + public function receive(callable $handler): void + { + for ($i = 0; $i < 3; ++$i) { + $handler(Envelope::wrap(new DummyMessage("Dummy $i"))); + } + } + + public function stop(): void + { + } +}