Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@
<services>
<defaults public="false" />

<!-- Bus -->
<!-- Message Bus -->
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on purpose, in preparation for event bus

<service id="message_bus" class="Symfony\Component\Message\MessageBus" public="true">
<argument type="collection" /> <!-- Middlewares -->
</service>

<service id="Symfony\Component\Message\MessageBusInterface" alias="message_bus" />

<!-- Handlers -->
<service id="message.handler_resolver" class="Symfony\Component\Message\HandlerLocator">
<argument type="collection" /> <!-- Message to handler mapping -->
<service id="message.container_message_handler_resolver" class="Symfony\Component\Message\ContainerHandlerLocator">
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

message on purpose, in preparation for event bus

<argument type="service" id="service_container"/>
</service>

<service id="message.middleware.call_message_handler" class="Symfony\Component\Message\Middleware\HandleMessageMiddleware">
<argument type="service" id="message.handler_resolver" />
<argument type="service" id="message.container_message_handler_resolver" />

<tag name="message_middleware" priority="-10" />
</service>
Expand Down
43 changes: 43 additions & 0 deletions src/Symfony/Component/Message/ContainerHandlerLocator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Message;

use Psr\Container\ContainerInterface;
use Symfony\Component\Message\Exception\NoHandlerForMessageException;

/**
* @author Miha Vrhovnik <miha.vrhovnik@gmail.com>
*/
class ContainerHandlerLocator implements HandlerLocatorInterface
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WDYT about Factory instead of Locator?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit late 🙊

Copy link

@ro0NL ro0NL Dec 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that implies renaming the interface to HandlerFactoryInterface right? Tend to agree we're indeed factorizing here :) but current naming is fine also IMHO.

{
/**
* @var ContainerInterface
*/
private $serviceLocator;

public function __construct(ContainerInterface $serviceLocator)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SF usually calls this one $container

{
$this->serviceLocator = $serviceLocator;
}

public function resolve($message): callable
{
$messageKey = get_class($message);

if (!$this->serviceLocator->has($messageKey)) {
throw new NoHandlerForMessageException(sprintf('No handler for message "%s"', $messageKey));
}

return $this->serviceLocator->get($messageKey);
}

}
28 changes: 23 additions & 5 deletions src/Symfony/Component/Message/DependencyInjection/MessagePass.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\Message\Handler\MessageHandlerCollection;

/**
* @author Samuel Roze <samuel.roze@gmail.com>
Expand All @@ -29,7 +32,7 @@ class MessagePass implements CompilerPassInterface
private $messageHandlerResolverService;
private $handlerTag;

public function __construct(string $messageBusService = 'message_bus', string $middlewareTag = 'message_middleware', string $messageHandlerResolverService = 'message.handler_resolver', string $handlerTag = 'message_handler')
public function __construct(string $messageBusService = 'message_bus', string $middlewareTag = 'message_middleware', string $messageHandlerResolverService = 'message.container_message_handler_resolver', string $handlerTag = 'message_handler')
{
$this->messageBusService = $messageBusService;
$this->middlewareTag = $middlewareTag;
Expand All @@ -53,11 +56,10 @@ public function process(ContainerBuilder $container)
$busDefinition = $container->getDefinition($this->messageBusService);
$busDefinition->replaceArgument(0, $middlewares);

$handlerResolver = $container->getDefinition($this->messageHandlerResolverService);
$handlerResolver->replaceArgument(0, $this->findHandlers($container));
$this->registerHandlers($container);
}

private function findHandlers(ContainerBuilder $container): array
private function registerHandlers(ContainerBuilder $container)
{
$handlersByMessage = array();

Expand All @@ -79,7 +81,23 @@ private function findHandlers(ContainerBuilder $container): array
$handlersByMessage[$message] = call_user_func_array('array_merge', $handlersByMessage[$message]);
}

return $handlersByMessage;

$definitions = array();
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ro0NL is this what you had in mind

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, exactly.

foreach ($handlersByMessage as $message => $handlers) {
if (1 === count($handlers)) {
$handlersByMessage[$message] = current($handlers);
} else {
$d = new Definition(MessageHandlerCollection::class, array($handlers));
$d->setPrivate(true);
$serviceId = hash('sha1', $message);
$definitions[$serviceId] = $d;
$handlersByMessage[$message] = new Reference($serviceId);
}
}
$container->addDefinitions($definitions);

$handlerResolver = $container->getDefinition($this->messageHandlerResolverService);
$handlerResolver->replaceArgument(0, ServiceLocatorTagPass::register($container, $handlersByMessage));
}

private function guessHandledClass(ContainerBuilder $container, string $serviceId): string
Expand Down