Created
March 26, 2013 11:31
-
-
Save zerkalica/5244743 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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; | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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; | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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