Skip to content

Commit 91f0a5e

Browse files
authored
Merge pull request #415 from doctrine/prefered-em
better selection of entity managers
2 parents 0d029c3 + 120cca6 commit 91f0a5e

File tree

4 files changed

+161
-125
lines changed

4 files changed

+161
-125
lines changed

DependencyInjection/CompilerPass/ConfigureDependencyFactoryPass.php

Lines changed: 83 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,52 +5,115 @@
55
namespace Doctrine\Bundle\MigrationsBundle\DependencyInjection\CompilerPass;
66

77
use Doctrine\Migrations\DependencyFactory;
8+
use InvalidArgumentException;
9+
use RuntimeException;
810
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
911
use Symfony\Component\DependencyInjection\ContainerBuilder;
1012
use Symfony\Component\DependencyInjection\Reference;
1113

14+
use function array_keys;
1215
use function assert;
16+
use function count;
17+
use function implode;
18+
use function is_array;
1319
use function is_string;
1420
use function sprintf;
1521

1622
class ConfigureDependencyFactoryPass implements CompilerPassInterface
1723
{
1824
public function process(ContainerBuilder $container): void
1925
{
26+
if (! $container->has('doctrine')) {
27+
throw new RuntimeException('DoctrineMigrationsBundle requires DoctrineBundle to be enabled.');
28+
}
29+
2030
$diDefinition = $container->getDefinition('doctrine.migrations.dependency_factory');
21-
$preferredEm = $container->getParameter('doctrine.migrations.preferred_em');
22-
if ($container->has('doctrine')) {
23-
$loaderDefinition = $container->getDefinition('doctrine.migrations.registry_loader');
24-
$loaderDefinition->setArgument(0, new Reference('doctrine'));
25-
if ($preferredEm !== null) {
26-
$loaderDefinition->setArgument(1, $preferredEm);
27-
}
2831

29-
$diDefinition->setFactory([DependencyFactory::class, 'fromEntityManager']);
30-
$diDefinition->setArgument(1, new Reference('doctrine.migrations.registry_loader'));
32+
$preferredConnection = $container->getParameter('doctrine.migrations.preferred_connection');
33+
assert(is_string($preferredConnection) || $preferredConnection === null);
34+
// explicitly use configured connection
35+
if ($preferredConnection !== null) {
36+
$this->validatePreferredConnection($container, $preferredConnection);
37+
38+
$loaderDefinition = $container->getDefinition('doctrine.migrations.connection_registry_loader');
39+
$loaderDefinition->setArgument(1, $preferredConnection);
40+
41+
$diDefinition->setFactory([DependencyFactory::class, 'fromConnection']);
42+
$diDefinition->setArgument(1, new Reference('doctrine.migrations.connection_registry_loader'));
3143

3244
return;
3345
}
3446

47+
$preferredEm = $container->getParameter('doctrine.migrations.preferred_em');
3548
assert(is_string($preferredEm) || $preferredEm === null);
36-
$emID = sprintf('doctrine.orm.%s_entity_manager', $preferredEm ?? 'default');
37-
if ($container->has($emID)) {
38-
$container->getDefinition('doctrine.migrations.em_loader')
39-
->setArgument(0, new Reference($emID));
49+
// explicitly use configured entity manager
50+
if ($preferredEm !== null) {
51+
$this->validatePreferredEm($container, $preferredEm);
52+
53+
$loaderDefinition = $container->getDefinition('doctrine.migrations.entity_manager_registry_loader');
54+
$loaderDefinition->setArgument(1, $preferredEm);
4055

4156
$diDefinition->setFactory([DependencyFactory::class, 'fromEntityManager']);
42-
$diDefinition->setArgument(1, new Reference('doctrine.migrations.em_loader'));
57+
$diDefinition->setArgument(1, new Reference('doctrine.migrations.entity_manager_registry_loader'));
4358

4459
return;
4560
}
4661

47-
$preferredConnection = $container->getParameter('doctrine.migrations.preferred_connection');
48-
assert(is_string($preferredConnection) || $preferredConnection === null);
49-
$connectionId = sprintf('doctrine.dbal.%s_connection', $preferredConnection ?? 'default');
50-
$container->getDefinition('doctrine.migrations.connection_loader')
51-
->setArgument(0, new Reference($connectionId));
62+
// try to use any/default entity manager
63+
if (
64+
$container->hasParameter('doctrine.entity_managers')
65+
&& is_array($container->getParameter('doctrine.entity_managers'))
66+
&& count($container->getParameter('doctrine.entity_managers')) > 0
67+
) {
68+
$diDefinition->setFactory([DependencyFactory::class, 'fromEntityManager']);
69+
$diDefinition->setArgument(1, new Reference('doctrine.migrations.entity_manager_registry_loader'));
70+
71+
return;
72+
}
5273

74+
// fallback on any/default connection
5375
$diDefinition->setFactory([DependencyFactory::class, 'fromConnection']);
54-
$diDefinition->setArgument(1, new Reference('doctrine.migrations.connection_loader'));
76+
$diDefinition->setArgument(1, new Reference('doctrine.migrations.connection_registry_loader'));
77+
}
78+
79+
private function validatePreferredConnection(ContainerBuilder $container, string $preferredConnection): void
80+
{
81+
/**
82+
* @var array<string, string> $allowedConnections
83+
*/
84+
$allowedConnections = $container->getParameter('doctrine.connections');
85+
if (! isset($allowedConnections[$preferredConnection])) {
86+
throw new InvalidArgumentException(sprintf(
87+
'The "%s" connection is not defined. Did you mean one of the following: %s',
88+
$preferredConnection,
89+
implode(', ', array_keys($allowedConnections))
90+
));
91+
}
92+
}
93+
94+
private function validatePreferredEm(ContainerBuilder $container, string $preferredEm): void
95+
{
96+
if (
97+
! $container->hasParameter('doctrine.entity_managers')
98+
|| ! is_array($container->getParameter('doctrine.entity_managers'))
99+
|| count($container->getParameter('doctrine.entity_managers')) === 0
100+
) {
101+
throw new InvalidArgumentException(sprintf(
102+
'The "%s" entity manager is not defined. It seems that you do not have configured any entity manager in the DoctrineBundle.',
103+
$preferredEm
104+
));
105+
}
106+
107+
/**
108+
* @var array<string, string> $allowedEms
109+
*/
110+
$allowedEms = $container->getParameter('doctrine.entity_managers');
111+
if (! isset($allowedEms[$preferredEm])) {
112+
throw new InvalidArgumentException(sprintf(
113+
'The "%s" entity manager is not defined. Did you mean one of the following: %s',
114+
$preferredEm,
115+
implode(', ', array_keys($allowedEms))
116+
));
117+
}
55118
}
56119
}

Resources/config/services.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,16 @@
2525

2626
</service>
2727

28-
<service id="doctrine.migrations.registry_loader" class="Doctrine\Migrations\Configuration\EntityManager\ManagerRegistryEntityManager" public="false">
28+
<service id="doctrine.migrations.entity_manager_registry_loader" class="Doctrine\Migrations\Configuration\EntityManager\ManagerRegistryEntityManager" public="false">
2929
<factory class="Doctrine\Migrations\Configuration\EntityManager\ManagerRegistryEntityManager" method="withSimpleDefault"/>
3030
<argument type="service" id="doctrine"/>
3131
</service>
3232

33+
<service id="doctrine.migrations.connection_registry_loader" class="Doctrine\Migrations\Configuration\Connection\ConnectionRegistryConnection" public="false">
34+
<factory class="Doctrine\Migrations\Configuration\Connection\ConnectionRegistryConnection" method="withSimpleDefault"/>
35+
<argument type="service" id="doctrine"/>
36+
</service>
37+
3338
<service id="doctrine.migrations.configuration" class="Doctrine\Migrations\Configuration\Configuration" public="false">
3439
</service>
3540

Tests/DependencyInjection/DoctrineCommandsTest.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Doctrine\Bundle\MigrationsBundle\Tests\DependencyInjection;
66

7+
use Doctrine\Bundle\DoctrineBundle\DependencyInjection\DoctrineExtension;
78
use Doctrine\Bundle\MigrationsBundle\DependencyInjection\CompilerPass\ConfigureDependencyFactoryPass;
89
use Doctrine\Bundle\MigrationsBundle\DependencyInjection\DoctrineMigrationsExtension;
910
use Doctrine\Migrations\Tools\Console\Command\CurrentCommand;
@@ -20,7 +21,6 @@
2021
use Doctrine\Migrations\Tools\Console\Command\SyncMetadataCommand;
2122
use Doctrine\Migrations\Tools\Console\Command\UpToDateCommand;
2223
use Doctrine\Migrations\Tools\Console\Command\VersionCommand;
23-
use Doctrine\ORM\EntityManager;
2424
use PHPUnit\Framework\MockObject\MockObject;
2525
use PHPUnit\Framework\TestCase;
2626
use Symfony\Bundle\FrameworkBundle\Console\Application;
@@ -95,17 +95,23 @@ private function getApplication(): Application
9595
'kernel.cache_dir' => sys_get_temp_dir(),
9696
'kernel.environment' => 'test',
9797
'kernel.project_dir' => __DIR__ . '/../',
98+
'kernel.root_dir' => __DIR__ ,
9899
]));
99100

100101
$kernel = $this->getKernel($container);
101102
$application = new Application($kernel);
102103
$container->set('application', $application);
103104

104-
$em = $this->createMock(EntityManager::class);
105-
$container->set('doctrine.orm.default_entity_manager', $em);
106-
107105
$container->addCompilerPass(new AddConsoleCommandPass());
108106

107+
$extension = new DoctrineExtension();
108+
$extension->load([
109+
'doctrine' => [
110+
'dbal' => ['url' => 'sqlite:///:memory:'],
111+
'orm' => null,
112+
],
113+
], $container);
114+
109115
$extension = new DoctrineMigrationsExtension();
110116
$extension->load([
111117
'doctrine_migrations' => [

0 commit comments

Comments
 (0)