Completed
Pull Request — master (#905)
by Gabriel
01:56
created

DoctrineExtensionTest   C

Complexity

Total Complexity 54

Size/Duplication

Total Lines 814
Duplicated Lines 18.06 %

Coupling/Cohesion

Components 1
Dependencies 11

Importance

Changes 0
Metric Value
wmc 54
lcom 1
cbo 11
dl 147
loc 814
rs 6.266
c 0
b 0
f 0

30 Methods

Rating   Name   Duplication   Size   Complexity  
A testAutowiringAlias() 0 24 2
A testPublicServicesAndAliases() 0 12 1
A testDbalGenerateDefaultConnectionConfiguration() 0 19 1
A testDbalOverrideDefaultConnection() 0 13 1
A testOrmRequiresDbal() 0 6 1
A getAutomappingConfigurations() 0 34 1
A testAutomapping() 0 52 2
A testDbalLoad() 0 17 1
A testDbalWrapperClass() 0 25 1
B testDependencyInjectionConfigurationDefaults() 6 103 4
A testUseSavePointsAddMethodCallToAddSavepointsToTheConnection() 0 19 1
A testAutoGenerateProxyClasses() 0 23 1
A testSingleEntityManagerWithDefaultConfiguration() 6 24 2
A testSingleEntityManagerWithDefaultSecondLevelCacheConfiguration() 6 32 3
A testSingleEntityManagerWithCustomSecondLevelCacheConfiguration() 6 38 3
A testBundleEntityAliases() 16 18 1
A testOverwriteEntityAliases() 16 18 1
A testYamlBundleMappingDetection() 0 17 1
A testXmlBundleMappingDetection() 26 26 1
A testAnnotationsBundleMappingDetection() 26 26 1
B testOrmMergeConfigs() 0 56 3
A testAnnotationsBundleMappingDetectionWithVendorNamespace() 0 24 1
A testMessengerIntegration() 0 23 2
A testCacheConfiguration() 0 28 1
A testShardManager() 0 23 1
A getContainer() 0 20 4
A assertDICConstructorArguments() 0 4 1
A assertDICDefinitionMethodCallAt() 15 15 3
B assertDICDefinitionMethodCallOnce() 24 24 6
A compileContainer() 0 6 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like DoctrineExtensionTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use DoctrineExtensionTest, and based on these observations, apply Extract Interface, too.

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($middlewarePrototype = $container->getDefinition('messenger.middleware.doctrine_transaction'));
701
        $this->assertCount(1, $middlewarePrototype->getArguments());
702
    }
703
704
    public function testCacheConfiguration()
705
    {
706
        $container = $this->getContainer();
707
        $extension = new DoctrineExtension();
708
709
        $config = BundleConfigurationBuilder::createBuilder()
710
             ->addBaseConnection()
711
             ->addEntityManager([
712
                 'metadata_cache_driver' => ['cache_provider' => 'metadata_cache'],
713
                 'query_cache_driver' => ['cache_provider' => 'query_cache'],
714
                 'result_cache_driver' => ['cache_provider' => 'result_cache'],
715
             ])
716
            ->build();
717
718
        $extension->load([$config], $container);
719
720
        $this->assertTrue($container->hasAlias('doctrine.orm.default_metadata_cache'));
721
        $alias = $container->getAlias('doctrine.orm.default_metadata_cache');
722
        $this->assertEquals('doctrine_cache.providers.metadata_cache', (string) $alias);
723
724
        $this->assertTrue($container->hasAlias('doctrine.orm.default_query_cache'));
725
        $alias = $container->getAlias('doctrine.orm.default_query_cache');
726
        $this->assertEquals('doctrine_cache.providers.query_cache', (string) $alias);
727
728
        $this->assertTrue($container->hasAlias('doctrine.orm.default_result_cache'));
729
        $alias = $container->getAlias('doctrine.orm.default_result_cache');
730
        $this->assertEquals('doctrine_cache.providers.result_cache', (string) $alias);
731
    }
732
733
    public function testShardManager()
734
    {
735
        $container = $this->getContainer();
736
        $extension = new DoctrineExtension();
737
738
        $config = BundleConfigurationBuilder::createBuilder()
739
             ->addConnection([
740
                 'connections' => [
741
                     'foo' => [
742
                         'shards' => [
743
                             'test' => ['id' => 1],
744
                         ],
745
                     ],
746
                     'bar' => [],
747
                 ],
748
             ])
749
            ->build();
750
751
        $extension->load([$config], $container);
752
753
        $this->assertTrue($container->hasDefinition('doctrine.dbal.foo_shard_manager'));
754
        $this->assertFalse($container->hasDefinition('doctrine.dbal.bar_shard_manager'));
755
    }
756
757
    private function getContainer($bundles = 'YamlBundle', $vendor = null)
758
    {
759
        $bundles = (array) $bundles;
760
761
        $map = [];
762
        foreach ($bundles as $bundle) {
763
            require_once __DIR__ . '/Fixtures/Bundles/' . ($vendor ? $vendor . '/' : '') . $bundle . '/' . $bundle . '.php';
764
765
            $map[$bundle] = 'Fixtures\\Bundles\\' . ($vendor ? $vendor . '\\' : '') . $bundle . '\\' . $bundle;
766
        }
767
768
        return new ContainerBuilder(new ParameterBag([
769
            'kernel.name' => 'app',
770
            'kernel.debug' => false,
771
            'kernel.bundles' => $map,
772
            'kernel.cache_dir' => sys_get_temp_dir(),
773
            'kernel.environment' => 'test',
774
            'kernel.root_dir' => __DIR__ . '/../../', // src dir
775
        ]));
776
    }
777
778
    private function assertDICConstructorArguments(Definition $definition, array $args)
779
    {
780
        $this->assertEquals($args, $definition->getArguments(), "Expected and actual DIC Service constructor arguments of definition '" . $definition->getClass() . "' don't match.");
781
    }
782
783 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...
784
    {
785
        $calls = $definition->getMethodCalls();
786
        if (! isset($calls[$pos][0])) {
787
            return;
788
        }
789
790
        $this->assertEquals($methodName, $calls[$pos][0], "Method '" . $methodName . "' is expected to be called at position " . $pos . '.');
791
792
        if ($params === null) {
793
            return;
794
        }
795
796
        $this->assertEquals($params, $calls[$pos][1], "Expected parameters to methods '" . $methodName . "' do not match the actual parameters.");
797
    }
798
799
    /**
800
     * Assertion for the DI Container, check if the given definition contains a method call with the given parameters.
801
     *
802
     * @param string     $methodName
803
     * @param array|null $params
804
     */
805 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...
806
    {
807
        $calls  = $definition->getMethodCalls();
808
        $called = false;
809
        foreach ($calls as $call) {
810
            if ($call[0] !== $methodName) {
811
                continue;
812
            }
813
814
            if ($called) {
815
                $this->fail("Method '" . $methodName . "' is expected to be called only once, a second call was registered though.");
816
            } else {
817
                $called = true;
818
                if ($params !== null) {
819
                    $this->assertEquals($params, $call[1], "Expected parameters to methods '" . $methodName . "' do not match the actual parameters.");
820
                }
821
            }
822
        }
823
        if ($called) {
824
            return;
825
        }
826
827
        $this->fail("Method '" . $methodName . "' is expected to be called once, definition does not contain a call though.");
828
    }
829
830
    private function compileContainer(ContainerBuilder $container)
831
    {
832
        $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...
833
        $container->getCompilerPassConfig()->setRemovingPasses([]);
834
        $container->compile();
835
    }
836
}
837
838
class TestWrapperClass extends Connection
839
{
840
}
841