Skip to content

Commit

Permalink
Added some tests, fixed a bug when using multiple EMs, and bumped PHP…
Browse files Browse the repository at this point in the history
…Unit to ~4.5.
  • Loading branch information
magnusnordlander committed Jun 1, 2017
1 parent 165ca8a commit fab0609
Show file tree
Hide file tree
Showing 3 changed files with 191 additions and 31 deletions.
59 changes: 29 additions & 30 deletions DependencyInjection/Compiler/RepositoryAliasPass.php
Expand Up @@ -46,46 +46,45 @@ public function process(ContainerBuilder $container)
];
}
}
}

$rootConflicts = [];
foreach ($customRepositories as $repositoryClass => $entities) {
$repoConflicts = $this->findConflictingServices($container, $repositoryClass);
$rootConflicts = [];
foreach ($customRepositories as $repositoryClass => $entities) {
$repoConflicts = $this->findConflictingServices($container, $repositoryClass);

if (count($repoConflicts)) {
$rootConflicts[$repositoryClass] = $repoConflicts;
}
if (count($repoConflicts)) {
$rootConflicts[$repositoryClass] = $repoConflicts;
}
}

foreach ($customRepositories as $repositoryClass => $entities) {
if ($container->has($repositoryClass)) {
continue;
}
foreach ($customRepositories as $repositoryClass => $entities) {
if ($container->has($repositoryClass)) {
continue;
}

if (count($entities) !== 1) {
$this->log($container, "Cannot auto-register repository \"".$repositoryClass."\": Entity belongs to multiple entity managers.");
continue;
}
if (count($entities) !== 1) {
$this->log($container, "Cannot auto-register repository \"".$repositoryClass."\": Entity belongs to multiple entity managers.");
continue;
}

if (isset($rootConflicts[$repositoryClass])) {
$this->log($container, "Cannot auto-register repository \"".$repositoryClass."\": There are already services for the repository class.");
continue;
}
if (isset($rootConflicts[$repositoryClass])) {
$this->log($container, "Cannot auto-register repository \"".$repositoryClass."\": There are already services for the repository class.");
continue;
}

foreach ($rootConflicts as $conflictingRepo => $conflicts) {
if (is_subclass_of($repositoryClass, $conflictingRepo, true)) {
$this->log($container, "Cannot auto-register repository \"".$repositoryClass."\": There are already services for a superclass of the repository class.");
continue 2;
}
}
$definition = $container->register($repositoryClass, $repositoryClass)
->setFactory([new Reference('doctrine'), 'getRepository'])
->setArguments($entities[0])
->setPublic(false)
;

$container->register($repositoryClass, $repositoryClass)
->setFactory([new Reference('doctrine'), 'getRepository'])
->setArguments($entities[0])
->setShared(false)
->setPublic(false)
;
if (Kernel::MAJOR_VERSION <= 2 && Kernel::MINOR_VERSION <= 7) {
$definition->setScope('prototype');
} else {
$definition->setShared(true);
}
}

}

private function findConflictingServices(ContainerBuilder $container, $repositoryClass)
Expand Down
161 changes: 161 additions & 0 deletions Tests/DependencyInjection/AutoregisterRepositoriesTest.php
@@ -0,0 +1,161 @@
<?php

namespace Doctrine\Bundle\DoctrineBundle\Tests\DependencyInjection;


use Prophecy\Argument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\RepositoryAliasPass;
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\HttpKernel\Kernel;


class AutoregisterRepositoriesTest extends \PHPUnit_Framework_TestCase
{
public function testSingleEmNoRegisteredRepositories()
{
$containerBuilder = $this->prophesize(ContainerBuilder::class);
$metadataDriver = $this->prophesize(MappingDriver::class);
$parameterBag = $this->prophesize(ParameterBag::class);
$definition = $this->prophesize(Definition::class);

$this->prepPropheciesForOneEmAndClassA($containerBuilder, $metadataDriver, $parameterBag);

$containerBuilder->getDefinitions()->willReturn([]);
$containerBuilder->has(ClassARepository::class)->willReturn(false);
$containerBuilder->register(ClassARepository::class, ClassARepository::class)->shouldBeCalled()->willReturn($definition);
$definition->setFactory(Argument::any())->shouldBeCalled()->willReturn($definition);
$definition->setArguments(['ClassA', 'default'])->shouldBeCalled()->willReturn($definition);
$definition->setPublic(false)->shouldBeCalled()->willReturn($definition);

if (method_exists(Definition::class, 'setShared')) {
$definition->setShared(false)->shouldBeCalled()->willReturn($definition);
} else {
$definition->setScope('prototype')->shouldBeCalled()->willReturn($definition);
}


$pass = new RepositoryAliasPass();
$pass->process($containerBuilder->reveal());
}

public function testSingleEmRepoAlreadyRegisteredWithClassName()
{
$containerBuilder = $this->prophesize(ContainerBuilder::class);
$metadataDriver = $this->prophesize(MappingDriver::class);
$parameterBag = $this->prophesize(ParameterBag::class);

$this->prepPropheciesForOneEmAndClassA($containerBuilder, $metadataDriver, $parameterBag);

$containerBuilder->getDefinitions()->willReturn([]);
$containerBuilder->has(ClassARepository::class)->willReturn(true);

$pass = new RepositoryAliasPass();
$pass->process($containerBuilder->reveal());
}

public function testSingleEmRepoAlreadyRegisteredVanillaServiceOnSymfony3()
{
if (Kernel::MAJOR_VERSION !== 3) {
$this->markTestSkipped("This test is only run with Symfony 3");
}

$pass = new RepositoryAliasPass();

$containerBuilder = $this->prophesize(ContainerBuilder::class);
$metadataDriver = $this->prophesize(MappingDriver::class);
$parameterBag = $this->prophesize(ParameterBag::class);
$previousDefinition = $this->prophesize(Definition::class);

$this->prepPropheciesForOneEmAndClassA($containerBuilder, $metadataDriver, $parameterBag);

$containerBuilder->getDefinitions()->willReturn([
'app.class_a_repo' => $previousDefinition,
]);
$previousDefinition->getClass()->willReturn(ClassARepository::class);
$containerBuilder->has(ClassARepository::class)->willReturn(false);
if (method_exists(ContainerBuilder::class, 'log')) {
$containerBuilder->log($pass, Argument::any())->shouldBeCalled();
}

$pass->process($containerBuilder->reveal());
}

public function testMultipleEms()
{
$pass = new RepositoryAliasPass();

$containerBuilder = $this->prophesize(ContainerBuilder::class);
$metadataDriver1 = $this->prophesize(MappingDriver::class);
$metadataDriver2 = $this->prophesize(MappingDriver::class);
$parameterBag = $this->prophesize(ParameterBag::class);

$containerBuilder->hasParameter('doctrine.entity_managers')->willReturn(true);
$containerBuilder->getParameter('doctrine.entity_managers')->willReturn([
'default' => 'doctrine.default',
'secondary' => 'doctrine.secondary',
]);
$containerBuilder->has('doctrine.orm.default_metadata_driver')->willReturn(true);
$containerBuilder->get('doctrine.orm.default_metadata_driver')->willReturn($metadataDriver1);
$containerBuilder->has('doctrine.orm.secondary_metadata_driver')->willReturn(true);
$containerBuilder->get('doctrine.orm.secondary_metadata_driver')->willReturn($metadataDriver1);
$containerBuilder->getParameterBag()->willReturn($parameterBag);

$parameterBag->resolveValue(Argument::any())->will(function($args) {
return $args[0];
});

$metadataDriver1->getAllClassNames()->willReturn([
'ClassA',
]);
$metadataDriver1->loadMetadataForClass('ClassA', Argument::which('getName', 'ClassA'))
->will(function($args) {
$args[1]->customRepositoryClassName = ClassARepository::class;
});

$metadataDriver2->getAllClassNames()->willReturn([
'ClassA',
]);
$metadataDriver2->loadMetadataForClass('ClassA', Argument::which('getName', 'ClassA'))
->will(function($args) {
$args[1]->customRepositoryClassName = ClassARepository::class;
});

$containerBuilder->getDefinitions()->willReturn([]);
$containerBuilder->has(ClassARepository::class)->willReturn(false);
if (method_exists(ContainerBuilder::class, 'log')) {
$containerBuilder->log($pass, Argument::any())->shouldBeCalled();
}

$pass->process($containerBuilder->reveal());
}

protected function prepPropheciesForOneEmAndClassA($containerBuilder, $metadataDriver, $parameterBag)
{
$containerBuilder->hasParameter('doctrine.entity_managers')->willReturn(true);
$containerBuilder->getParameter('doctrine.entity_managers')->willReturn([
'default' => 'doctrine.default',
]);
$containerBuilder->has('doctrine.orm.default_metadata_driver')->willReturn(true);
$containerBuilder->get('doctrine.orm.default_metadata_driver')->willReturn($metadataDriver);
$containerBuilder->getParameterBag()->willReturn($parameterBag);

$parameterBag->resolveValue(Argument::any())->will(function($args) {
return $args[0];
});

$metadataDriver->getAllClassNames()->willReturn([
'ClassA',
]);
$metadataDriver->loadMetadataForClass('ClassA', Argument::which('getName', 'ClassA'))
->will(function($args) {
$args[1]->customRepositoryClassName = ClassARepository::class;
});
}
}


class ClassAlphaRepository {}
class ClassARepository extends ClassAlphaRepository {}
2 changes: 1 addition & 1 deletion composer.json
Expand Up @@ -41,7 +41,7 @@
"symfony/phpunit-bridge": "~2.7|~3.0",
"twig/twig": "~1.12|~2.0",
"satooshi/php-coveralls": "^1.0",
"phpunit/phpunit": "~4"
"phpunit/phpunit": "~4.5"
},
"suggest": {
"symfony/web-profiler-bundle": "To use the data collector.",
Expand Down

0 comments on commit fab0609

Please sign in to comment.