[Messenger] fix support for abstract handlers

This commit is contained in:
TimiTao 2019-05-30 08:07:12 +02:00 committed by Nicolas Grekas
parent a66b645681
commit 22e59f31be
2 changed files with 46 additions and 2 deletions

View File

@ -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();
}
}
}

View File

@ -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');