Completed
Pull Request — master (#817)
by Maxime
02:16
created

DoctrineExtensionTest::testMessengerIntegration()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 24
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 24
rs 8.9713
cc 2
eloc 16
nc 2
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\Common\Persistence\ManagerRegistry;
8
use Doctrine\Common\Persistence\ObjectManager;
9
use Doctrine\Common\Proxy\AbstractProxyFactory;
10
use Doctrine\DBAL\Connection;
11
use Doctrine\DBAL\Driver\Connection as DriverConnection;
12
use Doctrine\ORM\EntityManagerInterface;
13
use Doctrine\ORM\Version;
14
use PHPUnit\Framework\TestCase;
15
use Symfony\Component\DependencyInjection\Compiler\ResolveChildDefinitionsPass;
16
use Symfony\Component\DependencyInjection\Compiler\ResolveDefinitionTemplatesPass;
17
use Symfony\Component\DependencyInjection\ContainerBuilder;
18
use Symfony\Component\DependencyInjection\Definition;
19
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
20
use Symfony\Component\DependencyInjection\Reference;
21
use Symfony\Component\Messenger\MessageBusInterface;
22
23
class DoctrineExtensionTest extends TestCase
24
{
25
    public function testAutowiringAlias()
26
    {
27
        $container = $this->getContainer();
28
        $extension = new DoctrineExtension();
29
        $config    = BundleConfigurationBuilder::createBuilderWithBaseValues()->build();
30
31
        $extension->load([$config], $container);
32
33
        $expectedAliases = [
34
            DriverConnection::class => 'database_connection',
35
            Connection::class => 'database_connection',
36
            ManagerRegistry::class => 'doctrine',
37
            ObjectManager::class => 'doctrine.orm.entity_manager',
38
            EntityManagerInterface::class => 'doctrine.orm.entity_manager',
39
        ];
40
41
        foreach ($expectedAliases as $id => $target) {
42
            $this->assertTrue($container->hasAlias($id), sprintf('The container should have a `%s` alias for autowiring support.', $id));
43
44
            $alias = $container->getAlias($id);
45
            $this->assertEquals($target, (string) $alias, sprintf('The autowiring for `%s` should use `%s`.', $id, $target));
46
            $this->assertFalse($alias->isPublic(), sprintf('The autowiring alias for `%s` should be private.', $id, $target));
47
        }
48
    }
49
50
    public function testPublicServicesAndAliases()
51
    {
52
        $container = $this->getContainer();
53
        $extension = new DoctrineExtension();
54
        $config    = BundleConfigurationBuilder::createBuilderWithBaseValues()->build();
55
56
        $extension->load([$config], $container);
57
58
        $this->assertTrue($container->getDefinition('doctrine')->isPublic());
59
        $this->assertTrue($container->getAlias('doctrine.orm.entity_manager')->isPublic());
60
        $this->assertTrue($container->getAlias('database_connection')->isPublic());
61
    }
62
63
    public function testDbalGenerateDefaultConnectionConfiguration()
64
    {
65
        $container = $this->getContainer();
66
        $extension = new DoctrineExtension();
67
68
        $container->registerExtension($extension);
69
70
        $extension->load([['dbal' => []]], $container);
71
72
        // doctrine.dbal.default_connection
73
        $this->assertEquals('%doctrine.default_connection%', $container->getDefinition('doctrine')->getArgument(3));
74
        $this->assertEquals('default', $container->getParameter('doctrine.default_connection'));
75
        $this->assertEquals('root', $container->getDefinition('doctrine.dbal.default_connection')->getArgument(0)['user']);
76
        $this->assertNull($container->getDefinition('doctrine.dbal.default_connection')->getArgument(0)['password']);
77
        $this->assertEquals('localhost', $container->getDefinition('doctrine.dbal.default_connection')->getArgument(0)['host']);
78
        $this->assertNull($container->getDefinition('doctrine.dbal.default_connection')->getArgument(0)['port']);
79
        $this->assertEquals('pdo_mysql', $container->getDefinition('doctrine.dbal.default_connection')->getArgument(0)['driver']);
80
        $this->assertEquals([], $container->getDefinition('doctrine.dbal.default_connection')->getArgument(0)['driverOptions']);
81
    }
82
83
    public function testDbalOverrideDefaultConnection()
84
    {
85
        $container = $this->getContainer();
86
        $extension = new DoctrineExtension();
87
88
        $container->registerExtension($extension);
89
90
        $extension->load([[], ['dbal' => ['default_connection' => 'foo']], []], $container);
91
92
        // doctrine.dbal.default_connection
93
        $this->assertEquals('%doctrine.default_connection%', $container->getDefinition('doctrine')->getArgument(3), '->load() overrides existing configuration options');
94
        $this->assertEquals('foo', $container->getParameter('doctrine.default_connection'), '->load() overrides existing configuration options');
95
    }
96
97
    /**
98
     * @expectedException \LogicException
99
     * @expectedExceptionMessage Configuring the ORM layer requires to configure the DBAL layer as well.
100
     */
101
    public function testOrmRequiresDbal()
102
    {
103
        $extension = new DoctrineExtension();
104
105
        $extension->load([['orm' => ['auto_mapping' => true]]], $this->getContainer());
106
    }
107
108
    public function getAutomappingConfigurations()
109
    {
110
        return [
111
            [
112
                [
113
                    'em1' => [
114
                        'mappings' => ['YamlBundle' => null],
115
                    ],
116
                    'em2' => [
117
                        'mappings' => ['XmlBundle' => null],
118
                    ],
119
                ],
120
            ],
121
            [
122
                [
123
                    'em1' => ['auto_mapping' => true],
124
                    'em2' => [
125
                        'mappings' => ['XmlBundle' => null],
126
                    ],
127
                ],
128
            ],
129
            [
130
                [
131
                    'em1' => [
132
                        'auto_mapping' => true,
133
                        'mappings' => ['YamlBundle' => null],
134
                    ],
135
                    'em2' => [
136
                        'mappings' => ['XmlBundle' => null],
137
                    ],
138
                ],
139
            ],
140
        ];
141
    }
142
143
    /**
144
     * @dataProvider getAutomappingConfigurations
145
     */
146
    public function testAutomapping(array $entityManagers)
147
    {
148
        $extension = new DoctrineExtension();
149
150
        if (! method_exists($extension, 'fixManagersAutoMappings')) {
151
            $this->markTestSkipped('Auto mapping with multiple managers available with Symfony ~2.6');
152
        }
153
154
        $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...
155
            'YamlBundle',
156
            'XmlBundle',
157
        ]);
158
159
        $extension->load(
160
            [
161
                [
162
                    'dbal' => [
163
                        'default_connection' => 'cn1',
164
                        'connections' => [
165
                            'cn1' => [],
166
                            'cn2' => [],
167
                        ],
168
                    ],
169
                    'orm' => ['entity_managers' => $entityManagers],
170
                ],
171
            ],
172
            $container
173
        );
174
175
        $configEm1 = $container->getDefinition('doctrine.orm.em1_configuration');
176
        $configEm2 = $container->getDefinition('doctrine.orm.em2_configuration');
177
178
        $this->assertContains(
179
            [
180
                'setEntityNamespaces',
181
                [
182
                    ['YamlBundle' => 'Fixtures\Bundles\YamlBundle\Entity'],
183
                ],
184
            ],
185
            $configEm1->getMethodCalls()
186
        );
187
188
        $this->assertContains(
189
            [
190
                'setEntityNamespaces',
191
                [
192
                    ['XmlBundle' => 'Fixtures\Bundles\XmlBundle\Entity'],
193
                ],
194
            ],
195
            $configEm2->getMethodCalls()
196
        );
197
    }
198
199
    public function testDbalLoad()
200
    {
201
        $container = $this->getContainer();
202
        $extension = new DoctrineExtension();
203
204
        $extension->load([
205
            ['dbal' => ['connections' => ['default' => ['password' => 'foo']]]],
206
            [],
207
            ['dbal' => ['default_connection' => 'foo']],
208
            [],
209
        ], $container);
210
211
        $config = $container->getDefinition('doctrine.dbal.default_connection')->getArgument(0);
212
213
        $this->assertEquals('foo', $config['password']);
214
        $this->assertEquals('root', $config['user']);
215
    }
216
217
    public function testDbalWrapperClass()
218
    {
219
        $container = $this->getContainer();
220
        $extension = new DoctrineExtension();
221
222
        $extension->load(
223
            [
224
                [
225
            'dbal' => [
226
            'connections' => [
227
                    'default' => ['password' => 'foo', 'wrapper_class' => TestWrapperClass::class],
228
                    'second' => ['password' => 'boo'],
229
                ],
230
            ],
231
                ],
232
                [],
233
                ['dbal' => ['default_connection' => 'foo']],
234
                [],
235
            ],
236
            $container
237
        );
238
239
        $this->assertEquals(TestWrapperClass::class, $container->getDefinition('doctrine.dbal.default_connection')->getClass());
240
        $this->assertNull($container->getDefinition('doctrine.dbal.second_connection')->getClass());
241
    }
242
243
    public function testDependencyInjectionConfigurationDefaults()
244
    {
245
        $container = $this->getContainer();
246
        $extension = new DoctrineExtension();
247
        $config    = BundleConfigurationBuilder::createBuilderWithBaseValues()->build();
248
249
        $extension->load([$config], $container);
250
251
        $this->assertFalse($container->getParameter('doctrine.orm.auto_generate_proxy_classes'));
252
        $this->assertEquals('Doctrine\ORM\Configuration', $container->getParameter('doctrine.orm.configuration.class'));
253
        $this->assertEquals('Doctrine\ORM\EntityManager', $container->getParameter('doctrine.orm.entity_manager.class'));
254
        $this->assertEquals('Proxies', $container->getParameter('doctrine.orm.proxy_namespace'));
255
        $this->assertEquals('Doctrine\Common\Cache\ArrayCache', $container->getParameter('doctrine.orm.cache.array.class'));
256
        $this->assertEquals('Doctrine\Common\Cache\ApcCache', $container->getParameter('doctrine.orm.cache.apc.class'));
257
        $this->assertEquals('Doctrine\Common\Cache\MemcacheCache', $container->getParameter('doctrine.orm.cache.memcache.class'));
258
        $this->assertEquals('localhost', $container->getParameter('doctrine.orm.cache.memcache_host'));
259
        $this->assertEquals('11211', $container->getParameter('doctrine.orm.cache.memcache_port'));
260
        $this->assertEquals('Memcache', $container->getParameter('doctrine.orm.cache.memcache_instance.class'));
261
        $this->assertEquals('Doctrine\Common\Cache\XcacheCache', $container->getParameter('doctrine.orm.cache.xcache.class'));
262
        $this->assertEquals('Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain', $container->getParameter('doctrine.orm.metadata.driver_chain.class'));
263
        $this->assertEquals('Doctrine\ORM\Mapping\Driver\AnnotationDriver', $container->getParameter('doctrine.orm.metadata.annotation.class'));
264
        $this->assertEquals('Doctrine\ORM\Mapping\Driver\SimplifiedXmlDriver', $container->getParameter('doctrine.orm.metadata.xml.class'));
265
        $this->assertEquals('Doctrine\ORM\Mapping\Driver\SimplifiedYamlDriver', $container->getParameter('doctrine.orm.metadata.yml.class'));
266
267
        // second-level cache
268
        $this->assertEquals('Doctrine\ORM\Cache\DefaultCacheFactory', $container->getParameter('doctrine.orm.second_level_cache.default_cache_factory.class'));
269
        $this->assertEquals('Doctrine\ORM\Cache\Region\DefaultRegion', $container->getParameter('doctrine.orm.second_level_cache.default_region.class'));
270
        $this->assertEquals('Doctrine\ORM\Cache\Region\FileLockRegion', $container->getParameter('doctrine.orm.second_level_cache.filelock_region.class'));
271
        $this->assertEquals('Doctrine\ORM\Cache\Logging\CacheLoggerChain', $container->getParameter('doctrine.orm.second_level_cache.logger_chain.class'));
272
        $this->assertEquals('Doctrine\ORM\Cache\Logging\StatisticsCacheLogger', $container->getParameter('doctrine.orm.second_level_cache.logger_statistics.class'));
273
        $this->assertEquals('Doctrine\ORM\Cache\CacheConfiguration', $container->getParameter('doctrine.orm.second_level_cache.cache_configuration.class'));
274
        $this->assertEquals('Doctrine\ORM\Cache\RegionsConfiguration', $container->getParameter('doctrine.orm.second_level_cache.regions_configuration.class'));
275
276
        $config = BundleConfigurationBuilder::createBuilder()
277
            ->addBaseConnection()
278
            ->addEntityManager([
279
                'proxy_namespace' => 'MyProxies',
280
                'auto_generate_proxy_classes' => true,
281
                'default_entity_manager' => 'default',
282
                'entity_managers' => [
283
                    'default' => [
284
                        'mappings' => ['YamlBundle' => []],
285
                    ],
286
                ],
287
            ])
288
            ->build();
289
290
        $container = $this->getContainer();
291
        $extension->load([$config], $container);
292
        $this->compileContainer($container);
293
294
        $definition = $container->getDefinition('doctrine.dbal.default_connection');
295
296
        $args = $definition->getArguments();
297
        $this->assertEquals('pdo_mysql', $args[0]['driver']);
298
        $this->assertEquals('localhost', $args[0]['host']);
299
        $this->assertEquals('root', $args[0]['user']);
300
        $this->assertEquals('doctrine.dbal.default_connection.configuration', (string) $args[1]);
301
        $this->assertEquals('doctrine.dbal.default_connection.event_manager', (string) $args[2]);
302
        $this->assertCount(0, $definition->getMethodCalls());
303
304
        $definition = $container->getDefinition('doctrine.orm.default_entity_manager');
305
        $this->assertEquals('%doctrine.orm.entity_manager.class%', $definition->getClass());
306 View Code Duplication
        if (method_exists($definition, 'getFactory')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
307
            $this->assertEquals(['%doctrine.orm.entity_manager.class%', 'create'], $definition->getFactory());
308
        } else {
309
            $this->assertEquals('%doctrine.orm.entity_manager.class%', $definition->getFactoryClass());
0 ignored issues
show
Bug introduced by
The method getFactoryClass() does not exist on Symfony\Component\DependencyInjection\Definition. Did you maybe mean getFactory()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
310
            $this->assertEquals('create', $definition->getFactoryMethod());
0 ignored issues
show
Bug introduced by
The method getFactoryMethod() does not exist on Symfony\Component\DependencyInjection\Definition. Did you maybe mean getFactory()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
311
        }
312
313
        $this->assertEquals(['default' => 'doctrine.orm.default_entity_manager'], $container->getParameter('doctrine.entity_managers'), 'Set of the existing EntityManagers names is incorrect.');
314
        $this->assertEquals('%doctrine.entity_managers%', $container->getDefinition('doctrine')->getArgument(2), 'Set of the existing EntityManagers names is incorrect.');
315
316
        $arguments = $definition->getArguments();
317
        $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $arguments[0]);
318
        $this->assertEquals('doctrine.dbal.default_connection', (string) $arguments[0]);
319
        $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $arguments[1]);
320
        $this->assertEquals('doctrine.orm.default_configuration', (string) $arguments[1]);
321
322
        $definition = $container->getDefinition('doctrine.orm.default_configuration');
323
        $calls      = array_values($definition->getMethodCalls());
324
        $this->assertEquals(['YamlBundle' => 'Fixtures\Bundles\YamlBundle\Entity'], $calls[0][1][0]);
325
        $this->assertEquals('doctrine.orm.default_metadata_cache', (string) $calls[1][1][0]);
326
        $this->assertEquals('doctrine.orm.default_query_cache', (string) $calls[2][1][0]);
327
        $this->assertEquals('doctrine.orm.default_result_cache', (string) $calls[3][1][0]);
328
329
        if (version_compare(Version::VERSION, '2.3.0-DEV') >= 0) {
330
            $this->assertEquals('doctrine.orm.naming_strategy.default', (string) $calls[10][1][0]);
331
            $this->assertEquals('doctrine.orm.quote_strategy.default', (string) $calls[11][1][0]);
332
        }
333
        if (version_compare(Version::VERSION, '2.4.0-DEV') >= 0) {
334
            $this->assertEquals('doctrine.orm.default_entity_listener_resolver', (string) $calls[12][1][0]);
335
        }
336
337
        $definition = $container->getDefinition((string) $container->getAlias('doctrine.orm.default_metadata_cache'));
338
        $this->assertEquals('%doctrine_cache.array.class%', $definition->getClass());
339
340
        $definition = $container->getDefinition((string) $container->getAlias('doctrine.orm.default_query_cache'));
341
        $this->assertEquals('%doctrine_cache.array.class%', $definition->getClass());
342
343
        $definition = $container->getDefinition((string) $container->getAlias('doctrine.orm.default_result_cache'));
344
        $this->assertEquals('%doctrine_cache.array.class%', $definition->getClass());
345
    }
346
347
    public function testUseSavePointsAddMethodCallToAddSavepointsToTheConnection()
348
    {
349
        $container = $this->getContainer();
350
        $extension = new DoctrineExtension();
351
352
        $extension->load([[
353
        'dbal' => [
354
        'connections' => [
355
            'default' => ['password' => 'foo', 'use_savepoints' => true],
356
        ],
357
        ],
358
        ],
359
        ], $container);
360
361
        $calls = $container->getDefinition('doctrine.dbal.default_connection')->getMethodCalls();
362
        $this->assertCount(1, $calls);
363
        $this->assertEquals('setNestTransactionsWithSavepoints', $calls[0][0]);
364
        $this->assertTrue($calls[0][1][0]);
365
    }
366
367
    public function testAutoGenerateProxyClasses()
368
    {
369
        $container = $this->getContainer();
370
        $extension = new DoctrineExtension();
371
372
        $config = BundleConfigurationBuilder::createBuilder()
373
            ->addBaseConnection()
374
            ->addEntityManager([
375
                'proxy_namespace' => 'MyProxies',
376
                'auto_generate_proxy_classes' => 'eval',
377
                'default_entity_manager' => 'default',
378
                'entity_managers' => [
379
                    'default' => [
380
                        'mappings' => ['YamlBundle' => []],
381
                    ],
382
                ],
383
            ])
384
            ->build();
385
386
        $extension->load([$config], $container);
387
388
        $this->assertEquals(AbstractProxyFactory::AUTOGENERATE_EVAL, $container->getParameter('doctrine.orm.auto_generate_proxy_classes'));
389
    }
390
391
    public function testSingleEntityManagerWithDefaultConfiguration()
392
    {
393
        $container = $this->getContainer();
394
        $extension = new DoctrineExtension();
395
396
        $configurationArray = BundleConfigurationBuilder::createBuilderWithBaseValues()->build();
397
398
        $extension->load([$configurationArray], $container);
399
        $this->compileContainer($container);
400
401
        $definition = $container->getDefinition('doctrine.orm.default_entity_manager');
402
        $this->assertEquals('%doctrine.orm.entity_manager.class%', $definition->getClass());
403 View Code Duplication
        if (method_exists($definition, 'getFactory')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
404
            $this->assertEquals(['%doctrine.orm.entity_manager.class%', 'create'], $definition->getFactory());
405
        } else {
406
            $this->assertEquals('%doctrine.orm.entity_manager.class%', $definition->getFactoryClass());
0 ignored issues
show
Bug introduced by
The method getFactoryClass() does not exist on Symfony\Component\DependencyInjection\Definition. Did you maybe mean getFactory()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
407
            $this->assertEquals('create', $definition->getFactoryMethod());
0 ignored issues
show
Bug introduced by
The method getFactoryMethod() does not exist on Symfony\Component\DependencyInjection\Definition. Did you maybe mean getFactory()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
408
        }
409
410
        $this->assertDICConstructorArguments($definition, [
411
            new Reference('doctrine.dbal.default_connection'),
412
        new Reference('doctrine.orm.default_configuration'),
413
        ]);
414
    }
415
416
    public function testSingleEntityManagerWithDefaultSecondLevelCacheConfiguration()
417
    {
418
        if (version_compare(Version::VERSION, '2.5.0-DEV') < 0) {
419
            $this->markTestSkipped(sprintf('Second Level cache not supported by this version of the ORM : %s', Version::VERSION));
420
        }
421
        $container = $this->getContainer();
422
        $extension = new DoctrineExtension();
423
424
        $configurationArray = BundleConfigurationBuilder::createBuilderWithBaseValues()
425
            ->addBaseSecondLevelCache()
426
            ->build();
427
428
        $extension->load([$configurationArray], $container);
429
        $this->compileContainer($container);
430
431
        $definition = $container->getDefinition('doctrine.orm.default_entity_manager');
432
        $this->assertEquals('%doctrine.orm.entity_manager.class%', $definition->getClass());
433 View Code Duplication
        if (method_exists($definition, 'getFactory')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
434
            $this->assertEquals(['%doctrine.orm.entity_manager.class%', 'create'], $definition->getFactory());
435
        } else {
436
            $this->assertEquals('%doctrine.orm.entity_manager.class%', $definition->getFactoryClass());
0 ignored issues
show
Bug introduced by
The method getFactoryClass() does not exist on Symfony\Component\DependencyInjection\Definition. Did you maybe mean getFactory()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
437
            $this->assertEquals('create', $definition->getFactoryMethod());
0 ignored issues
show
Bug introduced by
The method getFactoryMethod() does not exist on Symfony\Component\DependencyInjection\Definition. Did you maybe mean getFactory()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
438
        }
439
440
        $this->assertDICConstructorArguments($definition, [
441
            new Reference('doctrine.dbal.default_connection'),
442
        new Reference('doctrine.orm.default_configuration'),
443
        ]);
444
445
        $slcDefinition = $container->getDefinition('doctrine.orm.default_second_level_cache.default_cache_factory');
446
        $this->assertEquals('%doctrine.orm.second_level_cache.default_cache_factory.class%', $slcDefinition->getClass());
447
    }
448
449
    public function testSingleEntityManagerWithCustomSecondLevelCacheConfiguration()
450
    {
451
        if (version_compare(Version::VERSION, '2.5.0-DEV') < 0) {
452
            $this->markTestSkipped(sprintf('Second Level cache not supported by this version of the ORM : %s', Version::VERSION));
453
        }
454
        $container = $this->getContainer();
455
        $extension = new DoctrineExtension();
456
457
        $configurationArray = BundleConfigurationBuilder::createBuilderWithBaseValues()
458
            ->addSecondLevelCache([
459
                'region_cache_driver' => ['type' => 'memcache'],
460
                'regions' => [
461
                    'hour_region' => ['lifetime' => 3600],
462
                ],
463
                'factory' => 'YamlBundle\Cache\MyCacheFactory',
464
            ])
465
            ->build();
466
467
        $extension->load([$configurationArray], $container);
468
        $this->compileContainer($container);
469
470
        $definition = $container->getDefinition('doctrine.orm.default_entity_manager');
471
        $this->assertEquals('%doctrine.orm.entity_manager.class%', $definition->getClass());
472 View Code Duplication
        if (method_exists($definition, 'getFactory')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
473
            $this->assertEquals(['%doctrine.orm.entity_manager.class%', 'create'], $definition->getFactory());
474
        } else {
475
            $this->assertEquals('%doctrine.orm.entity_manager.class%', $definition->getFactoryClass());
0 ignored issues
show
Bug introduced by
The method getFactoryClass() does not exist on Symfony\Component\DependencyInjection\Definition. Did you maybe mean getFactory()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
476
            $this->assertEquals('create', $definition->getFactoryMethod());
0 ignored issues
show
Bug introduced by
The method getFactoryMethod() does not exist on Symfony\Component\DependencyInjection\Definition. Did you maybe mean getFactory()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
477
        }
478
479
        $this->assertDICConstructorArguments($definition, [
480
            new Reference('doctrine.dbal.default_connection'),
481
        new Reference('doctrine.orm.default_configuration'),
482
        ]);
483
484
        $slcDefinition = $container->getDefinition('doctrine.orm.default_second_level_cache.default_cache_factory');
485
        $this->assertEquals('YamlBundle\Cache\MyCacheFactory', $slcDefinition->getClass());
486
    }
487
488 View Code Duplication
    public function testBundleEntityAliases()
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' => []]]]];
497
        $extension->load([$config], $container);
498
499
        $definition = $container->getDefinition('doctrine.orm.default_configuration');
500
        $this->assertDICDefinitionMethodCallOnce(
501
            $definition,
502
            'setEntityNamespaces',
503
            [['YamlBundle' => 'Fixtures\Bundles\YamlBundle\Entity']]
504
        );
505
    }
506
507 View Code Duplication
    public function testOverwriteEntityAliases()
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...
508
    {
509
        $container = $this->getContainer();
510
        $extension = new DoctrineExtension();
511
512
        $config        = BundleConfigurationBuilder::createBuilder()
513
             ->addBaseConnection()
514
             ->build();
515
        $config['orm'] = ['default_entity_manager' => 'default', 'entity_managers' => ['default' => ['mappings' => ['YamlBundle' => ['alias' => 'yml']]]]];
516
        $extension->load([$config], $container);
517
518
        $definition = $container->getDefinition('doctrine.orm.default_configuration');
519
        $this->assertDICDefinitionMethodCallOnce(
520
            $definition,
521
            'setEntityNamespaces',
522
            [['yml' => 'Fixtures\Bundles\YamlBundle\Entity']]
523
        );
524
    }
525
526
    public function testYamlBundleMappingDetection()
527
    {
528
        $container = $this->getContainer('YamlBundle');
529
        $extension = new DoctrineExtension();
530
531
        $config = BundleConfigurationBuilder::createBuilder()
532
            ->addBaseConnection()
533
            ->addBaseEntityManager()
534
            ->build();
535
        $extension->load([$config], $container);
536
537
        $definition = $container->getDefinition('doctrine.orm.default_metadata_driver');
538
        $this->assertDICDefinitionMethodCallOnce($definition, 'addDriver', [
539
            new Reference('doctrine.orm.default_yml_metadata_driver'),
540
            'Fixtures\Bundles\YamlBundle\Entity',
541
        ]);
542
    }
543
544 View Code Duplication
    public function testXmlBundleMappingDetection()
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...
545
    {
546
        $container = $this->getContainer('XmlBundle');
547
        $extension = new DoctrineExtension();
548
549
        $config = BundleConfigurationBuilder::createBuilder()
550
            ->addBaseConnection()
551
            ->addEntityManager([
552
                'default_entity_manager' => 'default',
553
                'entity_managers' => [
554
                    'default' => [
555
                        'mappings' => [
556
                            'XmlBundle' => [],
557
                        ],
558
                    ],
559
                ],
560
            ])
561
            ->build();
562
        $extension->load([$config], $container);
563
564
        $definition = $container->getDefinition('doctrine.orm.default_metadata_driver');
565
        $this->assertDICDefinitionMethodCallOnce($definition, 'addDriver', [
566
            new Reference('doctrine.orm.default_xml_metadata_driver'),
567
            'Fixtures\Bundles\XmlBundle\Entity',
568
        ]);
569
    }
570
571 View Code Duplication
    public function testAnnotationsBundleMappingDetection()
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...
572
    {
573
        $container = $this->getContainer('AnnotationsBundle');
574
        $extension = new DoctrineExtension();
575
576
        $config = BundleConfigurationBuilder::createBuilder()
577
            ->addBaseConnection()
578
            ->addEntityManager([
579
                'default_entity_manager' => 'default',
580
                'entity_managers' => [
581
                    'default' => [
582
                        'mappings' => [
583
                            'AnnotationsBundle' => [],
584
                        ],
585
                    ],
586
                ],
587
            ])
588
            ->build();
589
        $extension->load([$config], $container);
590
591
        $definition = $container->getDefinition('doctrine.orm.default_metadata_driver');
592
        $this->assertDICDefinitionMethodCallOnce($definition, 'addDriver', [
593
            new Reference('doctrine.orm.default_annotation_metadata_driver'),
594
            'Fixtures\Bundles\AnnotationsBundle\Entity',
595
        ]);
596
    }
597
598
    public function testOrmMergeConfigs()
599
    {
600
        $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...
601
        $extension = new DoctrineExtension();
602
603
        $config1 = BundleConfigurationBuilder::createBuilder()
604
            ->addBaseConnection()
605
            ->addEntityManager([
606
                'auto_generate_proxy_classes' => true,
607
                'default_entity_manager' => 'default',
608
                'entity_managers' => [
609
                    'default' => [
610
                        'mappings' => [
611
                            'AnnotationsBundle' => [],
612
                        ],
613
                    ],
614
                ],
615
            ])
616
            ->build();
617
        $config2 = BundleConfigurationBuilder::createBuilder()
618
            ->addBaseConnection()
619
            ->addEntityManager([
620
                'auto_generate_proxy_classes' => false,
621
                'default_entity_manager' => 'default',
622
                'entity_managers' => [
623
                    'default' => [
624
                        'mappings' => [
625
                            'XmlBundle' => [],
626
                        ],
627
                    ],
628
                ],
629
            ])
630
            ->build();
631
        $extension->load([$config1, $config2], $container);
632
633
        $definition = $container->getDefinition('doctrine.orm.default_metadata_driver');
634
        $this->assertDICDefinitionMethodCallAt(0, $definition, 'addDriver', [
635
            new Reference('doctrine.orm.default_annotation_metadata_driver'),
636
            'Fixtures\Bundles\AnnotationsBundle\Entity',
637
        ]);
638
        $this->assertDICDefinitionMethodCallAt(1, $definition, 'addDriver', [
639
            new Reference('doctrine.orm.default_xml_metadata_driver'),
640
            'Fixtures\Bundles\XmlBundle\Entity',
641
        ]);
642
643
        $configDef = $container->getDefinition('doctrine.orm.default_configuration');
644
        $this->assertDICDefinitionMethodCallOnce($configDef, 'setAutoGenerateProxyClasses');
645
646
        $calls = $configDef->getMethodCalls();
647
        foreach ($calls as $call) {
648
            if ($call[0] === 'setAutoGenerateProxyClasses') {
649
                $this->assertFalse($container->getParameterBag()->resolveValue($call[1][0]));
650
                break;
651
            }
652
        }
653
    }
654
655
    public function testAnnotationsBundleMappingDetectionWithVendorNamespace()
656
    {
657
        $container = $this->getContainer('AnnotationsBundle', 'Vendor');
658
        $extension = new DoctrineExtension();
659
660
        $config = BundleConfigurationBuilder::createBuilder()
661
            ->addBaseConnection()
662
            ->addEntityManager([
663
                'default_entity_manager' => 'default',
664
                'entity_managers' => [
665
                    'default' => [
666
                        'mappings' => [
667
                            'AnnotationsBundle' => [],
668
                        ],
669
                    ],
670
                ],
671
            ])
672
            ->build();
673
        $extension->load([$config], $container);
674
675
        $calls = $container->getDefinition('doctrine.orm.default_metadata_driver')->getMethodCalls();
676
        $this->assertEquals('doctrine.orm.default_annotation_metadata_driver', (string) $calls[0][1][0]);
677
        $this->assertEquals('Fixtures\Bundles\Vendor\AnnotationsBundle\Entity', $calls[0][1][1]);
678
    }
679
680
    public function testMessengerIntegration()
681
    {
682
        if (! interface_exists(MessageBusInterface::class)) {
683
            $this->markTestSkipped('Symfony Messenger component is not installed');
684
        }
685
686
        $container = $this->getContainer();
687
        $extension = new DoctrineExtension();
688
689
        $config = BundleConfigurationBuilder::createBuilder()
690
            ->addBaseConnection()
691
            ->addEntityManager([
692
                'default_entity_manager' => 'default',
693
                'entity_managers' => [
694
                    'default' => [],
695
                ],
696
            ])
697
            ->build();
698
        $extension->load([$config], $container);
699
700
        $this->assertNotNull($container->getDefinition('doctrine.orm.messenger.middleware_factory.transaction'));
701
        $this->assertNotNull($middlewarePrototype = $container->getDefinition('messenger.middleware.doctrine_transaction_middleware'));
702
        $this->assertSame('default', $middlewarePrototype->getArgument(0));
703
    }
704
705
    public function testCacheConfiguration()
706
    {
707
        $container = $this->getContainer();
708
        $extension = new DoctrineExtension();
709
710
        $config = BundleConfigurationBuilder::createBuilder()
711
             ->addBaseConnection()
712
             ->addEntityManager([
713
                 'metadata_cache_driver' => ['cache_provider' => 'metadata_cache'],
714
                 'query_cache_driver' => ['cache_provider' => 'query_cache'],
715
                 'result_cache_driver' => ['cache_provider' => 'result_cache'],
716
             ])
717
            ->build();
718
719
        $extension->load([$config], $container);
720
721
        $this->assertTrue($container->hasAlias('doctrine.orm.default_metadata_cache'));
722
        $alias = $container->getAlias('doctrine.orm.default_metadata_cache');
723
        $this->assertEquals('doctrine_cache.providers.metadata_cache', (string) $alias);
724
725
        $this->assertTrue($container->hasAlias('doctrine.orm.default_query_cache'));
726
        $alias = $container->getAlias('doctrine.orm.default_query_cache');
727
        $this->assertEquals('doctrine_cache.providers.query_cache', (string) $alias);
728
729
        $this->assertTrue($container->hasAlias('doctrine.orm.default_result_cache'));
730
        $alias = $container->getAlias('doctrine.orm.default_result_cache');
731
        $this->assertEquals('doctrine_cache.providers.result_cache', (string) $alias);
732
    }
733
734
    public function testShardManager()
735
    {
736
        $container = $this->getContainer();
737
        $extension = new DoctrineExtension();
738
739
        $config = BundleConfigurationBuilder::createBuilder()
740
             ->addConnection([
741
                 'connections' => [
742
                     'foo' => [
743
                         'shards' => [
744
                             'test' => ['id' => 1],
745
                         ],
746
                     ],
747
                     'bar' => [],
748
                 ],
749
             ])
750
            ->build();
751
752
        $extension->load([$config], $container);
753
754
        $this->assertTrue($container->hasDefinition('doctrine.dbal.foo_shard_manager'));
755
        $this->assertFalse($container->hasDefinition('doctrine.dbal.bar_shard_manager'));
756
    }
757
758
    private function getContainer($bundles = 'YamlBundle', $vendor = null)
759
    {
760
        $bundles = (array) $bundles;
761
762
        $map = [];
763
        foreach ($bundles as $bundle) {
764
            require_once __DIR__ . '/Fixtures/Bundles/' . ($vendor ? $vendor . '/' : '') . $bundle . '/' . $bundle . '.php';
765
766
            $map[$bundle] = 'Fixtures\\Bundles\\' . ($vendor ? $vendor . '\\' : '') . $bundle . '\\' . $bundle;
767
        }
768
769
        return new ContainerBuilder(new ParameterBag([
770
            'kernel.name' => 'app',
771
            'kernel.debug' => false,
772
            'kernel.bundles' => $map,
773
            'kernel.cache_dir' => sys_get_temp_dir(),
774
            'kernel.environment' => 'test',
775
            'kernel.root_dir' => __DIR__ . '/../../', // src dir
776
        ]));
777
    }
778
779
    private function assertDICConstructorArguments(Definition $definition, array $args)
780
    {
781
        $this->assertEquals($args, $definition->getArguments(), "Expected and actual DIC Service constructor arguments of definition '" . $definition->getClass() . "' don't match.");
782
    }
783
784 View Code Duplication
    private function assertDICDefinitionMethodCallAt($pos, Definition $definition, $methodName, array $params = null)
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...
785
    {
786
        $calls = $definition->getMethodCalls();
787
        if (! isset($calls[$pos][0])) {
788
            return;
789
        }
790
791
        $this->assertEquals($methodName, $calls[$pos][0], "Method '" . $methodName . "' is expected to be called at position " . $pos . '.');
792
793
        if ($params === null) {
794
            return;
795
        }
796
797
        $this->assertEquals($params, $calls[$pos][1], "Expected parameters to methods '" . $methodName . "' do not match the actual parameters.");
798
    }
799
800
    /**
801
     * Assertion for the DI Container, check if the given definition contains a method call with the given parameters.
802
     *
803
     * @param string     $methodName
804
     * @param array|null $params
805
     */
806 View Code Duplication
    private function assertDICDefinitionMethodCallOnce(Definition $definition, $methodName, array $params = null)
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...
807
    {
808
        $calls  = $definition->getMethodCalls();
809
        $called = false;
810
        foreach ($calls as $call) {
811
            if ($call[0] !== $methodName) {
812
                continue;
813
            }
814
815
            if ($called) {
816
                $this->fail("Method '" . $methodName . "' is expected to be called only once, a second call was registered though.");
817
            } else {
818
                $called = true;
819
                if ($params !== null) {
820
                    $this->assertEquals($params, $call[1], "Expected parameters to methods '" . $methodName . "' do not match the actual parameters.");
821
                }
822
            }
823
        }
824
        if ($called) {
825
            return;
826
        }
827
828
        $this->fail("Method '" . $methodName . "' is expected to be called once, definition does not contain a call though.");
829
    }
830
831
    private function compileContainer(ContainerBuilder $container)
832
    {
833
        $container->getCompilerPassConfig()->setOptimizationPasses([class_exists(ResolveChildDefinitionsPass::class) ? new ResolveChildDefinitionsPass() : new ResolveDefinitionTemplatesPass()]);
0 ignored issues
show
Documentation introduced by
array(class_exists(\Symf...initionTemplatesPass()) is of type array<integer,object<Sym...nitionTemplatesPass>"}>, but the function expects a array<integer,object<Sym...CompilerPassInterface>>.

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...
834
        $container->getCompilerPassConfig()->setRemovingPasses([]);
835
        $container->compile();
836
    }
837
}
838
839
class TestWrapperClass extends Connection
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
840
{
841
}
842