Skip to content

Commit

Permalink
Merge pull request #2 from biig-io/fix/doctrine-bundle-configurator
Browse files Browse the repository at this point in the history
Add support of many entity managers
  • Loading branch information
Maxime Veber authored Feb 9, 2018
2 parents 77f35d0 + 4bd2239 commit a6ca34d
Show file tree
Hide file tree
Showing 10 changed files with 135 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
namespace Biig\Component\Domain\Tests\Symfony\DependencyInjection\CompilerPass;

use Biig\Component\Domain\Integration\Symfony\DependencyInjection\CompilerPass\InsertDispatcherInClassMetadataFactoryCompilerPass;
use Biig\Component\Domain\Integration\Symfony\DependencyInjection\EntityManagerConfigurator;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;

class InsertDispatcherInClassMetadataFactoryCompilerPassTest extends TestCase
{
Expand All @@ -17,33 +19,60 @@ public function testItIsASymfonyCompilerPass()
$this->assertInstanceOf(CompilerPassInterface::class, $pass);
}

public function testItAddsConfigurationForEntityManagers()
public function testItDecorateEntityManagersConfigurators()
{
$container = $this->prophesize(ContainerBuilder::class);
$container->getParameter('biig_domain.entity_managers')->willReturn(['hello', 'world']);
$container->getParameter('biig_domain_doctrine_domain_event_instantiator')->willReturn(true);
$configChild = $this->prophesize(ChildDefinition::class);
$configChild->getParent()->willReturn('doctrine.orm.entity_manager.abstract');
$container->getDefinitions()->willReturn([
'doctrine.orm.default_entity_manager' => $configChild->reveal()
]);

$configChild->setConfigurator(Argument::any())->shouldBeCalled();
$defHello = new Definition();
$defWorld = new Definition();

$container->register('biig_domain.hello_configurator', EntityManagerConfigurator::class)->shouldBeCalled()->willReturn($defHello);
$container->register('biig_domain.world_configurator', EntityManagerConfigurator::class)->shouldBeCalled()->willReturn($defWorld);

$compilerPass = new InsertDispatcherInClassMetadataFactoryCompilerPass();
$compilerPass->process($container->reveal());

$this->assertFalse($defHello->isPublic());
$this->assertFalse($defWorld->isPublic());

$this->assertInstanceOf(Reference::class, $defHello->getArgument(0));
$this->assertInstanceOf(Reference::class, $defWorld->getArgument(0));

$this->assertEquals((string) $defHello->getArgument(0), 'biig_domain.hello_configurator.inner');
$this->assertEquals((string) $defWorld->getArgument(0), 'biig_domain.world_configurator.inner');
$this->assertEquals((string) $defHello->getArgument(1), 'biig_domain.dispatcher');
$this->assertEquals((string) $defWorld->getArgument(1), 'biig_domain.dispatcher');
}

public function testItUseDoctrineDefaultIfNoEntityManagerProvided()
{
$container = $this->prophesize(ContainerBuilder::class);
$container->getParameter('biig_domain.entity_managers')->willReturn([]);
$container->getParameter('doctrine.default_entity_manager')->willReturn('default');
$container->getParameter('biig_domain_doctrine_domain_event_instantiator')->willReturn(true);

$configurator = new Definition();

$container->register('biig_domain.default_configurator', EntityManagerConfigurator::class)->shouldBeCalled()->willReturn($configurator);

$compilerPass = new InsertDispatcherInClassMetadataFactoryCompilerPass();
$compilerPass->process($container->reveal());

$this->assertFalse($configurator->isPublic());
$this->assertInstanceOf(Reference::class, $configurator->getArgument(0));
$this->assertEquals((string) $configurator->getArgument(0), 'biig_domain.default_configurator.inner');
$this->assertEquals((string) $configurator->getArgument(1), 'biig_domain.dispatcher');
}

public function testItDoesNotAddConfigurationForEntityManagers()
{
$container = $this->prophesize(ContainerBuilder::class);
$container->getParameter('biig_domain.entity_managers')->willReturn(['hello', 'world']);
$container->getParameter('biig_domain_doctrine_domain_event_instantiator')->willReturn(false);
$configChild = $this->prophesize(ChildDefinition::class);
$configChild->getParent()->willReturn('doctrine.orm.entity_manager.abstract');
$container->getDefinitions()->willReturn([
'doctrine.orm.default_entity_manager' => $configChild->reveal()
]);

$configChild->setConfigurator(Argument::any())->shouldNotBeCalled();
$container->register(Argument::cetera())->shouldNotBeCalled();

$compilerPass = new InsertDispatcherInClassMetadataFactoryCompilerPass();
$compilerPass->process($container->reveal());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<?php

namespace Biig\Component\Domain\Tests\Model\Instantiator\DoctrineConfig;
namespace Biig\Component\Domain\Tests\Symfony\DependencyInjection;

use Biig\Component\Domain\Event\DomainEventDispatcher;
use Biig\Component\Domain\Integration\Symfony\DependencyInjection\EntityManagerConfigurator;
use Biig\Component\Domain\Model\Instantiator\DoctrineConfig\ClassMetadataFactory;
use Biig\Component\Domain\Model\Instantiator\DoctrineConfig\EntityManagerConfigurator;
use Doctrine\Bundle\DoctrineBundle\ManagerConfigurator;
use Doctrine\ORM\EntityManager;
use PHPUnit\Framework\TestCase;

Expand All @@ -13,12 +14,13 @@ class EntityManagerConfiguratorTest extends TestCase
public function testItInsertTheDispacher()
{
$entityManager = $this->prophesize(EntityManager::class);
$dispacher = $this->prophesize(DomainEventDispatcher::class)->reveal();
$dispatcher = $this->prophesize(DomainEventDispatcher::class)->reveal();
$originalConfigurator = $this->prophesize(ManagerConfigurator::class)->reveal();
$factory = new ClassMetadataFactory();

$entityManager->getMetadataFactory()->willReturn($factory);

$configurator = new EntityManagerConfigurator($dispacher);
$configurator = new EntityManagerConfigurator($originalConfigurator, $dispatcher);
$configurator->configure($entityManager->reveal());

$ref = new \ReflectionObject($factory);
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"phpunit/phpunit": "^6.4",
"doctrine/orm": "^2.5",
"symfony/symfony": "~3.3|~4.0",
"friendsofphp/php-cs-fixer": "^2.8"
"friendsofphp/php-cs-fixer": "^2.8",
"doctrine/doctrine-bundle": "^1.8"
},
"autoload": {
"psr-4": {
Expand Down
18 changes: 17 additions & 1 deletion docs/domain_event_dispatcher.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ $dispatcher->addRule(new class implements DomainRuleInterface {

### Symfony Integration

If you use the Symfony Bundle with autoconfiguration of your services.
If you use the Symfony Bundle with auto-configuration of your services.
*You don't have anything to do.*

If you don't want to use the given interface or want more control on the
Expand All @@ -42,3 +42,19 @@ My\Domain\Rule:
```
_Notice: the priority field is optional._
#### Configuration reference
```yaml
biig_domain:
# It modifies the DoctrineBundle configuration to register a new
# ClassMetadataInfo class so the instantiator now set the domain event
# dispatcher to your models automatically
override_doctrine_instantiator: true

# By default it will override the doctrine instantiator only for
# the "default" entity manager of your application. You can specify
# many entity managers if you want.
entity_managers: []
```
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

namespace Biig\Component\Domain\Integration\Symfony\DependencyInjection\CompilerPass;

use Biig\Component\Domain\Model\Instantiator\DoctrineConfig\EntityManagerConfigurator;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Biig\Component\Domain\Integration\Symfony\DependencyInjection\EntityManagerConfigurator;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
Expand All @@ -12,17 +11,28 @@ class InsertDispatcherInClassMetadataFactoryCompilerPass implements CompilerPass
{
public function process(ContainerBuilder $container)
{
if ($container->getParameter('biig_domain_doctrine_domain_event_instantiator')) {
$definitions = $container->getDefinitions();
$entityManagers = $container->getParameter('biig_domain.entity_managers');
if (empty($entityManagers)) {
$entityManagers = [$container->getParameter('doctrine.default_entity_manager')];
}

foreach ($definitions as $name => $definition) {
if (
$definition instanceof ChildDefinition
&& 'doctrine.orm.entity_manager.abstract' === $definition->getParent()
) {
$definition->setConfigurator([new Reference(EntityManagerConfigurator::class), 'configure']);
}
if ($container->getParameter('biig_domain_doctrine_domain_event_instantiator')) {
foreach ($entityManagers as $entityManager) {
$this->addDecoratorToConfigurator($container, $entityManager);
}
}
}

private function addDecoratorToConfigurator(ContainerBuilder $container, string $entityManager)
{
$serviceName = sprintf('biig_domain.%s_configurator', $entityManager);
$originalConfiguratorName = sprintf('doctrine.orm.%s_manager_configurator', $entityManager);

$container->register($serviceName, EntityManagerConfigurator::class)
->setDecoratedService($originalConfiguratorName)
->addArgument(new Reference($serviceName . '.inner'))
->addArgument(new Reference('biig_domain.dispatcher'))
->setPublic(false)
;
}
}
3 changes: 3 additions & 0 deletions src/Integration/Symfony/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ public function getConfigTreeBuilder()
->booleanNode('override_doctrine_instantiator')
->defaultTrue()
->end()
->arrayNode('entity_managers')
->scalarPrototype()->end()
->end()
->end()
;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public function load(array $configs, ContainerBuilder $container)
$container->setParameter('biig_domain_doctrine_domain_event_instantiator', $config['override_doctrine_instantiator']);

$container->registerForAutoconfiguration(DomainRuleInterface::class)->addTag(self::DOMAIN_RULE_TAG);

$container->setParameter('biig_domain.entity_managers', $config['entity_managers']);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace Biig\Component\Domain\Integration\Symfony\DependencyInjection;

use Biig\Component\Domain\Event\DomainEventDispatcher;
use Biig\Component\Domain\Model\Instantiator\DoctrineConfig\ClassMetadataFactory;
use Doctrine\Bundle\DoctrineBundle\ManagerConfigurator;
use Doctrine\ORM\EntityManager;

/**
* @internal
*/
class EntityManagerConfigurator
{
/**
* @var ManagerConfigurator
*/
private $originalConfigurator;

/**
* @var DomainEventDispatcher
*/
private $dispatcher;

public function __construct(ManagerConfigurator $configurator, DomainEventDispatcher $dispatcher)
{
$this->originalConfigurator = $configurator;
$this->dispatcher = $dispatcher;
}

public function configure(EntityManager $entityManager)
{
$this->originalConfigurator->configure($entityManager);
$metadataFactory = $entityManager->getMetadataFactory();

if ($metadataFactory instanceof ClassMetadataFactory) {
$metadataFactory->setDispatcher($this->dispatcher);
}
}
}
6 changes: 1 addition & 5 deletions src/Integration/Symfony/Resources/config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,10 @@ services:
biig_domain.dispatcher:
class: Biig\Component\Domain\Event\DomainEventDispatcher

Biig\Component\Domain\Model\Instantiator\DoctrineConfig\EntityManagerConfigurator:
arguments:
- "@biig_domain.dispatcher"

Biig\Component\Domain\Model\Instantiator\Instantiator:
arguments:
- "@biig_domain.dispatcher"

biig_domain.instantiator.default:
alias: Biig\Component\Domain\Model\Instantiator\Instantiator
public: true
public: true

This file was deleted.

0 comments on commit a6ca34d

Please sign in to comment.