diff --git a/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php b/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php index 4ab31e8404..0ec792e734 100644 --- a/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php +++ b/src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php @@ -78,7 +78,7 @@ class MessengerPass implements CompilerPassInterface throw new RuntimeException(sprintf('Invalid handler service "%s": bus "%s" specified on the tag "%s" does not exist (known ones are: %s).', $serviceId, $tag['bus'], $this->handlerTag, implode(', ', $busIds))); } - $className = $container->getDefinition($serviceId)->getClass(); + $className = $this->getServiceClass($container, $serviceId); $r = $container->getReflectionClass($className); if (null === $r) { @@ -240,7 +240,7 @@ class MessengerPass implements CompilerPassInterface $receiverMapping = []; foreach ($container->findTaggedServiceIds($this->receiverTag) as $id => $tags) { - $receiverClass = $container->findDefinition($id)->getClass(); + $receiverClass = $this->getServiceClass($container, $id); if (!is_subclass_of($receiverClass, ReceiverInterface::class)) { throw new RuntimeException(sprintf('Invalid receiver "%s": class "%s" must implement interface "%s".', $id, $receiverClass, ReceiverInterface::class)); } @@ -336,4 +336,19 @@ class MessengerPass implements CompilerPassInterface $container->getDefinition($busId)->replaceArgument(0, new IteratorArgument($middlewareReferences)); } + + private function getServiceClass(ContainerBuilder $container, string $serviceId): string + { + while (true) { + $definition = $container->findDefinition($serviceId); + + if (!$definition->getClass() && $definition instanceof ChildDefinition) { + $serviceId = $definition->getParent(); + + continue; + } + + return $definition->getClass(); + } + } } diff --git a/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php b/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php index c1c5148fd7..6f102af0c9 100644 --- a/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php +++ b/src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Messenger\Tests\DependencyInjection; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\Compiler\ResolveChildDefinitionsPass; use Symfony\Component\DependencyInjection\Compiler\ResolveClassPass; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -225,6 +226,34 @@ class MessengerPassTest extends TestCase $this->assertSame(PrioritizedHandler::class, $secondHandlerDefinition->getClass()); } + public function testRegisterAbstractHandler() + { + $container = $this->getContainerBuilder($messageBusId = 'message_bus'); + $container->register($messageBusId, MessageBusInterface::class)->addTag('messenger.bus')->setArgument(0, []); + + $container + ->register(DummyHandler::class, DummyHandler::class) + ->setAbstract(true); + + $container + ->setDefinition($abstractDirectChildId = 'direct_child', new ChildDefinition(DummyHandler::class)) + ->setAbstract(true); + + $container + ->setDefinition($abstractHandlerId = 'child', new ChildDefinition($abstractDirectChildId)) + ->addTag('messenger.message_handler'); + + (new MessengerPass())->process($container); + + $messageHandlerMapping = $container->getDefinition($messageBusId.'.messenger.handlers_locator')->getArgument(0); + $this->assertHandlerDescriptor( + $container, + $messageHandlerMapping, + DummyMessage::class, + [$abstractHandlerId] + ); + } + public function testThrowsExceptionIfTheHandlerClassDoesNotExist() { $this->expectException('Symfony\Component\DependencyInjection\Exception\RuntimeException');