From 01695bc654a8c1c8c997c87330b4c6481ea17e69 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 27 Apr 2011 23:03:29 +0200 Subject: [PATCH] [DoctrineBundle] refactored event listeners/subscribers to not rely on parameter name conventions * Doctrine event subscribers now all use the same "doctrine.event_subscriber" tag. To specify a connection, use the "connection" attribute. * Doctrine event listeners now all use the same "doctrine.event_listener" tag. To specify a connection, use the "connection" attribute. --- UPDATE.md | 30 +++++ ...gisterEventListenersAndSubscribersPass.php | 112 +++++++++++------- .../DependencyInjection/DoctrineExtension.php | 2 +- 3 files changed, 102 insertions(+), 42 deletions(-) diff --git a/UPDATE.md b/UPDATE.md index 35992ba7a1..f8833ea007 100644 --- a/UPDATE.md +++ b/UPDATE.md @@ -9,6 +9,36 @@ timeline closely anyway. beta1 to beta2 -------------- +* Doctrine event subscribers now use a unique "doctrine.event_subscriber" tag. + Doctrine event listeners also use a unique "doctrine.event_listener" tag. To + specify a connection, use the optional "connection" attribute. + + Before: + + listener: + class: MyEventListener + tags: + - { name: doctrine.common.event_listener, event: name } + - { name: doctrine.dbal.default_event_listener, event: name } + subscriber: + class: MyEventSubscriber + tags: + - { name: doctrine.common.event_subscriber } + - { name: doctrine.dbal.default_event_subscriber } + + After: + + listener: + class: MyEventListener + tags: + - { name: doctrine.event_listener, event: name } # register for all connections + - { name: doctrine.event_listener, event: name, connection: default } # only for the default connection + subscriber: + class: MyEventSubscriber + tags: + - { name: doctrine.event_subscriber } # register for all connections + - { name: doctrine.event_subscriber, connection: default } # only for the default connection + * The `doctrine.orm.entity_managers` is now hash of entity manager names/ids pairs: Before: array('default', 'foo') diff --git a/src/Symfony/Bundle/DoctrineBundle/DependencyInjection/Compiler/RegisterEventListenersAndSubscribersPass.php b/src/Symfony/Bundle/DoctrineBundle/DependencyInjection/Compiler/RegisterEventListenersAndSubscribersPass.php index 52a497e2a1..7c9aba5ea2 100644 --- a/src/Symfony/Bundle/DoctrineBundle/DependencyInjection/Compiler/RegisterEventListenersAndSubscribersPass.php +++ b/src/Symfony/Bundle/DoctrineBundle/DependencyInjection/Compiler/RegisterEventListenersAndSubscribersPass.php @@ -9,55 +9,85 @@ use Symfony\Component\DependencyInjection\DefinitionDecorator; class RegisterEventListenersAndSubscribersPass implements CompilerPassInterface { - protected $container; + private $container; + private $connections; + private $eventManagers; public function process(ContainerBuilder $container) { $this->container = $container; - foreach ($container->getDefinitions() as $id => $definition) { - if (!$definition instanceof DefinitionDecorator || 'doctrine.dbal.connection.event_manager' !== $definition->getParent()) { - continue; + $this->connections = $container->getParameter('doctrine.dbal.connections'); + + foreach ($container->findTaggedServiceIds('doctrine.event_subscriber') as $subscriberId => $instances) { + $this->registerSubscriber($subscriberId, $instances); + } + + foreach ($container->findTaggedServiceIds('doctrine.event_listener') as $listenerId => $instances) { + $this->registerListener($listenerId, $instances); + } + } + + protected function registerSubscriber($subscriberId, $instances) + { + $connections = array(); + foreach ($instances as $attributes) { + if (isset($attributes['connection'])) { + $connections[] = $attributes['connection']; + } else { + $connections = array_keys($this->connections); + break; + } + } + + foreach ($connections as $name) { + $this->getEventManager($name)->addMethodCall('addEventSubscriber', array(new Reference($subscriberId))); + } + } + + protected function registerListener($listenerId, $instances) + { + $connections = array(); + foreach ($instances as $attributes) { + if (!isset($attributes['event'])) { + throw new \InvalidArgumentException(sprintf('Doctrine event listener "%s" must specify the "event" attribute.', $listenerId)); } - $prefix = substr($id, 0, -strlen('_connection.event_manager')); - $this->registerListeners($prefix, $definition); - $this->registerSubscribers($prefix, $definition); - } - } + if (isset($attributes['connection'])) { + $cs = array($attributes['connection']); + } else { + $cs = array_keys($this->connections); + } - protected function registerSubscribers($prefix, $definition) - { - $subscribers = array_merge( - $this->container->findTaggedServiceIds('doctrine.common.event_subscriber'), - $this->container->findTaggedServiceIds($prefix.'_event_subscriber') - ); - - foreach ($subscribers as $id => $instances) { - $definition->addMethodCall('addEventSubscriber', array(new Reference($id))); - } - } - - protected function registerListeners($prefix, $definition) - { - $listeners = array_merge( - $this->container->findTaggedServiceIds('doctrine.common.event_listener'), - $this->container->findTaggedServiceIds($prefix.'_event_listener') - ); - - foreach ($listeners as $listenerId => $instances) { - $events = array(); - foreach ($instances as $attributes) { - if (isset($attributes['event'])) { - $events[] = $attributes['event']; + foreach ($cs as $connection) { + if (!is_array($connections[$connection])) { + $connections[$connection] = array(); } - } - - if (0 < count($events)) { - $definition->addMethodCall('addEventListener', array( - $events, - new Reference($listenerId), - )); + $connections[$connection][] = $attributes['event']; } } + + foreach ($connections as $name => $events) { + $this->getEventManager($name)->addMethodCall('addEventListener', array( + array_unique($events), + new Reference($listenerId), + )); + } } -} \ No newline at end of file + + private function getEventManager($name) + { + if (null === $this->eventManagers) { + $this->eventManagers = array(); + foreach ($this->connections as $n => $id) { + $arguments = $this->container->getDefinition($id)->getArguments(); + $this->eventManagers[$n] = $this->container->getDefinition((string) $arguments[2]); + } + } + + if (!isset($this->eventManagers[$name])) { + throw new \InvalidArgumentException(sprintf('Doctrine connection "%s" does not exist but is referenced in the "%s" event listener.', $name, $listenerId)); + } + + return $this->eventManagers[$name]; + } +} diff --git a/src/Symfony/Bundle/DoctrineBundle/DependencyInjection/DoctrineExtension.php b/src/Symfony/Bundle/DoctrineBundle/DependencyInjection/DoctrineExtension.php index 930cb078d4..5a6d97efd7 100755 --- a/src/Symfony/Bundle/DoctrineBundle/DependencyInjection/DoctrineExtension.php +++ b/src/Symfony/Bundle/DoctrineBundle/DependencyInjection/DoctrineExtension.php @@ -108,7 +108,7 @@ class DoctrineExtension extends AbstractDoctrineExtension $mysqlSessionInit = new Definition('%doctrine.dbal.events.mysql_session_init.class%'); $mysqlSessionInit->setArguments(array($connection['charset'])); $mysqlSessionInit->setPublic(false); - $mysqlSessionInit->addTag(sprintf('doctrine.dbal.%s_event_subscriber', $name)); + $mysqlSessionInit->addTag('doctrine.event_subscriber', array('connection' => $name)); $container->setDefinition( sprintf('doctrine.dbal.%s_connection.events.mysqlsessioninit', $name),