Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[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
jmikola committed Feb 27, 2012
1 parent 027379a commit 43e34f4
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 90 deletions.
67 changes: 0 additions & 67 deletions DependencyInjection/Compiler/EventManagerPass.php

This file was deleted.

23 changes: 10 additions & 13 deletions DependencyInjection/DoctrineMongoDBExtension.php
Expand Up @@ -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.
Expand Down Expand Up @@ -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%');
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions DoctrineMongoDBBundle.php
Expand Up @@ -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;
Expand All @@ -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'));
Expand Down
7 changes: 6 additions & 1 deletion Resources/config/mongodb.xml
Expand Up @@ -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>
Expand Down Expand Up @@ -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" />
Expand Down
55 changes: 48 additions & 7 deletions Tests/DependencyInjection/AbstractMongoDBExtensionTest.php
Expand Up @@ -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
{
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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'));

Expand All @@ -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());
Expand Down

8 comments on commit 43e34f4

@kusmierz
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@stof
Copy link
Member

@stof stof commented on 43e34f4 Jun 25, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@kusmierz
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@stof
Copy link
Member

@stof stof commented on 43e34f4 Jun 25, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Member

@stof stof commented on 43e34f4 Jun 25, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@kusmierz
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't use betas on production :(

@stof
Copy link
Member

@stof stof commented on 43e34f4 Jun 27, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.