Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

[DependencyInjection] Create event managers per connection (BC break)

This commit relies upon new Doctrine bridge classes in symfony/symfony#3434.

Previously, no event manager was given as a constructor argument for a Connection service, which lead to a new object being created internally. Since that event manager was not injected and wasn't registered with the service container, the compiler pass was unable to assign listeners on core doctrine-mongdb events.

This commit makes the event manager creation consistent with DoctrineBundle. Event managers now exist per connection, and document managers use the event manager of their connection.

BC break: the syntax for tags has changed. Previously, listeners were tagged as "doctrine.odm.mongodb.%s_event_listener", with the DM's configuration name as a placeholder. The "doctrine.common.event_listener" tag was also supported for global listeners. Listeners must now be tagged as "doctrine.odm.mongodb.event_listener". Tags may use a "connection" attribute to target a specific connection by name. Additionally, "priority" is also supported. This change applies to event subscribers as well.
  • Loading branch information...
commit 43e34f42afc38f838c61b7822ff40c8d1e4e1215 1 parent 027379a
@jmikola jmikola authored
View
67 DependencyInjection/Compiler/EventManagerPass.php
@@ -1,67 +0,0 @@
-<?php
-
-/*
- * This file is part of the Doctrine MongoDBBundle
- *
- * The code was originally distributed inside the Symfony framework.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- * (c) Doctrine Project
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Doctrine\Bundle\MongoDBBundle\DependencyInjection\Compiler;
-
-use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\Definition;
-use Symfony\Component\DependencyInjection\Reference;
-
-class EventManagerPass implements CompilerPassInterface
-{
- public function process(ContainerBuilder $container)
- {
- foreach ($container->findTaggedServiceIds('doctrine.odm.mongodb.event_manager') as $id => $tags) {
- // trim _event_manager suffix
- $prefix = substr($id, 0, -14);
- $evm = $container->getDefinition($id);
- $this->registerListeners($container, $prefix, $evm);
- $this->registerSubscribers($container, $prefix, $evm);
- }
- }
-
- private function registerSubscribers(ContainerBuilder $container, $prefix, Definition $evm)
- {
- $subscribers = array_replace(
- $container->findTaggedServiceIds('doctrine.common.event_subscriber'),
- $container->findTaggedServiceIds($prefix.'_event_subscriber')
- );
-
- foreach ($subscribers as $id => $tags) {
- $evm->addMethodCall('addEventSubscriber', array(new Reference($id)));
- }
- }
-
- private function registerListeners(ContainerBuilder $container, $prefix, Definition $evm)
- {
- $listeners = array_replace(
- $container->findTaggedServiceIds('doctrine.common.event_listener'),
- $container->findTaggedServiceIds($prefix.'_event_listener')
- );
-
- foreach ($listeners as $id => $tags) {
- $events = array();
- foreach ($tags as $tag) {
- if (isset($tag['event'])) {
- $events[] = $tag['event'];
- }
- }
-
- if (0 < count($events)) {
- $evm->addMethodCall('addEventListener', array($events, new Reference($id)));
- }
- }
- }
-}
View
23 DependencyInjection/DoctrineMongoDBExtension.php
@@ -19,8 +19,9 @@
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
-use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
+use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
/**
* Doctrine MongoDB ODM extension.
@@ -200,20 +201,11 @@ protected function loadDocumentManager(array $documentManager, $defaultDM, $defa
$odmConfigDef->addMethodCall($method, array($arg));
}
- // event manager
- $eventManagerName = isset($documentManager['event_manager']) ? $documentManager['event_manager'] : $documentManager['name'];
- $eventManagerId = sprintf('doctrine.odm.mongodb.%s_event_manager', $eventManagerName);
- if (!$container->hasDefinition($eventManagerId)) {
- $eventManagerDef = new Definition('%doctrine.odm.mongodb.event_manager.class%');
- $eventManagerDef->addTag('doctrine.odm.mongodb.event_manager');
- $eventManagerDef->setPublic(false);
- $container->setDefinition($eventManagerId, $eventManagerDef);
- }
-
$odmDmArgs = array(
new Reference(sprintf('doctrine.odm.mongodb.%s_connection', isset($documentManager['connection']) ? $documentManager['connection'] : $documentManager['name'])),
new Reference(sprintf('doctrine.odm.mongodb.%s_configuration', $documentManager['name'])),
- new Reference($eventManagerId),
+ // Document managers will share their connection's event manager
+ new Reference(sprintf('doctrine.odm.mongodb.%s_connection.event_manager', $defaultDatabase)),
);
$odmDmDef = new Definition('%doctrine.odm.mongodb.document_manager.class%', $odmDmArgs);
$odmDmDef->setFactoryClass('%doctrine.odm.mongodb.document_manager.class%');
@@ -272,10 +264,15 @@ protected function loadConnections(array $connections, ContainerBuilder $contain
{
$cons = array();
foreach ($connections as $name => $connection) {
+ // Define an event manager for this connection
+ $eventManagerId = sprintf('doctrine.odm.mongodb.%s_connection.event_manager', $name);
+ $container->setDefinition($eventManagerId, new DefinitionDecorator('doctrine.odm.mongodb.connection.event_manager'));
+
$odmConnArgs = array(
isset($connection['server']) ? $connection['server'] : null,
isset($connection['options']) ? $connection['options'] : array(),
- new Reference(sprintf('doctrine.odm.mongodb.%s_configuration', $name))
+ new Reference(sprintf('doctrine.odm.mongodb.%s_configuration', $name)),
+ new Reference($eventManagerId),
);
$odmConnDef = new Definition('%doctrine.odm.mongodb.connection.class%', $odmConnArgs);
$id = sprintf('doctrine.odm.mongodb.%s_connection', $name);
View
4 DoctrineMongoDBBundle.php
@@ -16,9 +16,9 @@
use Doctrine\Bundle\MongoDBBundle\DependencyInjection\Compiler\CreateHydratorDirectoryPass;
use Doctrine\Bundle\MongoDBBundle\DependencyInjection\Compiler\CreateProxyDirectoryPass;
-use Doctrine\Bundle\MongoDBBundle\DependencyInjection\Compiler\EventManagerPass;
use Doctrine\Bundle\MongoDBBundle\DependencyInjection\DoctrineMongoDBExtension;
use Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass\DoctrineValidationPass;
+use Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass\RegisterEventListenersAndSubscribersPass;
use Symfony\Bridge\Doctrine\DependencyInjection\Security\UserProvider\EntityFactory;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -35,7 +35,7 @@ class DoctrineMongoDBBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
- $container->addCompilerPass(new EventManagerPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION);
+ $container->addCompilerPass(new RegisterEventListenersAndSubscribersPass('doctrine.odm.mongodb.connections', 'doctrine.odm.mongodb.%s_connection.event_manager', 'doctrine.odm.mongodb'), PassConfig::TYPE_BEFORE_OPTIMIZATION);
$container->addCompilerPass(new CreateProxyDirectoryPass(), PassConfig::TYPE_BEFORE_REMOVING);
$container->addCompilerPass(new CreateHydratorDirectoryPass(), PassConfig::TYPE_BEFORE_REMOVING);
$container->addCompilerPass(new DoctrineValidationPass('mongodb'));
View
7 Resources/config/mongodb.xml
@@ -13,7 +13,7 @@
<parameter key="doctrine.odm.mongodb.logger.aggregate.class">Doctrine\Bundle\MongoDBBundle\Logger\AggregateLogger</parameter>
<parameter key="doctrine.odm.mongodb.data_collector.standard.class">Doctrine\Bundle\MongoDBBundle\DataCollector\StandardDataCollector</parameter>
<parameter key="doctrine.odm.mongodb.data_collector.pretty.class">Doctrine\Bundle\MongoDBBundle\DataCollector\PrettyDataCollector</parameter>
- <parameter key="doctrine.odm.mongodb.event_manager.class">Doctrine\Common\EventManager</parameter>
+ <parameter key="doctrine.odm.mongodb.event_manager.class">Symfony\Bridge\Doctrine\ContainerAwareEventManager</parameter>
<parameter key="doctrine_odm.mongodb.validator_initializer.class">Symfony\Bridge\Doctrine\Validator\DoctrineInitializer</parameter>
<parameter key="doctrine_odm.mongodb.validator.unique.class">Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntityValidator</parameter>
<parameter key="doctrine.odm.mongodb.class">Doctrine\Bundle\MongoDBBundle\ManagerRegistry</parameter>
@@ -60,6 +60,11 @@
<!-- defaults -->
<service id="doctrine.odm.mongodb.cache" alias="doctrine.odm.mongodb.cache.array" />
+ <!-- events -->
+ <service id="doctrine.odm.mongodb.connection.event_manager" class="%doctrine.odm.mongodb.event_manager.class%" public="false" abstract="true">
+ <argument type="service" id="service_container" />
+ </service>
+
<!-- form -->
<service id="form.type.mongodb_document" class="Doctrine\Bundle\MongoDBBundle\Form\Type\DocumentType">
<tag name="form.type" alias="document" />
View
55 Tests/DependencyInjection/AbstractMongoDBExtensionTest.php
@@ -19,7 +19,6 @@
use Doctrine\Bundle\MongoDBBundle\Tests\TestCase;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
-use Symfony\Component\DependencyInjection\Reference;
abstract class AbstractMongoDBExtensionTest extends TestCase
{
@@ -64,7 +63,14 @@ public function testDependencyInjectionConfigurationDefaults()
$definition = $container->getDefinition('doctrine.odm.mongodb.default_connection');
$this->assertEquals('%doctrine.odm.mongodb.connection.class%', $definition->getClass());
- $this->assertEquals(array(null, array(), new Reference('doctrine.odm.mongodb.default_configuration')), $definition->getArguments());
+
+ $arguments = $definition->getArguments();
+ $this->assertEquals(null, $arguments[0]);
+ $this->assertEquals(array(), $arguments[1]);
+ $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $arguments[2]);
+ $this->assertEquals('doctrine.odm.mongodb.default_configuration', (string) $arguments[2]);
+ $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $arguments[3]);
+ $this->assertEquals('doctrine.odm.mongodb.default_connection.event_manager', (string) $arguments[3]);
$definition = $container->getDefinition('doctrine.odm.mongodb.default_document_manager');
$this->assertEquals('%doctrine.odm.mongodb.document_manager.class%', $definition->getClass());
@@ -97,7 +103,14 @@ public function testSingleDocumentManagerConfiguration()
$definition = $container->getDefinition('doctrine.odm.mongodb.default_connection');
$this->assertEquals('%doctrine.odm.mongodb.connection.class%', $definition->getClass());
- $this->assertEquals(array('mongodb://localhost:27017', array('connect' => true), new Reference('doctrine.odm.mongodb.default_configuration')), $definition->getArguments());
+
+ $arguments = $definition->getArguments();
+ $this->assertEquals('mongodb://localhost:27017', $arguments[0]);
+ $this->assertEquals(array('connect' => true), $arguments[1]);
+ $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $arguments[2]);
+ $this->assertEquals('doctrine.odm.mongodb.default_configuration', (string) $arguments[2]);
+ $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $arguments[3]);
+ $this->assertEquals('doctrine.odm.mongodb.default_connection.event_manager', (string) $arguments[3]);
$definition = $container->getDefinition('doctrine.odm.mongodb.default_document_manager');
$this->assertEquals('%doctrine.odm.mongodb.document_manager.class%', $definition->getClass());
@@ -126,7 +139,14 @@ public function testLoadSimpleSingleConnection()
$definition = $container->getDefinition('doctrine.odm.mongodb.default_connection');
$this->assertEquals('%doctrine.odm.mongodb.connection.class%', $definition->getClass());
- $this->assertEquals(array('mongodb://localhost:27017', array('connect' => true), new Reference('doctrine.odm.mongodb.default_configuration')), $definition->getArguments());
+
+ $arguments = $definition->getArguments();
+ $this->assertEquals('mongodb://localhost:27017', $arguments[0]);
+ $this->assertEquals(array('connect' => true), $arguments[1]);
+ $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $arguments[2]);
+ $this->assertEquals('doctrine.odm.mongodb.default_configuration', (string) $arguments[2]);
+ $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $arguments[3]);
+ $this->assertEquals('doctrine.odm.mongodb.default_connection.event_manager', (string) $arguments[3]);
$definition = $container->getDefinition('doctrine.odm.mongodb.default_configuration');
$methodCalls = $definition->getMethodCalls();
@@ -161,7 +181,14 @@ public function testLoadSingleConnection()
$definition = $container->getDefinition('doctrine.odm.mongodb.default_connection');
$this->assertEquals('%doctrine.odm.mongodb.connection.class%', $definition->getClass());
- $this->assertEquals(array('mongodb://localhost:27017', array('connect' => true), new Reference('doctrine.odm.mongodb.default_configuration')), $definition->getArguments());
+
+ $arguments = $definition->getArguments();
+ $this->assertEquals('mongodb://localhost:27017', $arguments[0]);
+ $this->assertEquals(array('connect' => true), $arguments[1]);
+ $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $arguments[2]);
+ $this->assertEquals('doctrine.odm.mongodb.default_configuration', (string) $arguments[2]);
+ $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $arguments[3]);
+ $this->assertEquals('doctrine.odm.mongodb.default_connection.event_manager', (string) $arguments[3]);
$definition = $container->getDefinition('doctrine.odm.mongodb.default_document_manager');
$this->assertEquals('%doctrine.odm.mongodb.document_manager.class%', $definition->getClass());
@@ -190,7 +217,14 @@ public function testLoadMultipleConnections()
$definition = $container->getDefinition('doctrine.odm.mongodb.conn1_connection');
$this->assertEquals('%doctrine.odm.mongodb.connection.class%', $definition->getClass());
- $this->assertEquals(array('mongodb://localhost:27017', array('connect' => true), new Reference('doctrine.odm.mongodb.conn1_configuration')), $definition->getArguments());
+
+ $arguments = $definition->getArguments();
+ $this->assertEquals('mongodb://localhost:27017', $arguments[0]);
+ $this->assertEquals(array('connect' => true), $arguments[1]);
+ $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $arguments[2]);
+ $this->assertEquals('doctrine.odm.mongodb.conn1_configuration', (string) $arguments[2]);
+ $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $arguments[3]);
+ $this->assertEquals('doctrine.odm.mongodb.conn1_connection.event_manager', (string) $arguments[3]);
$this->assertEquals('doctrine.odm.mongodb.dm2_document_manager', (string) $container->getAlias('doctrine.odm.mongodb.document_manager'));
@@ -208,7 +242,14 @@ public function testLoadMultipleConnections()
$definition = $container->getDefinition('doctrine.odm.mongodb.conn2_connection');
$this->assertEquals('%doctrine.odm.mongodb.connection.class%', $definition->getClass());
- $this->assertEquals(array('mongodb://localhost:27017', array('connect' => true), new Reference('doctrine.odm.mongodb.conn2_configuration')), $definition->getArguments());
+
+ $arguments = $definition->getArguments();
+ $this->assertEquals('mongodb://localhost:27017', $arguments[0]);
+ $this->assertEquals(array('connect' => true), $arguments[1]);
+ $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $arguments[2]);
+ $this->assertEquals('doctrine.odm.mongodb.conn2_configuration', (string) $arguments[2]);
+ $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $arguments[3]);
+ $this->assertEquals('doctrine.odm.mongodb.conn2_connection.event_manager', (string) $arguments[3]);
$definition = $container->getDefinition('doctrine.odm.mongodb.dm2_document_manager');
$this->assertEquals('%doctrine.odm.mongodb.document_manager.class%', $definition->getClass());

8 comments on commit 43e34f4

@kusmierz

#112 is it possible to apply this patch to 2.0 branch too?

@stof
Collaborator

no it is not. Read the commit message: it relies on the new classes introduced in symfony 2.1

@kusmierz

So no hope for using Connection's events on 2.0?

@stof
Collaborator

not without a refactoring targeting only the 2.0 branch, which is unlikely. Refactoring generally don't occurs in maintenance branches, and as 2.1 is already in beta now, I don't think it is worth doing such a refactoring (which would impact users using the 2.0 branch in their projects)

@jmikola
Owner

Stof is correct. If you do need Connection events, I'd suggest back-porting the functionality in your own fork. Doing so in the 2.0 branch of this bundle would involve a bit of redundancy, since the bridge classes aren't available.

@stof
Collaborator

my own recommendation would be to upgrade to 2.1 beta :)

@kusmierz

I can't use betas on production :(

@stof
Collaborator

@kusmierz I know some companies using 2.1-dev since months even it was not even beta :)

And the MongoDB ODM is only alpha, so you are not using only stable tools.

Please sign in to comment.
Something went wrong with that request. Please try again.