testAnnotationsBundleMappingDetectionWithVendorNamespace()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 24
rs 9.536
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Doctrine\Bundle\DoctrineBundle\Tests\DependencyInjection;
4
5
use Doctrine\Bundle\DoctrineBundle\DependencyInjection\DoctrineExtension;
6
use Doctrine\Bundle\DoctrineBundle\Tests\Builder\BundleConfigurationBuilder;
7
use Doctrine\DBAL\Connection;
8
use Doctrine\DBAL\Driver\Connection as DriverConnection;
9
use Doctrine\ORM\EntityManagerInterface;
10
use InvalidArgumentException;
11
use PHPUnit\Framework\TestCase;
12
use Symfony\Bridge\Doctrine\Messenger\DoctrineClearEntityManagerWorkerSubscriber;
13
use Symfony\Component\Cache\Adapter\ArrayAdapter;
14
use Symfony\Component\Cache\DoctrineProvider;
15
use Symfony\Component\DependencyInjection\Compiler\ResolveChildDefinitionsPass;
16
use Symfony\Component\DependencyInjection\ContainerBuilder;
17
use Symfony\Component\DependencyInjection\Definition;
18
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
19
use Symfony\Component\DependencyInjection\Reference;
20
use Symfony\Component\Messenger\MessageBusInterface;
21
22
class DoctrineExtensionTest extends TestCase
23
{
24
    /**
25
     * https://github.com/doctrine/orm/pull/7953 needed, otherwise ORM classes we define services for trigger deprecations
26
     *
27
     * @group legacy
28
     */
29
    public function testAutowiringAlias() : void
30
    {
31
        $container = $this->getContainer();
32
        $extension = new DoctrineExtension();
33
        $config    = BundleConfigurationBuilder::createBuilderWithBaseValues()->build();
34
35
        $extension->load([$config], $container);
36
37
        $expectedAliases = [
38
            DriverConnection::class => 'database_connection',
39
            Connection::class => 'database_connection',
40
            EntityManagerInterface::class => 'doctrine.orm.entity_manager',
41
        ];
42
43
        foreach ($expectedAliases as $id => $target) {
44
            $this->assertTrue($container->hasAlias($id), sprintf('The container should have a `%s` alias for autowiring support.', $id));
45
46
            $alias = $container->getAlias($id);
47
            $this->assertEquals($target, (string) $alias, sprintf('The autowiring for `%s` should use `%s`.', $id, $target));
48
            $this->assertFalse($alias->isPublic(), sprintf('The autowiring alias for `%s` should be private.', $id, $target));
49
        }
50
    }
51
52
    public function testPublicServicesAndAliases() : void
53
    {
54
        $container = $this->getContainer();
55
        $extension = new DoctrineExtension();
56
        $config    = BundleConfigurationBuilder::createBuilderWithBaseValues()->build();
57
58
        $extension->load([$config], $container);
59
60
        $this->assertTrue($container->getDefinition('doctrine')->isPublic());
61
        $this->assertTrue($container->getAlias('doctrine.orm.entity_manager')->isPublic());
62
        $this->assertTrue($container->getAlias('database_connection')->isPublic());
63
    }
64
65
    public function testDbalGenerateDefaultConnectionConfiguration() : void
66
    {
67
        $container = $this->getContainer();
68
        $extension = new DoctrineExtension();
69
70
        $container->registerExtension($extension);
71
72
        $extension->load([['dbal' => []]], $container);
73
74
        // doctrine.dbal.default_connection
75
        $this->assertEquals('%doctrine.default_connection%', $container->getDefinition('doctrine')->getArgument(3));
76
        $this->assertEquals('default', $container->getParameter('doctrine.default_connection'));
77
        $this->assertEquals('root', $container->getDefinition('doctrine.dbal.default_connection')->getArgument(0)['user']);
78
        $this->assertNull($container->getDefinition('doctrine.dbal.default_connection')->getArgument(0)['password']);
79
        $this->assertEquals('localhost', $container->getDefinition('doctrine.dbal.default_connection')->getArgument(0)['host']);
80
        $this->assertNull($container->getDefinition('doctrine.dbal.default_connection')->getArgument(0)['port']);
81
        $this->assertEquals('pdo_mysql', $container->getDefinition('doctrine.dbal.default_connection')->getArgument(0)['driver']);
82
        $this->assertEquals([], $container->getDefinition('doctrine.dbal.default_connection')->getArgument(0)['driverOptions']);
83
    }
84
85
    public function testDbalOverrideDefaultConnection() : void
86
    {
87
        $container = $this->getContainer();
88
        $extension = new DoctrineExtension();
89
90
        $container->registerExtension($extension);
91
92
        $extension->load([[], ['dbal' => ['default_connection' => 'foo']], []], $container);
93
94
        // doctrine.dbal.default_connection
95
        $this->assertEquals('%doctrine.default_connection%', $container->getDefinition('doctrine')->getArgument(3), '->load() overrides existing configuration options');
96
        $this->assertEquals('foo', $container->getParameter('doctrine.default_connection'), '->load() overrides existing configuration options');
97
    }
98
99
    /**
100
     * @expectedException \LogicException
101
     * @expectedExceptionMessage Configuring the ORM layer requires to configure the DBAL layer as well.
102
     */
103
    public function testOrmRequiresDbal() : void
104
    {
105
        $extension = new DoctrineExtension();
106
107
        $extension->load([['orm' => ['auto_mapping' => true]]], $this->getContainer());
108
    }
109
110
    public function getAutomappingConfigurations() : array
111
    {
112
        return [
113
            [
114
                [
115
                    'em1' => [
116
                        'mappings' => ['YamlBundle' => null],
117
                    ],
118
                    'em2' => [
119
                        'mappings' => ['XmlBundle' => null],
120
                    ],
121
                ],
122
            ],
123
            [
124
                [
125
                    'em1' => ['auto_mapping' => true],
126
                    'em2' => [
127
                        'mappings' => ['XmlBundle' => null],
128
                    ],
129
                ],
130
            ],
131
            [
132
                [
133
                    'em1' => [
134
                        'auto_mapping' => true,
135
                        'mappings' => ['YamlBundle' => null],
136
                    ],
137
                    'em2' => [
138
                        'mappings' => ['XmlBundle' => null],
139
                    ],
140
                ],
141
            ],
142
        ];
143
    }
144
145
    /**
146
     * @dataProvider getAutomappingConfigurations
147
     */
148
    public function testAutomapping(array $entityManagers) : void
149
    {
150
        $extension = new DoctrineExtension();
151
152
        $container = $this->getContainer([
0 ignored issues
show
Documentation introduced by
array('YamlBundle', 'XmlBundle') is of type array<integer,string,{"0":"string","1":"string"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
153
            'YamlBundle',
154
            'XmlBundle',
155
        ]);
156
157
        $extension->load(
158
            [
159
                [
160
                    'dbal' => [
161
                        'default_connection' => 'cn1',
162
                        'connections' => [
163
                            'cn1' => [],
164
                            'cn2' => [],
165
                        ],
166
                    ],
167
                    'orm' => ['entity_managers' => $entityManagers],
168
                ],
169
            ],
170
            $container
171
        );
172
173
        $configEm1 = $container->getDefinition('doctrine.orm.em1_configuration');
174
        $configEm2 = $container->getDefinition('doctrine.orm.em2_configuration');
175
176
        $this->assertContains(
177
            [
178
                'setEntityNamespaces',
179
                [
180
                    ['YamlBundle' => 'Fixtures\Bundles\YamlBundle\Entity'],
181
                ],
182
            ],
183
            $configEm1->getMethodCalls()
184
        );
185
186
        $this->assertContains(
187
            [
188
                'setEntityNamespaces',
189
                [
190
                    ['XmlBundle' => 'Fixtures\Bundles\XmlBundle\Entity'],
191
                ],
192
            ],
193
            $configEm2->getMethodCalls()
194
        );
195
    }
196
197
    public function testDbalLoad() : void
198
    {
199
        $container = $this->getContainer();
200
        $extension = new DoctrineExtension();
201
202
        $extension->load([
203
            ['dbal' => ['connections' => ['default' => ['password' => 'foo']]]],
204
            [],
205
            ['dbal' => ['default_connection' => 'foo']],
206
            [],
207
        ], $container);
208
209
        $config = $container->getDefinition('doctrine.dbal.default_connection')->getArgument(0);
210
211
        $this->assertEquals('foo', $config['password']);
212
        $this->assertEquals('root', $config['user']);
213
    }
214
215
    public function testDbalWrapperClass() : void
216
    {
217
        $container = $this->getContainer();
218
        $extension = new DoctrineExtension();
219
220
        $extension->load(
221
            [
222
                [
223
                    'dbal' => [
224
                        'connections' => [
225
                            'default' => ['password' => 'foo', 'wrapper_class' => TestWrapperClass::class],
226
                            'second' => ['password' => 'boo'],
227
                        ],
228
                    ],
229
                ],
230
                [],
231
                ['dbal' => ['default_connection' => 'foo']],
232
                [],
233
            ],
234
            $container
235
        );
236
237
        $this->assertEquals(TestWrapperClass::class, $container->getDefinition('doctrine.dbal.default_connection')->getClass());
238
        $this->assertNull($container->getDefinition('doctrine.dbal.second_connection')->getClass());
239
    }
240
241
    public function testDependencyInjectionConfigurationDefaults() : void
242
    {
243
        $container = $this->getContainer();
244
        $extension = new DoctrineExtension();
245
        $config    = BundleConfigurationBuilder::createBuilderWithBaseValues()->build();
246
247
        $extension->load([$config], $container);
248
249
        $this->assertFalse($container->getParameter('doctrine.orm.auto_generate_proxy_classes'));
250
        $this->assertEquals('Doctrine\ORM\Configuration', $container->getParameter('doctrine.orm.configuration.class'));
251
        $this->assertEquals('Doctrine\ORM\EntityManager', $container->getParameter('doctrine.orm.entity_manager.class'));
252
        $this->assertEquals('Proxies', $container->getParameter('doctrine.orm.proxy_namespace'));
253
        $this->assertEquals('Doctrine\Common\Cache\ArrayCache', $container->getParameter('doctrine.orm.cache.array.class'));
254
        $this->assertEquals('Doctrine\Common\Cache\ApcCache', $container->getParameter('doctrine.orm.cache.apc.class'));
255
        $this->assertEquals('Doctrine\Common\Cache\MemcacheCache', $container->getParameter('doctrine.orm.cache.memcache.class'));
256
        $this->assertEquals('localhost', $container->getParameter('doctrine.orm.cache.memcache_host'));
257
        $this->assertEquals('11211', $container->getParameter('doctrine.orm.cache.memcache_port'));
258
        $this->assertEquals('Memcache', $container->getParameter('doctrine.orm.cache.memcache_instance.class'));
259
        $this->assertEquals('Doctrine\Common\Cache\XcacheCache', $container->getParameter('doctrine.orm.cache.xcache.class'));
260
        $this->assertEquals('Doctrine\Persistence\Mapping\Driver\MappingDriverChain', $container->getParameter('doctrine.orm.metadata.driver_chain.class'));
261
        $this->assertEquals('Doctrine\ORM\Mapping\Driver\AnnotationDriver', $container->getParameter('doctrine.orm.metadata.annotation.class'));
262
        $this->assertEquals('Doctrine\ORM\Mapping\Driver\SimplifiedXmlDriver', $container->getParameter('doctrine.orm.metadata.xml.class'));
263
        $this->assertEquals('Doctrine\ORM\Mapping\Driver\SimplifiedYamlDriver', $container->getParameter('doctrine.orm.metadata.yml.class'));
264
265
        // second-level cache
266
        $this->assertEquals('Doctrine\ORM\Cache\DefaultCacheFactory', $container->getParameter('doctrine.orm.second_level_cache.default_cache_factory.class'));
267
        $this->assertEquals('Doctrine\ORM\Cache\Region\DefaultRegion', $container->getParameter('doctrine.orm.second_level_cache.default_region.class'));
268
        $this->assertEquals('Doctrine\ORM\Cache\Region\FileLockRegion', $container->getParameter('doctrine.orm.second_level_cache.filelock_region.class'));
269
        $this->assertEquals('Doctrine\ORM\Cache\Logging\CacheLoggerChain', $container->getParameter('doctrine.orm.second_level_cache.logger_chain.class'));
270
        $this->assertEquals('Doctrine\ORM\Cache\Logging\StatisticsCacheLogger', $container->getParameter('doctrine.orm.second_level_cache.logger_statistics.class'));
271
        $this->assertEquals('Doctrine\ORM\Cache\CacheConfiguration', $container->getParameter('doctrine.orm.second_level_cache.cache_configuration.class'));
272
        $this->assertEquals('Doctrine\ORM\Cache\RegionsConfiguration', $container->getParameter('doctrine.orm.second_level_cache.regions_configuration.class'));
273
274
        $config = BundleConfigurationBuilder::createBuilder()
275
            ->addBaseConnection()
276
            ->addEntityManager([
277
                'proxy_namespace' => 'MyProxies',
278
                'auto_generate_proxy_classes' => true,
279
                'default_entity_manager' => 'default',
280
                'entity_managers' => [
281
                    'default' => [
282
                        'mappings' => ['YamlBundle' => []],
283
                    ],
284
                ],
285
            ])
286
            ->build();
287
288
        $container = $this->getContainer();
289
        $extension->load([$config], $container);
290
        $this->compileContainer($container);
291
292
        $definition = $container->getDefinition('doctrine.dbal.default_connection');
293
294
        $args = $definition->getArguments();
295
        $this->assertEquals('pdo_mysql', $args[0]['driver']);
296
        $this->assertEquals('localhost', $args[0]['host']);
297
        $this->assertEquals('root', $args[0]['user']);
298
        $this->assertEquals('doctrine.dbal.default_connection.configuration', (string) $args[1]);
299
        $this->assertEquals('doctrine.dbal.default_connection.event_manager', (string) $args[2]);
300
        $this->assertCount(0, $definition->getMethodCalls());
0 ignored issues
show
Documentation introduced by
$definition->getMethodCalls() is of type array, but the function expects a object<Countable>|object...nit\Framework\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
301
302
        $definition = $container->getDefinition('doctrine.orm.default_entity_manager');
303
        $this->assertEquals('%doctrine.orm.entity_manager.class%', $definition->getClass());
304
        $this->assertEquals(['%doctrine.orm.entity_manager.class%', 'create'], $definition->getFactory());
305
306
        $this->assertEquals(['default' => 'doctrine.orm.default_entity_manager'], $container->getParameter('doctrine.entity_managers'), 'Set of the existing EntityManagers names is incorrect.');
307
        $this->assertEquals('%doctrine.entity_managers%', $container->getDefinition('doctrine')->getArgument(2), 'Set of the existing EntityManagers names is incorrect.');
308
309
        $arguments = $definition->getArguments();
310
        $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $arguments[0]);
311
        $this->assertEquals('doctrine.dbal.default_connection', (string) $arguments[0]);
312
        $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $arguments[1]);
313
        $this->assertEquals('doctrine.orm.default_configuration', (string) $arguments[1]);
314
315
        $definition = $container->getDefinition('doctrine.orm.default_configuration');
316
        $calls      = array_values($definition->getMethodCalls());
317
        $this->assertEquals(['YamlBundle' => 'Fixtures\Bundles\YamlBundle\Entity'], $calls[0][1][0]);
318
        $this->assertEquals('doctrine.orm.default_metadata_cache', (string) $calls[1][1][0]);
319
        $this->assertEquals('doctrine.orm.default_query_cache', (string) $calls[2][1][0]);
320
        $this->assertEquals('doctrine.orm.default_result_cache', (string) $calls[3][1][0]);
321
322
        $this->assertEquals('doctrine.orm.naming_strategy.default', (string) $calls[10][1][0]);
323
        $this->assertEquals('doctrine.orm.quote_strategy.default', (string) $calls[11][1][0]);
324
        $this->assertEquals('doctrine.orm.default_entity_listener_resolver', (string) $calls[12][1][0]);
325
326
        $definition = $container->getDefinition((string) $container->getAlias('doctrine.orm.default_metadata_cache'));
327
        $this->assertEquals(DoctrineProvider::class, $definition->getClass());
328
        $arguments = $definition->getArguments();
329
        $this->assertInstanceOf(Reference::class, $arguments[0]);
330
        $this->assertEquals('cache.doctrine.orm.default.metadata', (string) $arguments[0]);
331
        $this->assertSame(ArrayAdapter::class, $container->getDefinition((string) $arguments[0])->getClass());
332
333
        $definition = $container->getDefinition((string) $container->getAlias('doctrine.orm.default_query_cache'));
334
        $this->assertEquals(DoctrineProvider::class, $definition->getClass());
335
        $arguments = $definition->getArguments();
336
        $this->assertInstanceOf(Reference::class, $arguments[0]);
337
        $this->assertEquals('cache.doctrine.orm.default.query', (string) $arguments[0]);
338
        $this->assertSame(ArrayAdapter::class, $container->getDefinition((string) $arguments[0])->getClass());
339
340
        $definition = $container->getDefinition((string) $container->getAlias('doctrine.orm.default_result_cache'));
341
        $this->assertEquals(DoctrineProvider::class, $definition->getClass());
342
        $arguments = $definition->getArguments();
343
        $this->assertInstanceOf(Reference::class, $arguments[0]);
344
        $this->assertEquals('cache.doctrine.orm.default.result', (string) $arguments[0]);
345
        $this->assertSame(ArrayAdapter::class, $container->getDefinition((string) $arguments[0])->getClass());
346
    }
347
348
    public function testUseSavePointsAddMethodCallToAddSavepointsToTheConnection() : void
349
    {
350
        $container = $this->getContainer();
351
        $extension = new DoctrineExtension();
352
353
        $extension->load([
354
            [
355
                'dbal' => [
356
                    'connections' => [
357
                        'default' => ['password' => 'foo', 'use_savepoints' => true],
358
                    ],
359
                ],
360
            ],
361
        ], $container);
362
363
        $calls = $container->getDefinition('doctrine.dbal.default_connection')->getMethodCalls();
364
        $this->assertCount(1, $calls);
0 ignored issues
show
Documentation introduced by
$calls is of type array, but the function expects a object<Countable>|object...nit\Framework\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
365
        $this->assertEquals('setNestTransactionsWithSavepoints', $calls[0][0]);
366
        $this->assertTrue($calls[0][1][0]);
367
    }
368
369
    public function testAutoGenerateProxyClasses() : void
370
    {
371
        $container = $this->getContainer();
372
        $extension = new DoctrineExtension();
373
374
        $config = BundleConfigurationBuilder::createBuilder()
375
            ->addBaseConnection()
376
            ->addEntityManager([
377
                'proxy_namespace' => 'MyProxies',
378
                'auto_generate_proxy_classes' => 'eval',
379
                'default_entity_manager' => 'default',
380
                'entity_managers' => [
381
                    'default' => [
382
                        'mappings' => ['YamlBundle' => []],
383
                    ],
384
                ],
385
            ])
386
            ->build();
387
388
        $extension->load([$config], $container);
389
390
        $this->assertEquals(3 /* \Doctrine\Common\Proxy\AbstractProxyFactory::AUTOGENERATE_EVAL */, $container->getParameter('doctrine.orm.auto_generate_proxy_classes'));
391
    }
392
393
    public function testSingleEntityManagerWithDefaultConfiguration() : void
394
    {
395
        $container = $this->getContainer();
396
        $extension = new DoctrineExtension();
397
398
        $configurationArray = BundleConfigurationBuilder::createBuilderWithBaseValues()->build();
399
400
        $extension->load([$configurationArray], $container);
401
        $this->compileContainer($container);
402
403
        $definition = $container->getDefinition('doctrine.orm.default_entity_manager');
404
        $this->assertEquals('%doctrine.orm.entity_manager.class%', $definition->getClass());
405
        $this->assertEquals(['%doctrine.orm.entity_manager.class%', 'create'], $definition->getFactory());
406
407
        $this->assertDICConstructorArguments($definition, [
408
            new Reference('doctrine.dbal.default_connection'),
409
            new Reference('doctrine.orm.default_configuration'),
410
        ]);
411
    }
412
413
    public function testSingleEntityManagerWithDefaultSecondLevelCacheConfiguration() : void
414
    {
415
        $container = $this->getContainer();
416
        $extension = new DoctrineExtension();
417
418
        $configurationArray = BundleConfigurationBuilder::createBuilderWithBaseValues()
419
            ->addBaseSecondLevelCache()
420
            ->build();
421
422
        $extension->load([$configurationArray], $container);
423
        $this->compileContainer($container);
424
425
        $definition = $container->getDefinition('doctrine.orm.default_entity_manager');
426
        $this->assertEquals('%doctrine.orm.entity_manager.class%', $definition->getClass());
427
        $this->assertEquals(['%doctrine.orm.entity_manager.class%', 'create'], $definition->getFactory());
428
429
        $this->assertDICConstructorArguments($definition, [
430
            new Reference('doctrine.dbal.default_connection'),
431
            new Reference('doctrine.orm.default_configuration'),
432
        ]);
433
434
        $slcDefinition = $container->getDefinition('doctrine.orm.default_second_level_cache.default_cache_factory');
435
        $this->assertEquals('%doctrine.orm.second_level_cache.default_cache_factory.class%', $slcDefinition->getClass());
436
    }
437
438
    public function testSingleEntityManagerWithCustomSecondLevelCacheConfiguration() : void
439
    {
440
        $container = $this->getContainer();
441
        $extension = new DoctrineExtension();
442
443
        $configurationArray = BundleConfigurationBuilder::createBuilderWithBaseValues()
444
            ->addSecondLevelCache([
445
                'region_cache_driver' => ['type' => 'service', 'id' => 'my_cache'],
446
                'regions' => [
447
                    'hour_region' => ['lifetime' => 3600],
448
                ],
449
                'factory' => 'YamlBundle\Cache\MyCacheFactory',
450
            ])
451
            ->build();
452
453
        $extension->load([$configurationArray], $container);
454
        $this->compileContainer($container);
455
456
        $definition = $container->getDefinition('doctrine.orm.default_entity_manager');
457
        $this->assertEquals('%doctrine.orm.entity_manager.class%', $definition->getClass());
458
        $this->assertEquals(['%doctrine.orm.entity_manager.class%', 'create'], $definition->getFactory());
459
460
        $this->assertDICConstructorArguments($definition, [
461
            new Reference('doctrine.dbal.default_connection'),
462
            new Reference('doctrine.orm.default_configuration'),
463
        ]);
464
465
        $slcDefinition = $container->getDefinition('doctrine.orm.default_second_level_cache.default_cache_factory');
466
        $this->assertEquals('YamlBundle\Cache\MyCacheFactory', $slcDefinition->getClass());
467
    }
468
469 View Code Duplication
    public function testBundleEntityAliases() : void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
470
    {
471
        $container = $this->getContainer();
472
        $extension = new DoctrineExtension();
473
474
        $config        = BundleConfigurationBuilder::createBuilder()
475
             ->addBaseConnection()
476
             ->build();
477
        $config['orm'] = ['default_entity_manager' => 'default', 'entity_managers' => ['default' => ['mappings' => ['YamlBundle' => []]]]];
478
        $extension->load([$config], $container);
479
480
        $definition = $container->getDefinition('doctrine.orm.default_configuration');
481
        $this->assertDICDefinitionMethodCallOnce(
482
            $definition,
483
            'setEntityNamespaces',
484
            [['YamlBundle' => 'Fixtures\Bundles\YamlBundle\Entity']]
485
        );
486
    }
487
488 View Code Duplication
    public function testOverwriteEntityAliases() : void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
489
    {
490
        $container = $this->getContainer();
491
        $extension = new DoctrineExtension();
492
493
        $config        = BundleConfigurationBuilder::createBuilder()
494
             ->addBaseConnection()
495
             ->build();
496
        $config['orm'] = ['default_entity_manager' => 'default', 'entity_managers' => ['default' => ['mappings' => ['YamlBundle' => ['alias' => 'yml']]]]];
497
        $extension->load([$config], $container);
498
499
        $definition = $container->getDefinition('doctrine.orm.default_configuration');
500
        $this->assertDICDefinitionMethodCallOnce(
501
            $definition,
502
            'setEntityNamespaces',
503
            [['yml' => 'Fixtures\Bundles\YamlBundle\Entity']]
504
        );
505
    }
506
507
    public function testYamlBundleMappingDetection() : void
508
    {
509
        $container = $this->getContainer('YamlBundle');
510
        $extension = new DoctrineExtension();
511
512
        $config = BundleConfigurationBuilder::createBuilder()
513
            ->addBaseConnection()
514
            ->addBaseEntityManager()
515
            ->build();
516
        $extension->load([$config], $container);
517
518
        $definition = $container->getDefinition('doctrine.orm.default_metadata_driver');
519
        $this->assertDICDefinitionMethodCallOnce($definition, 'addDriver', [
520
            new Reference('doctrine.orm.default_yml_metadata_driver'),
521
            'Fixtures\Bundles\YamlBundle\Entity',
522
        ]);
523
    }
524
525 View Code Duplication
    public function testXmlBundleMappingDetection() : void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
526
    {
527
        $container = $this->getContainer('XmlBundle');
528
        $extension = new DoctrineExtension();
529
530
        $config = BundleConfigurationBuilder::createBuilder()
531
            ->addBaseConnection()
532
            ->addEntityManager([
533
                'default_entity_manager' => 'default',
534
                'entity_managers' => [
535
                    'default' => [
536
                        'mappings' => [
537
                            'XmlBundle' => [],
538
                        ],
539
                    ],
540
                ],
541
            ])
542
            ->build();
543
        $extension->load([$config], $container);
544
545
        $definition = $container->getDefinition('doctrine.orm.default_metadata_driver');
546
        $this->assertDICDefinitionMethodCallOnce($definition, 'addDriver', [
547
            new Reference('doctrine.orm.default_xml_metadata_driver'),
548
            'Fixtures\Bundles\XmlBundle\Entity',
549
        ]);
550
    }
551
552 View Code Duplication
    public function testAnnotationsBundleMappingDetection() : void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
553
    {
554
        $container = $this->getContainer('AnnotationsBundle');
555
        $extension = new DoctrineExtension();
556
557
        $config = BundleConfigurationBuilder::createBuilder()
558
            ->addBaseConnection()
559
            ->addEntityManager([
560
                'default_entity_manager' => 'default',
561
                'entity_managers' => [
562
                    'default' => [
563
                        'mappings' => [
564
                            'AnnotationsBundle' => [],
565
                        ],
566
                    ],
567
                ],
568
            ])
569
            ->build();
570
        $extension->load([$config], $container);
571
572
        $definition = $container->getDefinition('doctrine.orm.default_metadata_driver');
573
        $this->assertDICDefinitionMethodCallOnce($definition, 'addDriver', [
574
            new Reference('doctrine.orm.default_annotation_metadata_driver'),
575
            'Fixtures\Bundles\AnnotationsBundle\Entity',
576
        ]);
577
    }
578
579
    public function testOrmMergeConfigs() : void
580
    {
581
        $container = $this->getContainer(['XmlBundle', 'AnnotationsBundle']);
0 ignored issues
show
Documentation introduced by
array('XmlBundle', 'AnnotationsBundle') is of type array<integer,string,{"0":"string","1":"string"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
582
        $extension = new DoctrineExtension();
583
584
        $config1 = BundleConfigurationBuilder::createBuilder()
585
            ->addBaseConnection()
586
            ->addEntityManager([
587
                'auto_generate_proxy_classes' => true,
588
                'default_entity_manager' => 'default',
589
                'entity_managers' => [
590
                    'default' => [
591
                        'mappings' => [
592
                            'AnnotationsBundle' => [],
593
                        ],
594
                    ],
595
                ],
596
            ])
597
            ->build();
598
        $config2 = BundleConfigurationBuilder::createBuilder()
599
            ->addBaseConnection()
600
            ->addEntityManager([
601
                'auto_generate_proxy_classes' => false,
602
                'default_entity_manager' => 'default',
603
                'entity_managers' => [
604
                    'default' => [
605
                        'mappings' => [
606
                            'XmlBundle' => [],
607
                        ],
608
                    ],
609
                ],
610
            ])
611
            ->build();
612
        $extension->load([$config1, $config2], $container);
613
614
        $definition = $container->getDefinition('doctrine.orm.default_metadata_driver');
615
        $this->assertDICDefinitionMethodCallAt(0, $definition, 'addDriver', [
616
            new Reference('doctrine.orm.default_annotation_metadata_driver'),
617
            'Fixtures\Bundles\AnnotationsBundle\Entity',
618
        ]);
619
        $this->assertDICDefinitionMethodCallAt(1, $definition, 'addDriver', [
620
            new Reference('doctrine.orm.default_xml_metadata_driver'),
621
            'Fixtures\Bundles\XmlBundle\Entity',
622
        ]);
623
624
        $configDef = $container->getDefinition('doctrine.orm.default_configuration');
625
        $this->assertDICDefinitionMethodCallOnce($configDef, 'setAutoGenerateProxyClasses');
626
627
        $calls = $configDef->getMethodCalls();
628
        foreach ($calls as $call) {
629
            if ($call[0] === 'setAutoGenerateProxyClasses') {
630
                $this->assertFalse($container->getParameterBag()->resolveValue($call[1][0]));
631
                break;
632
            }
633
        }
634
    }
635
636
    public function testAnnotationsBundleMappingDetectionWithVendorNamespace() : void
637
    {
638
        $container = $this->getContainer('AnnotationsBundle', 'Vendor');
639
        $extension = new DoctrineExtension();
640
641
        $config = BundleConfigurationBuilder::createBuilder()
642
            ->addBaseConnection()
643
            ->addEntityManager([
644
                'default_entity_manager' => 'default',
645
                'entity_managers' => [
646
                    'default' => [
647
                        'mappings' => [
648
                            'AnnotationsBundle' => [],
649
                        ],
650
                    ],
651
                ],
652
            ])
653
            ->build();
654
        $extension->load([$config], $container);
655
656
        $calls = $container->getDefinition('doctrine.orm.default_metadata_driver')->getMethodCalls();
657
        $this->assertEquals('doctrine.orm.default_annotation_metadata_driver', (string) $calls[0][1][0]);
658
        $this->assertEquals('Fixtures\Bundles\Vendor\AnnotationsBundle\Entity', $calls[0][1][1]);
659
    }
660
661
    public function testMessengerIntegration() : void
662
    {
663
        if (! interface_exists(MessageBusInterface::class)) {
664
            $this->markTestSkipped('Symfony Messenger component is not installed');
665
        }
666
667
        $container = $this->getContainer();
668
        $extension = new DoctrineExtension();
669
670
        $config = BundleConfigurationBuilder::createBuilder()
671
            ->addBaseConnection()
672
            ->build();
673
        $extension->load([$config], $container);
674
675
        $this->assertNotNull($middlewarePrototype = $container->getDefinition('messenger.middleware.doctrine_transaction'));
676
        $this->assertCount(1, $middlewarePrototype->getArguments());
0 ignored issues
show
Documentation introduced by
$middlewarePrototype->getArguments() is of type array, but the function expects a object<Countable>|object...nit\Framework\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
677
        $this->assertNotNull($middlewarePrototype = $container->getDefinition('messenger.middleware.doctrine_ping_connection'));
678
        $this->assertCount(1, $middlewarePrototype->getArguments());
0 ignored issues
show
Documentation introduced by
$middlewarePrototype->getArguments() is of type array, but the function expects a object<Countable>|object...nit\Framework\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
679
        $this->assertNotNull($middlewarePrototype = $container->getDefinition('messenger.middleware.doctrine_close_connection'));
680
        $this->assertCount(1, $middlewarePrototype->getArguments());
0 ignored issues
show
Documentation introduced by
$middlewarePrototype->getArguments() is of type array, but the function expects a object<Countable>|object...nit\Framework\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
681
682
        if (class_exists(DoctrineClearEntityManagerWorkerSubscriber::class)) {
683
            $this->assertNotNull($subscriber = $container->getDefinition('doctrine.orm.messenger.event_subscriber.doctrine_clear_entity_manager'));
684
            $this->assertCount(1, $subscriber->getArguments());
0 ignored issues
show
Documentation introduced by
$subscriber->getArguments() is of type array, but the function expects a object<Countable>|object...nit\Framework\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
685
        } else {
686
            $this->assertFalse($container->hasDefinition('doctrine.orm.messenger.event_subscriber.doctrine_clear_entity_manager'));
687
        }
688
    }
689
690
    public function testInvalidCacheConfiguration() : void
691
    {
692
        $container = $this->getContainer();
693
        $extension = new DoctrineExtension();
694
695
        $config = BundleConfigurationBuilder::createBuilder()
696
            ->addBaseConnection()
697
            ->addEntityManager(['metadata_cache_driver' => 'redis'])
698
            ->build();
699
700
        $this->expectException(InvalidArgumentException::class);
701
        $this->expectExceptionMessage('Unknown cache of type "redis" configured for cache "metadata_cache" in entity manager "default"');
702
703
        $extension->load([$config], $container);
704
    }
705
706
    /**
707
     * @param array|string $cacheConfig
708
     *
709
     * @dataProvider cacheConfigurationProvider
710
     */
711
    public function testCacheConfiguration(string $expectedAliasName, string $expectedAliasTarget, string $cacheName, $cacheConfig) : void
712
    {
713
        $container = $this->getContainer();
714
        $extension = new DoctrineExtension();
715
716
        $config = BundleConfigurationBuilder::createBuilder()
717
            ->addBaseConnection()
718
            ->addEntityManager([$cacheName => $cacheConfig])
719
            ->build();
720
721
        $extension->load([$config], $container);
722
723
        $this->assertTrue($container->hasAlias($expectedAliasName));
724
        $alias = $container->getAlias($expectedAliasName);
725
        $this->assertEquals($expectedAliasTarget, (string) $alias);
726
    }
727
728
    public static function cacheConfigurationProvider() : array
729
    {
730
        return [
731
            'metadata_cache_default' => [
732
                'expectedAliasName' => 'doctrine.orm.default_metadata_cache',
733
                'expectedAliasTarget' => 'doctrine.orm.cache.provider.cache.doctrine.orm.default.metadata',
734
                'cacheName' => 'metadata_cache_driver',
735
                'cacheConfig' => ['type' => null],
736
            ],
737
            'query_cache_default' => [
738
                'expectedAliasName' => 'doctrine.orm.default_query_cache',
739
                'expectedAliasTarget' => 'doctrine.orm.cache.provider.cache.doctrine.orm.default.query',
740
                'cacheName' => 'query_cache_driver',
741
                'cacheConfig' => ['type' => null],
742
            ],
743
            'result_cache_default' => [
744
                'expectedAliasName' => 'doctrine.orm.default_result_cache',
745
                'expectedAliasTarget' => 'doctrine.orm.cache.provider.cache.doctrine.orm.default.result',
746
                'cacheName' => 'result_cache_driver',
747
                'cacheConfig' => ['type' => null],
748
            ],
749
750
            'metadata_cache_pool' => [
751
                'expectedAliasName' => 'doctrine.orm.default_metadata_cache',
752
                'expectedAliasTarget' => 'doctrine.orm.cache.provider.metadata_cache_pool',
753
                'cacheName' => 'metadata_cache_driver',
754
                'cacheConfig' => ['type' => 'pool', 'pool' => 'metadata_cache_pool'],
755
            ],
756
            'query_cache_pool' => [
757
                'expectedAliasName' => 'doctrine.orm.default_query_cache',
758
                'expectedAliasTarget' => 'doctrine.orm.cache.provider.query_cache_pool',
759
                'cacheName' => 'query_cache_driver',
760
                'cacheConfig' => ['type' => 'pool', 'pool' => 'query_cache_pool'],
761
            ],
762
            'result_cache_pool' => [
763
                'expectedAliasName' => 'doctrine.orm.default_result_cache',
764
                'expectedAliasTarget' => 'doctrine.orm.cache.provider.result_cache_pool',
765
                'cacheName' => 'result_cache_driver',
766
                'cacheConfig' => ['type' => 'pool', 'pool' => 'result_cache_pool'],
767
            ],
768
769
            'metadata_cache_service' => [
770
                'expectedAliasName' => 'doctrine.orm.default_metadata_cache',
771
                'expectedAliasTarget' => 'service_target_metadata',
772
                'cacheName' => 'metadata_cache_driver',
773
                'cacheConfig' => ['type' => 'service', 'id' => 'service_target_metadata'],
774
            ],
775
            'query_cache_service' => [
776
                'expectedAliasName' => 'doctrine.orm.default_query_cache',
777
                'expectedAliasTarget' => 'service_target_query',
778
                'cacheName' => 'query_cache_driver',
779
                'cacheConfig' => ['type' => 'service', 'id' => 'service_target_query'],
780
            ],
781
            'result_cache_service' => [
782
                'expectedAliasName' => 'doctrine.orm.default_result_cache',
783
                'expectedAliasTarget' => 'service_target_result',
784
                'cacheName' => 'result_cache_driver',
785
                'cacheConfig' => ['type' => 'service', 'id' => 'service_target_result'],
786
            ],
787
        ];
788
    }
789
790
    public function testShardManager() : void
791
    {
792
        $container = $this->getContainer();
793
        $extension = new DoctrineExtension();
794
795
        $config = BundleConfigurationBuilder::createBuilder()
796
             ->addConnection([
797
                 'connections' => [
798
                     'foo' => [
799
                         'shards' => [
800
                             'test' => ['id' => 1],
801
                         ],
802
                     ],
803
                     'bar' => [],
804
                 ],
805
             ])
806
            ->build();
807
808
        $extension->load([$config], $container);
809
810
        $this->assertTrue($container->hasDefinition('doctrine.dbal.foo_shard_manager'));
811
        $this->assertFalse($container->hasDefinition('doctrine.dbal.bar_shard_manager'));
812
    }
813
814
    private function getContainer($bundles = 'YamlBundle', $vendor = null) : ContainerBuilder
815
    {
816
        $bundles = (array) $bundles;
817
818
        $map = [];
819
        foreach ($bundles as $bundle) {
820
            require_once __DIR__ . '/Fixtures/Bundles/' . ($vendor ? $vendor . '/' : '') . $bundle . '/' . $bundle . '.php';
821
822
            $map[$bundle] = 'Fixtures\\Bundles\\' . ($vendor ? $vendor . '\\' : '') . $bundle . '\\' . $bundle;
823
        }
824
825
        $container = new ContainerBuilder(new ParameterBag([
826
            'kernel.name' => 'app',
827
            'kernel.debug' => false,
828
            'kernel.bundles' => $map,
829
            'kernel.cache_dir' => sys_get_temp_dir(),
830
            'kernel.environment' => 'test',
831
            'kernel.root_dir' => __DIR__ . '/../../', // src dir
832
        ]));
833
834
        // Register dummy cache services so we don't have to load the FrameworkExtension
835
        $container->setDefinition('cache.system', (new Definition(ArrayAdapter::class))->setPublic(true));
836
        $container->setDefinition('cache.app', (new Definition(ArrayAdapter::class))->setPublic(true));
837
        $container->setDefinition('my_pool', (new Definition(ArrayAdapter::class))->setPublic(true));
838
839
        return $container;
840
    }
841
842
    private function assertDICConstructorArguments(Definition $definition, array $args) : void
843
    {
844
        $this->assertEquals($args, $definition->getArguments(), "Expected and actual DIC Service constructor arguments of definition '" . $definition->getClass() . "' don't match.");
845
    }
846
847 View Code Duplication
    private function assertDICDefinitionMethodCallAt(int $pos, Definition $definition, string $methodName, array $params = null) : void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
848
    {
849
        $calls = $definition->getMethodCalls();
850
        if (! isset($calls[$pos][0])) {
851
            return;
852
        }
853
854
        $this->assertEquals($methodName, $calls[$pos][0], "Method '" . $methodName . "' is expected to be called at position " . $pos . '.');
855
856
        if ($params === null) {
857
            return;
858
        }
859
860
        $this->assertEquals($params, $calls[$pos][1], "Expected parameters to methods '" . $methodName . "' do not match the actual parameters.");
861
    }
862
863
    /**
864
     * Assertion for the DI Container, check if the given definition contains a method call with the given parameters.
865
     */
866 View Code Duplication
    private function assertDICDefinitionMethodCallOnce(Definition $definition, string $methodName, array $params = null) : void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
867
    {
868
        $calls  = $definition->getMethodCalls();
869
        $called = false;
870
        foreach ($calls as $call) {
871
            if ($call[0] !== $methodName) {
872
                continue;
873
            }
874
875
            if ($called) {
876
                $this->fail("Method '" . $methodName . "' is expected to be called only once, a second call was registered though.");
877
            } else {
878
                $called = true;
879
                if ($params !== null) {
880
                    $this->assertEquals($params, $call[1], "Expected parameters to methods '" . $methodName . "' do not match the actual parameters.");
881
                }
882
            }
883
        }
884
        if ($called) {
885
            return;
886
        }
887
888
        $this->fail("Method '" . $methodName . "' is expected to be called once, definition does not contain a call though.");
889
    }
890
891
    private function compileContainer(ContainerBuilder $container) : void
892
    {
893
        $container->getCompilerPassConfig()->setOptimizationPasses([new ResolveChildDefinitionsPass()]);
894
        $container->getCompilerPassConfig()->setRemovingPasses([]);
895
        $container->compile();
896
    }
897
}
898
899
class TestWrapperClass extends Connection
900
{
901
}
902