Skip to content

Instantly share code, notes, and snippets.

@zerkalica
Created March 26, 2013 11:31
Show Gist options
  • Save zerkalica/5244743 to your computer and use it in GitHub Desktop.
Save zerkalica/5244743 to your computer and use it in GitHub Desktop.
<?php
namespace Millwright\CQRSDomain\Bus;
/**
* Util
*
* @author nexor
*/
class BusUtil
{
/**
* Convert plain handlers list to [command -> [handler::method map]]
*
* @param array|\IteratorAggregate $handlers list of command or event handler objects or definuitions
* @param \Closure|null $getClass how to get class name from definition function($object) {return get_class($object)}
* @param \Closure|null $prepareClass how to convert command class name to map key
*
* @return array (commandClass => [handlerObject, methodName][])
*
* @throws \LogicException If more than one command defined in handlers
*/
public static function buildMap($handlers, \Closure $getClass = null, \Closure $prepareClass = null) {
$groups = array();
if ($getClass === null) {
$getClass = function($object)
{
return get_class($object);
};
}
if ($prepareClass === null) {
$prepareClass = function($className)
{
return $className;
};
}
foreach ($handlers as $handler) {
$class = $getClass($handler);
$reflClass = new \ReflectionClass($class);
foreach ($reflClass->getMethods() as $method) {
/** @var $commandParam \ReflectionParameter */
if (!$method->isPublic() || $method->isConstructor()) {
continue;
}
/** @var $commandParam \ReflectionParameter */
$commandParam = current($method->getParameters());
$paramClass = $commandParam->getClass();
if ($paramClass) {
$name = $prepareClass($paramClass->getName());
$groups[$name][] = array($handler, $method->getName());
}
}
}
return $groups;
}
}
<?php
namespace Millwright\CQRSDomain\Bus;
/**
* Abstract bus
*/
use Doctrine\Common\Util\Debug;
class Bus implements BusInterface
{
protected $handlers;
protected $throw;
/**
* Constructor
*
* @param object[] $handlers
* @param boolean $throw throw exception if handler not found for given command
*/
public function __construct(array $handlers, $throw = false)
{
$this->handlers = $handlers;
$this->throw = $throw;
}
/**
* {@inheritDoc}
*
* @throws \InvalidArgumentException Handler is not registered for command
*/
public function handle()
{
$args = func_get_args();
$className = get_class($args[0]);
if (!isset($this->handlers[$className])) {
if ($this->throw) {
throw new \InvalidArgumentException(sprintf('Handler is not registered for command %s', $className));
} else {
return null;
}
}
$handlers = $this->handlers[$className];
$result = null;
foreach ($handlers as $handler) {
$res = call_user_func_array($handler, $args);
if (null !== $res) {
$result = $res;
}
}
return $result;
}
}
<?php
namespace Millwright\CQRSDomain\Plugins\Symfony\DependencyInjection\Compiler;
use Millwright\CQRSDomain\Bus\BusUtil;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Definition;
/**
* Handler pass
*/
class HandlerPass implements CompilerPassInterface
{
/**
* {@inheritDoc}
*/
public function process(ContainerBuilder $container)
{
$getClass = function(Definition $def)
{
return $def->getClass();
};
$services = $this->getDefinitions('millwright_cqrs.encoder', $container);
$container->findDefinition('millwright_cqrs.security')->replaceArgument(3, $services);
$services = $this->getDefinitions('millwright_cqrs.command_handler', $container);
$services = BusUtil::buildMap($services, $getClass);
$container->findDefinition('millwright_cqrs.command_bus_proto')->replaceArgument(0, $services);
$services = $this->getDefinitions('millwright_cqrs.message_handler', $container);
$services = BusUtil::buildMap($services, $getClass);
$container->findDefinition('millwright_cqrs.message_bus_proto')->replaceArgument(0, $services);
}
/**
* Gets definitions
*
* @param string $tag
* @param ContainerBuilder $container
*
* @return Definition[id]
*/
protected function getDefinitions($tag, ContainerBuilder $container)
{
$definitions = array();
foreach ($container->findTaggedServiceIds($tag) as $id => $def) {
$definitions[$id] = $container->getDefinition($id);
}
return $definitions;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment