diff --git a/src/DependencyInjection/Compiler/PluginsPass.php b/src/DependencyInjection/Compiler/PluginsPass.php new file mode 100644 index 0000000..489f6c0 --- /dev/null +++ b/src/DependencyInjection/Compiler/PluginsPass.php @@ -0,0 +1,44 @@ + $busClass) { + if (!$container->hasParameter('prooph_service_bus.' . $type . '_buses')) { + continue; + } + + $buses = $container->getParameter('prooph_service_bus.' . $type . '_buses'); + + foreach ($buses as $name => $bus) { + $globalPlugins = $container->findTaggedServiceIds('prooph_service_bus.plugin'); + $typePlugins = $container->findTaggedServiceIds(sprintf('prooph_service_bus.%s.plugin', $type . '_bus')); + $plugins = $container->findTaggedServiceIds(sprintf('prooph_service_bus.%s.plugin', $name)); + + $plugins = array_merge($globalPlugins, $typePlugins, $plugins); + + foreach ($plugins as $id => $args) { + $definition = $container->findDefinition('prooph_service_bus.' . $name); + $definition->addMethodCall('utilize', [new Reference($id)]); + } + } + } + } +} diff --git a/src/ProophServiceBusBundle.php b/src/ProophServiceBusBundle.php index 56a4c6f..d7338be 100644 --- a/src/ProophServiceBusBundle.php +++ b/src/ProophServiceBusBundle.php @@ -11,6 +11,7 @@ namespace Prooph\Bundle\ServiceBus; +use Prooph\Bundle\ServiceBus\DependencyInjection\Compiler\PluginsPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; @@ -19,7 +20,6 @@ final class ProophServiceBusBundle extends Bundle public function build(ContainerBuilder $container) { parent::build($container); - - // TODO RegisterEventListenersAndSubscribersPass like doctrine ? + $container->addCompilerPass(new PluginsPass()); } } diff --git a/test/DependencyInjection/AbtractServiceBusExtensionTestCase.php b/test/DependencyInjection/AbtractServiceBusExtensionTestCase.php index 06214c1..77400a2 100644 --- a/test/DependencyInjection/AbtractServiceBusExtensionTestCase.php +++ b/test/DependencyInjection/AbtractServiceBusExtensionTestCase.php @@ -12,15 +12,19 @@ namespace ProophTest\Bundle\ServiceBus\DependencyInjection; use PHPUnit_Framework_TestCase as TestCase; +use Prooph\Bundle\ServiceBus\DependencyInjection\Compiler\PluginsPass; use Prooph\Bundle\ServiceBus\DependencyInjection\ProophServiceBusExtension; use Prooph\ServiceBus\CommandBus; use Prooph\ServiceBus\EventBus; +use Prooph\ServiceBus\Exception\CommandDispatchException; +use Prooph\ServiceBus\Exception\MessageDispatchException; use Prooph\ServiceBus\Plugin\Router\CommandRouter; use Prooph\ServiceBus\Plugin\Router\EventRouter; use Prooph\ServiceBus\Plugin\Router\QueryRouter; use Prooph\ServiceBus\QueryBus; use ProophTest\Bundle\ServiceBus\DependencyInjection\Fixture\Model\AcmeRegisterUserCommand; use ProophTest\Bundle\ServiceBus\DependencyInjection\Fixture\Model\AcmeRegisterUserHandler; +use ProophTest\Bundle\ServiceBus\DependencyInjection\Fixture\Model\MockPlugin; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\ResolveDefinitionTemplatesPass; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -105,6 +109,72 @@ public function it_adds_default_container_plugin() self::assertSame($command, $mockHandler->lastCommand()); } + /** + * @test + */ + public function it_adds_plugins_based_on_tags() + { + $container = $this->loadContainer('plugins', new PluginsPass()); + + /** @var MockPlugin $globalPlugin */ + $globalPlugin = $container->get('global_plugin'); + + /** @var MockPlugin $commandTypePlugin */ + $commandTypePlugin = $container->get('command_type_plugin'); + + /** @var MockPlugin $mainCommandBusPlugin */ + $mainCommandBusPlugin = $container->get('main_command_bus_plugin'); + + $reset = function () use ($globalPlugin, $commandTypePlugin, $mainCommandBusPlugin) { + $globalPlugin->reset(); + $commandTypePlugin->reset(); + $mainCommandBusPlugin->reset(); + }; + + /* @var $mainCommandBus CommandBus */ + $mainCommandBus = $container->get('prooph_service_bus.main_command_bus'); + + /* @var $secondCommandBus CommandBus */ + $secondCommandBus = $container->get('prooph_service_bus.second_command_bus'); + + /* @var $mainEventBus EventBus */ + $mainEventBus = $container->get('prooph_service_bus.main_event_bus'); + + try { + $mainCommandBus->dispatch('a message'); + } catch (CommandDispatchException $ex) { + //ignore + } + + $this->assertTrue($globalPlugin->wasFired()); + $this->assertTrue($commandTypePlugin->wasFired()); + $this->assertTrue($mainCommandBusPlugin->wasFired()); + + $reset(); + + try { + $secondCommandBus->dispatch('a message'); + } catch (CommandDispatchException $ex) { + //ignore + } + + $this->assertTrue($globalPlugin->wasFired()); + $this->assertTrue($commandTypePlugin->wasFired()); + $this->assertFalse($mainCommandBusPlugin->wasFired()); + + $reset(); + + try { + $mainEventBus->dispatch('a message'); + } catch (MessageDispatchException $ex) { + //ignore + } + + $this->assertTrue($globalPlugin->wasFired()); + $this->assertFalse($commandTypePlugin->wasFired()); + $this->assertFalse($mainCommandBusPlugin->wasFired()); + } + /** * @test */ diff --git a/test/DependencyInjection/Fixture/Model/CommandTypePlugin.php b/test/DependencyInjection/Fixture/Model/CommandTypePlugin.php new file mode 100644 index 0000000..30b6037 --- /dev/null +++ b/test/DependencyInjection/Fixture/Model/CommandTypePlugin.php @@ -0,0 +1,15 @@ +fired; + } + + /** + * @param ActionEventEmitter $dispatcher + */ + public function attach(ActionEventEmitter $dispatcher) + { + $this->trackHandler($dispatcher->attachListener(MessageBus::EVENT_INITIALIZE, [$this, 'onInitialize'])); + } + + public function onInitialize(ActionEvent $event) + { + $this->fired = true; + } + + public function reset() + { + $this->fired = false; + } +} diff --git a/test/DependencyInjection/Fixture/config/xml/plugins.xml b/test/DependencyInjection/Fixture/config/xml/plugins.xml new file mode 100644 index 0000000..f1833a2 --- /dev/null +++ b/test/DependencyInjection/Fixture/config/xml/plugins.xml @@ -0,0 +1,49 @@ + + + + + + + Prooph\ServiceBus\Plugin\InvokeStrategy\OnEventStrategy + + Prooph\ProophessorDo\Model\User\Handler\RegisterUserHandler + Prooph\ProophessorDo\Model\User\Handler\UpdateUserHandler + + + + + Prooph\ServiceBus\Plugin\InvokeStrategy\OnEventStrategy + Prooph\ServiceBus\Plugin\InvokeStrategy\OnEventStrategy + + Prooph\ProophessorDo\Model\User\Handler\RegisterUserHandler + Prooph\ProophessorDo\Model\User\Handler\UpdateUserHandler + + + + + Prooph\ServiceBus\Plugin\InvokeStrategy\OnEventStrategy + + + Prooph\ProophessorDo\Projection\Todo\TodoProjector + Prooph\ProophessorDo\Projection\Todo\UserProjector + + + + + + + + + + + + + + + + + diff --git a/test/DependencyInjection/Fixture/config/yml/plugins.yml b/test/DependencyInjection/Fixture/config/yml/plugins.yml new file mode 100644 index 0000000..e7b0c7e --- /dev/null +++ b/test/DependencyInjection/Fixture/config/yml/plugins.yml @@ -0,0 +1,44 @@ +prooph_service_bus: + command_buses: + main_command_bus: + message_factory: 'prooph_service_bus.message_factory' + router: + type: 'prooph_service_bus.command_bus_router' + routes: + 'Prooph\ProophessorDo\Model\User\Command\RegisterUser': 'Prooph\ProophessorDo\Model\User\Handler\RegisterUserHandler' + 'Prooph\ProophessorDo\Model\User\Command\UpdateUser': 'Prooph\ProophessorDo\Model\User\Handler\UpdateUserHandler' + + # uses default values + second_command_bus: + router: + routes: + 'Prooph\ProophessorDo\Model\User\Command\RegisterUser': 'Prooph\ProophessorDo\Model\User\Handler\RegisterUserHandler' + 'Prooph\ProophessorDo\Model\User\Command\UpdateUser': 'Prooph\ProophessorDo\Model\User\Handler\UpdateUserHandler' + + event_buses: + main_event_bus: + plugins: + - 'Prooph\ServiceBus\Plugin\InvokeStrategy\OnEventStrategy' + message_factory: 'prooph_service_bus.message_factory' + router: + type: 'prooph_service_bus.event_bus_router' + routes: + 'Prooph\ProophessorDo\Model\Todo\Event\TodoWasPosted': + - 'Prooph\ProophessorDo\Projection\Todo\TodoProjector' + - 'Prooph\ProophessorDo\Projection\User\UserProjector' + +services: + 'global_plugin': + class: 'ProophTest\Bundle\ServiceBus\DependencyInjection\Fixture\Model\GlobalPlugin' + tags: + - { name: prooph_service_bus.plugin } + + 'command_type_plugin': + class: 'ProophTest\Bundle\ServiceBus\DependencyInjection\Fixture\Model\CommandTypePlugin' + tags: + - { name: prooph_service_bus.command_bus.plugin } + + 'main_command_bus_plugin': + class: 'ProophTest\Bundle\ServiceBus\DependencyInjection\Fixture\Model\MainCommandBusPlugin' + tags: + - { name: prooph_service_bus.main_command_bus.plugin }