Completed
Push — master ( e56cb3...ac31f3 )
by Andreas
01:49 queued 11s
created

testAbstractEntityListener()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11

Duplication

Lines 11
Ratio 100 %

Importance

Changes 0
Metric Value
dl 11
loc 11
rs 9.9
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Doctrine\Bundle\DoctrineBundle\Tests\DependencyInjection;
4
5
use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\DbalSchemaFilterPass;
6
use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\EntityListenerPass;
7
use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\WellKnownSchemaFilterPass;
8
use Doctrine\Bundle\DoctrineBundle\DependencyInjection\DoctrineExtension;
9
use Doctrine\DBAL\Configuration;
10
use Doctrine\DBAL\Schema\AbstractAsset;
11
use Doctrine\ORM\EntityManager;
12
use PHPUnit\Framework\TestCase;
13
use Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass\RegisterEventListenersAndSubscribersPass;
14
use Symfony\Component\Cache\Adapter\ArrayAdapter;
15
use Symfony\Component\Cache\DoctrineProvider;
16
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
17
use Symfony\Component\DependencyInjection\Compiler\ResolveChildDefinitionsPass;
18
use Symfony\Component\DependencyInjection\ContainerBuilder;
19
use Symfony\Component\DependencyInjection\Definition;
20
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
21
use Symfony\Component\DependencyInjection\Reference;
22
use Symfony\Component\DependencyInjection\ServiceLocator;
23
24
abstract class AbstractDoctrineExtensionTest extends TestCase
25
{
26
    abstract protected function loadFromFile(ContainerBuilder $container, string $file) : void;
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
27
28
    public function testDbalLoadFromXmlMultipleConnections() : void
29
    {
30
        $container = $this->loadContainer('dbal_service_multiple_connections');
31
32
        // doctrine.dbal.mysql_connection
33
        $config = $container->getDefinition('doctrine.dbal.mysql_connection')->getArgument(0);
34
35
        $this->assertEquals('mysql_s3cr3t', $config['password']);
36
        $this->assertEquals('mysql_user', $config['user']);
37
        $this->assertEquals('mysql_db', $config['dbname']);
38
        $this->assertEquals('/path/to/mysqld.sock', $config['unix_socket']);
39
40
        // doctrine.dbal.sqlite_connection
41
        $config = $container->getDefinition('doctrine.dbal.sqlite_connection')->getArgument(0);
42
        $this->assertSame('pdo_sqlite', $config['driver']);
43
        $this->assertSame('sqlite_db', $config['dbname']);
44
        $this->assertSame('sqlite_user', $config['user']);
45
        $this->assertSame('sqlite_s3cr3t', $config['password']);
46
        $this->assertSame('/tmp/db.sqlite', $config['path']);
47
        $this->assertTrue($config['memory']);
48
        $this->assertSame(['asin' => ['callback' => 'asin', 'numArgs' => 1]], $config['driverOptions']['userDefinedFunctions']);
49
        $this->assertSame('foo', $config['driverOptions']['arbitraryValue']);
50
51
        // doctrine.dbal.oci8_connection
52
        $config = $container->getDefinition('doctrine.dbal.oci_connection')->getArgument(0);
53
        $this->assertSame('oci8', $config['driver']);
54
        $this->assertSame('oracle_db', $config['dbname']);
55
        $this->assertSame('oracle_user', $config['user']);
56
        $this->assertSame('oracle_s3cr3t', $config['password']);
57
        $this->assertSame('oracle_service', $config['servicename']);
58
        $this->assertTrue($config['service']);
59
        $this->assertTrue($config['pooled']);
60
        $this->assertSame('utf8', $config['charset']);
61
62
        // doctrine.dbal.ibmdb2_connection
63
        $config = $container->getDefinition('doctrine.dbal.ibmdb2_connection')->getArgument(0);
64
        $this->assertSame('ibm_db2', $config['driver']);
65
        $this->assertSame('ibmdb2_db', $config['dbname']);
66
        $this->assertSame('ibmdb2_user', $config['user']);
67
        $this->assertSame('ibmdb2_s3cr3t', $config['password']);
68
        $this->assertSame('TCPIP', $config['protocol']);
69
70
        // doctrine.dbal.pgsql_connection
71
        $config = $container->getDefinition('doctrine.dbal.pgsql_connection')->getArgument(0);
72
        $this->assertSame('pdo_pgsql', $config['driver']);
73
        $this->assertSame('pgsql_schema', $config['dbname']);
74
        $this->assertSame('pgsql_user', $config['user']);
75
        $this->assertSame('pgsql_s3cr3t', $config['password']);
76
        $this->assertSame('pgsql_db', $config['default_dbname']);
77
        $this->assertSame('require', $config['sslmode']);
78
        $this->assertSame('postgresql-ca.pem', $config['sslrootcert']);
79
        $this->assertSame('postgresql-cert.pem', $config['sslcert']);
80
        $this->assertSame('postgresql-key.pem', $config['sslkey']);
81
        $this->assertSame('postgresql.crl', $config['sslcrl']);
82
        $this->assertSame('utf8', $config['charset']);
83
84
        // doctrine.dbal.sqlanywhere_connection
85
        $config = $container->getDefinition('doctrine.dbal.sqlanywhere_connection')->getArgument(0);
86
        $this->assertSame('sqlanywhere', $config['driver']);
87
        $this->assertSame('localhost', $config['host']);
88
        $this->assertSame(2683, $config['port']);
89
        $this->assertSame('sqlanywhere_server', $config['server']);
90
        $this->assertSame('sqlanywhere_db', $config['dbname']);
91
        $this->assertSame('sqlanywhere_user', $config['user']);
92
        $this->assertSame('sqlanywhere_s3cr3t', $config['password']);
93
        $this->assertTrue($config['persistent']);
94
        $this->assertSame('utf8', $config['charset']);
95
    }
96
97
    public function testDbalLoadFromXmlSingleConnections() : void
98
    {
99
        $container = $this->loadContainer('dbal_service_single_connection');
100
101
        // doctrine.dbal.mysql_connection
102
        $config = $container->getDefinition('doctrine.dbal.default_connection')->getArgument(0);
103
104
        $this->assertEquals('mysql_s3cr3t', $config['password']);
105
        $this->assertEquals('mysql_user', $config['user']);
106
        $this->assertEquals('mysql_db', $config['dbname']);
107
        $this->assertEquals('/path/to/mysqld.sock', $config['unix_socket']);
108
        $this->assertEquals('5.6.20', $config['serverVersion']);
109
    }
110
111
    public function testDbalLoadSingleMasterSlaveConnection() : void
112
    {
113
        $container = $this->loadContainer('dbal_service_single_master_slave_connection');
114
115
        // doctrine.dbal.mysql_connection
116
        $param = $container->getDefinition('doctrine.dbal.default_connection')->getArgument(0);
117
118
        $this->assertEquals('Doctrine\\DBAL\\Connections\\MasterSlaveConnection', $param['wrapperClass']);
119
        $this->assertTrue($param['keepSlave']);
120
        $this->assertEquals(
121
            [
122
                'user' => 'mysql_user',
123
                'password' => 'mysql_s3cr3t',
124
                'port' => null,
125
                'dbname' => 'mysql_db',
126
                'host' => 'localhost',
127
                'unix_socket' => '/path/to/mysqld.sock',
128
            ],
129
            $param['master']
130
        );
131
        $this->assertEquals(
132
            [
133
                'user' => 'slave_user',
134
                'password' => 'slave_s3cr3t',
135
                'port' => null,
136
                'dbname' => 'slave_db',
137
                'host' => 'localhost',
138
                'unix_socket' => '/path/to/mysqld_slave.sock',
139
            ],
140
            $param['slaves']['slave1']
141
        );
142
        $this->assertEquals(['engine' => 'InnoDB'], $param['defaultTableOptions']);
143
    }
144
145
    public function testDbalLoadPoolShardingConnection() : void
146
    {
147
        $container = $this->loadContainer('dbal_service_pool_sharding_connection');
148
149
        // doctrine.dbal.mysql_connection
150
        $param = $container->getDefinition('doctrine.dbal.default_connection')->getArgument(0);
151
152
        $this->assertEquals('Doctrine\\DBAL\\Sharding\\PoolingShardConnection', $param['wrapperClass']);
153
        $this->assertEquals(new Reference('foo.shard_choser'), $param['shardChoser']);
154
        $this->assertEquals(
155
            [
156
                'user' => 'mysql_user',
157
                'password' => 'mysql_s3cr3t',
158
                'port' => null,
159
                'dbname' => 'mysql_db',
160
                'host' => 'localhost',
161
                'unix_socket' => '/path/to/mysqld.sock',
162
            ],
163
            $param['global']
164
        );
165
        $this->assertEquals(
166
            [
167
                'user' => 'shard_user',
168
                'password' => 'shard_s3cr3t',
169
                'port' => null,
170
                'dbname' => 'shard_db',
171
                'host' => 'localhost',
172
                'unix_socket' => '/path/to/mysqld_shard.sock',
173
                'id' => 1,
174
            ],
175
            $param['shards'][0]
176
        );
177
        $this->assertEquals(['engine' => 'InnoDB'], $param['defaultTableOptions']);
178
    }
179
180
    public function testDbalLoadSavepointsForNestedTransactions() : void
181
    {
182
        $container = $this->loadContainer('dbal_savepoints');
183
184
        $calls = $container->getDefinition('doctrine.dbal.savepoints_connection')->getMethodCalls();
185
        $this->assertCount(1, $calls);
0 ignored issues
show
Documentation introduced by
$calls is of type array, but the function expects a object<Countable>|object...nit\Framework\iterable>.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
186
        $this->assertEquals('setNestTransactionsWithSavepoints', $calls[0][0]);
187
        $this->assertTrue($calls[0][1][0]);
188
189
        $calls = $container->getDefinition('doctrine.dbal.nosavepoints_connection')->getMethodCalls();
190
        $this->assertCount(0, $calls);
0 ignored issues
show
Documentation introduced by
$calls is of type array, but the function expects a object<Countable>|object...nit\Framework\iterable>.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
191
192
        $calls = $container->getDefinition('doctrine.dbal.notset_connection')->getMethodCalls();
193
        $this->assertCount(0, $calls);
0 ignored issues
show
Documentation introduced by
$calls is of type array, but the function expects a object<Countable>|object...nit\Framework\iterable>.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
194
    }
195
196
    public function testLoadSimpleSingleConnection() : void
197
    {
198
        $container = $this->loadContainer('orm_service_simple_single_entity_manager');
199
200
        $definition = $container->getDefinition('doctrine.dbal.default_connection');
201
202
        $this->assertDICConstructorArguments($definition, [
203
            [
204
                'dbname' => 'db',
205
                'host' => 'localhost',
206
                'port' => null,
207
                'user' => 'root',
208
                'password' => null,
209
                'driver' => 'pdo_mysql',
210
                'driverOptions' => [],
211
                'defaultTableOptions' => [],
212
            ],
213
            new Reference('doctrine.dbal.default_connection.configuration'),
214
            new Reference('doctrine.dbal.default_connection.event_manager'),
215
            [],
216
        ]);
217
218
        $definition = $container->getDefinition('doctrine.orm.default_entity_manager');
219
        $this->assertEquals('%doctrine.orm.entity_manager.class%', $definition->getClass());
220
        $this->assertEquals(['%doctrine.orm.entity_manager.class%', 'create'], $definition->getFactory());
221
222
        $this->assertDICConstructorArguments($definition, [
223
            new Reference('doctrine.dbal.default_connection'),
224
            new Reference('doctrine.orm.default_configuration'),
225
        ]);
226
    }
227
228
    /**
229
     * The PDO driver doesn't require a database name to be to set when connecting to a database server
230
     */
231
    public function testLoadSimpleSingleConnectionWithoutDbName() : void
232
    {
233
        $container = $this->loadContainer('orm_service_simple_single_entity_manager_without_dbname');
234
235
        /** @var Definition $definition */
236
        $definition = $container->getDefinition('doctrine.dbal.default_connection');
237
238
        $this->assertDICConstructorArguments($definition, [
239
            [
240
                'host' => 'localhost',
241
                'port' => null,
242
                'user' => 'root',
243
                'password' => null,
244
                'driver' => 'pdo_mysql',
245
                'driverOptions' => [],
246
                'defaultTableOptions' => [],
247
            ],
248
            new Reference('doctrine.dbal.default_connection.configuration'),
249
            new Reference('doctrine.dbal.default_connection.event_manager'),
250
            [],
251
        ]);
252
253
        $definition = $container->getDefinition('doctrine.orm.default_entity_manager');
254
        $this->assertEquals('%doctrine.orm.entity_manager.class%', $definition->getClass());
255
        $factory = $definition->getFactory();
256
257
        $this->assertEquals('%doctrine.orm.entity_manager.class%', $factory[0]);
258
        $this->assertEquals('create', $factory[1]);
259
260
        $this->assertDICConstructorArguments($definition, [
261
            new Reference('doctrine.dbal.default_connection'),
262
            new Reference('doctrine.orm.default_configuration'),
263
        ]);
264
    }
265
266
    public function testLoadSingleConnection() : void
267
    {
268
        $container = $this->loadContainer('orm_service_single_entity_manager');
269
270
        $definition = $container->getDefinition('doctrine.dbal.default_connection');
271
272
        $this->assertDICConstructorArguments($definition, [
273
            [
274
                'host' => 'localhost',
275
                'driver' => 'pdo_sqlite',
276
                'driverOptions' => [],
277
                'user' => 'sqlite_user',
278
                'port' => null,
279
                'password' => 'sqlite_s3cr3t',
280
                'dbname' => 'sqlite_db',
281
                'memory' => true,
282
                'defaultTableOptions' => [],
283
            ],
284
            new Reference('doctrine.dbal.default_connection.configuration'),
285
            new Reference('doctrine.dbal.default_connection.event_manager'),
286
            [],
287
        ]);
288
289
        $definition = $container->getDefinition('doctrine.orm.default_entity_manager');
290
        $this->assertEquals('%doctrine.orm.entity_manager.class%', $definition->getClass());
291
        $this->assertEquals(['%doctrine.orm.entity_manager.class%', 'create'], $definition->getFactory());
292
293
        $this->assertDICConstructorArguments($definition, [
294
            new Reference('doctrine.dbal.default_connection'),
295
            new Reference('doctrine.orm.default_configuration'),
296
        ]);
297
298
        $configDef = $container->getDefinition('doctrine.orm.default_configuration');
299
        $this->assertDICDefinitionMethodCallOnce($configDef, 'setDefaultRepositoryClassName', ['Acme\Doctrine\Repository']);
300
    }
301
302
    public function testLoadMultipleConnections() : void
303
    {
304
        $container = $this->loadContainer('orm_service_multiple_entity_managers');
305
306
        $definition = $container->getDefinition('doctrine.dbal.conn1_connection');
307
308
        $args = $definition->getArguments();
309
        $this->assertEquals('pdo_sqlite', $args[0]['driver']);
310
        $this->assertEquals('localhost', $args[0]['host']);
311
        $this->assertEquals('sqlite_user', $args[0]['user']);
312
        $this->assertEquals('doctrine.dbal.conn1_connection.configuration', (string) $args[1]);
313
        $this->assertEquals('doctrine.dbal.conn1_connection.event_manager', (string) $args[2]);
314
315
        $this->assertEquals('doctrine.orm.em2_entity_manager', (string) $container->getAlias('doctrine.orm.entity_manager'));
316
317
        $definition = $container->getDefinition('doctrine.orm.em1_entity_manager');
318
        $this->assertEquals('%doctrine.orm.entity_manager.class%', $definition->getClass());
319
        $this->assertEquals(['%doctrine.orm.entity_manager.class%', 'create'], $definition->getFactory());
320
321
        $arguments = $definition->getArguments();
322
        $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $arguments[0]);
323
        $this->assertEquals('doctrine.dbal.conn1_connection', (string) $arguments[0]);
324
        $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $arguments[1]);
325
        $this->assertEquals('doctrine.orm.em1_configuration', (string) $arguments[1]);
326
327
        $definition = $container->getDefinition('doctrine.dbal.conn2_connection');
328
329
        $args = $definition->getArguments();
330
        $this->assertEquals('pdo_sqlite', $args[0]['driver']);
331
        $this->assertEquals('localhost', $args[0]['host']);
332
        $this->assertEquals('sqlite_user', $args[0]['user']);
333
        $this->assertEquals('doctrine.dbal.conn2_connection.configuration', (string) $args[1]);
334
        $this->assertEquals('doctrine.dbal.conn2_connection.event_manager', (string) $args[2]);
335
336
        $definition = $container->getDefinition('doctrine.orm.em2_entity_manager');
337
        $this->assertEquals('%doctrine.orm.entity_manager.class%', $definition->getClass());
338
        $this->assertEquals(['%doctrine.orm.entity_manager.class%', 'create'], $definition->getFactory());
339
340
        $arguments = $definition->getArguments();
341
        $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $arguments[0]);
342
        $this->assertEquals('doctrine.dbal.conn2_connection', (string) $arguments[0]);
343
        $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $arguments[1]);
344
        $this->assertEquals('doctrine.orm.em2_configuration', (string) $arguments[1]);
345
346
        $definition = $container->getDefinition((string) $container->getAlias('doctrine.orm.em1_metadata_cache'));
347
        $this->assertEquals(DoctrineProvider::class, $definition->getClass());
348
349
        $definition = $container->getDefinition((string) $container->getAlias('doctrine.orm.em1_query_cache'));
350
        $this->assertEquals(DoctrineProvider::class, $definition->getClass());
351
        $arguments = $definition->getArguments();
352
        $this->assertInstanceOf(Reference::class, $arguments[0]);
353
        $this->assertEquals('cache.doctrine.orm.em1.query', (string) $arguments[0]);
354
355
        $definition = $container->getDefinition((string) $container->getAlias('doctrine.orm.em1_result_cache'));
356
        $this->assertEquals(DoctrineProvider::class, $definition->getClass());
357
        $arguments = $definition->getArguments();
358
        $this->assertInstanceOf(Reference::class, $arguments[0]);
359
        $this->assertEquals('cache.doctrine.orm.em1.result', (string) $arguments[0]);
360
    }
361
362
    public function testLoadLogging() : void
363
    {
364
        $container = $this->loadContainer('dbal_logging');
365
366
        $definition = $container->getDefinition('doctrine.dbal.log_connection.configuration');
367
        $this->assertDICDefinitionMethodCallOnce($definition, 'setSQLLogger', [new Reference('doctrine.dbal.logger')]);
368
369
        $definition = $container->getDefinition('doctrine.dbal.profile_connection.configuration');
370
        $this->assertDICDefinitionMethodCallOnce($definition, 'setSQLLogger', [new Reference('doctrine.dbal.logger.profiling.profile')]);
371
372
        $definition = $container->getDefinition('doctrine.dbal.profile_with_backtrace_connection.configuration');
373
        $this->assertDICDefinitionMethodCallOnce($definition, 'setSQLLogger', [new Reference('doctrine.dbal.logger.backtrace.profile_with_backtrace')]);
374
375
        $definition = $container->getDefinition('doctrine.dbal.backtrace_without_profile_connection.configuration');
376
        $this->assertDICDefinitionNoMethodCall($definition, 'setSQLLogger');
377
378
        $definition = $container->getDefinition('doctrine.dbal.both_connection.configuration');
379
        $this->assertDICDefinitionMethodCallOnce($definition, 'setSQLLogger', [new Reference('doctrine.dbal.logger.chain.both')]);
380
    }
381
382
    public function testEntityManagerMetadataCacheDriverConfiguration() : void
383
    {
384
        $container = $this->loadContainer('orm_service_multiple_entity_managers');
385
386
        $definition = $container->getDefinition((string) $container->getAlias('doctrine.orm.em1_metadata_cache'));
387
        $this->assertDICDefinitionClass($definition, DoctrineProvider::class);
388
389
        $definition = $container->getDefinition((string) $container->getAlias('doctrine.orm.em2_metadata_cache'));
390
        $this->assertDICDefinitionClass($definition, DoctrineProvider::class);
391
    }
392
393
    public function testDependencyInjectionImportsOverrideDefaults() : void
394
    {
395
        $container = $this->loadContainer('orm_imports');
396
397
        $cacheDefinition = $container->getDefinition((string) $container->getAlias('doctrine.orm.default_metadata_cache'));
398
        $this->assertEquals(DoctrineProvider::class, $cacheDefinition->getClass());
399
400
        $configDefinition = $container->getDefinition('doctrine.orm.default_configuration');
401
        $this->assertDICDefinitionMethodCallOnce($configDefinition, 'setAutoGenerateProxyClasses', ['%doctrine.orm.auto_generate_proxy_classes%']);
402
    }
403
404
    public function testSingleEntityManagerMultipleMappingBundleDefinitions() : void
405
    {
406
        $container = $this->loadContainer('orm_single_em_bundle_mappings', ['YamlBundle', 'AnnotationsBundle', 'XmlBundle']);
407
408
        $definition = $container->getDefinition('doctrine.orm.default_metadata_driver');
409
410
        $this->assertDICDefinitionMethodCallAt(0, $definition, 'addDriver', [
411
            new Reference('doctrine.orm.default_annotation_metadata_driver'),
412
            'Fixtures\Bundles\AnnotationsBundle\Entity',
413
        ]);
414
415
        $this->assertDICDefinitionMethodCallAt(1, $definition, 'addDriver', [
416
            new Reference('doctrine.orm.default_yml_metadata_driver'),
417
            'Fixtures\Bundles\YamlBundle\Entity',
418
        ]);
419
420
        $this->assertDICDefinitionMethodCallAt(2, $definition, 'addDriver', [
421
            new Reference('doctrine.orm.default_xml_metadata_driver'),
422
            'Fixtures\Bundles\XmlBundle',
423
        ]);
424
425
        $annDef = $container->getDefinition('doctrine.orm.default_annotation_metadata_driver');
426
        $this->assertDICConstructorArguments($annDef, [
427
            new Reference('doctrine.orm.metadata.annotation_reader'),
428
            [__DIR__ . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR . 'Bundles' . DIRECTORY_SEPARATOR . 'AnnotationsBundle' . DIRECTORY_SEPARATOR . 'Entity'],
429
        ]);
430
431
        $ymlDef = $container->getDefinition('doctrine.orm.default_yml_metadata_driver');
432
        $this->assertDICConstructorArguments($ymlDef, [
433
            [__DIR__ . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR . 'Bundles' . DIRECTORY_SEPARATOR . 'YamlBundle' . DIRECTORY_SEPARATOR . 'Resources' . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'doctrine' => 'Fixtures\Bundles\YamlBundle\Entity'],
434
        ]);
435
436
        $xmlDef = $container->getDefinition('doctrine.orm.default_xml_metadata_driver');
437
        $this->assertDICConstructorArguments($xmlDef, [
438
            [__DIR__ . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR . 'Bundles' . DIRECTORY_SEPARATOR . 'XmlBundle' . DIRECTORY_SEPARATOR . 'Resources' . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'doctrine' => 'Fixtures\Bundles\XmlBundle'],
439
        ]);
440
    }
441
442
    public function testMultipleEntityManagersMappingBundleDefinitions() : void
443
    {
444
        $container = $this->loadContainer('orm_multiple_em_bundle_mappings', ['YamlBundle', 'AnnotationsBundle', 'XmlBundle']);
445
446
        $this->assertEquals(['em1' => 'doctrine.orm.em1_entity_manager', 'em2' => 'doctrine.orm.em2_entity_manager'], $container->getParameter('doctrine.entity_managers'), 'Set of the existing EntityManagers names is incorrect.');
447
        $this->assertEquals('%doctrine.entity_managers%', $container->getDefinition('doctrine')->getArgument(2), 'Set of the existing EntityManagers names is incorrect.');
448
449
        $def1 = $container->getDefinition('doctrine.orm.em1_metadata_driver');
450
        $def2 = $container->getDefinition('doctrine.orm.em2_metadata_driver');
451
452
        $this->assertDICDefinitionMethodCallAt(0, $def1, 'addDriver', [
453
            new Reference('doctrine.orm.em1_annotation_metadata_driver'),
454
            'Fixtures\Bundles\AnnotationsBundle\Entity',
455
        ]);
456
457
        $this->assertDICDefinitionMethodCallAt(0, $def2, 'addDriver', [
458
            new Reference('doctrine.orm.em2_yml_metadata_driver'),
459
            'Fixtures\Bundles\YamlBundle\Entity',
460
        ]);
461
462
        $this->assertDICDefinitionMethodCallAt(1, $def2, 'addDriver', [
463
            new Reference('doctrine.orm.em2_xml_metadata_driver'),
464
            'Fixtures\Bundles\XmlBundle',
465
        ]);
466
467
        $annDef = $container->getDefinition('doctrine.orm.em1_annotation_metadata_driver');
468
        $this->assertDICConstructorArguments($annDef, [
469
            new Reference('doctrine.orm.metadata.annotation_reader'),
470
            [__DIR__ . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR . 'Bundles' . DIRECTORY_SEPARATOR . 'AnnotationsBundle' . DIRECTORY_SEPARATOR . 'Entity'],
471
        ]);
472
473
        $ymlDef = $container->getDefinition('doctrine.orm.em2_yml_metadata_driver');
474
        $this->assertDICConstructorArguments($ymlDef, [
475
            [__DIR__ . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR . 'Bundles' . DIRECTORY_SEPARATOR . 'YamlBundle' . DIRECTORY_SEPARATOR . 'Resources' . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'doctrine' => 'Fixtures\Bundles\YamlBundle\Entity'],
476
        ]);
477
478
        $xmlDef = $container->getDefinition('doctrine.orm.em2_xml_metadata_driver');
479
        $this->assertDICConstructorArguments($xmlDef, [
480
            [__DIR__ . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR . 'Bundles' . DIRECTORY_SEPARATOR . 'XmlBundle' . DIRECTORY_SEPARATOR . 'Resources' . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'doctrine' => 'Fixtures\Bundles\XmlBundle'],
481
        ]);
482
    }
483
484
    public function testSingleEntityManagerDefaultTableOptions() : void
485
    {
486
        $container = $this->loadContainer('orm_single_em_default_table_options', ['YamlBundle', 'AnnotationsBundle', 'XmlBundle']);
487
488
        $param = $container->getDefinition('doctrine.dbal.default_connection')->getArgument(0);
489
490
        $this->assertArrayHasKey('defaultTableOptions', $param);
491
492
        $defaults = $param['defaultTableOptions'];
493
494
        $this->assertArrayHasKey('charset', $defaults);
495
        $this->assertArrayHasKey('collate', $defaults);
496
        $this->assertArrayHasKey('engine', $defaults);
497
498
        $this->assertEquals('utf8mb4', $defaults['charset']);
499
        $this->assertEquals('utf8mb4_unicode_ci', $defaults['collate']);
500
        $this->assertEquals('InnoDB', $defaults['engine']);
501
    }
502
503
    public function testSetTypes() : void
504
    {
505
        $container = $this->loadContainer('dbal_types');
506
507
        $this->assertEquals(
508
            ['test' => ['class' => TestType::class]],
509
            $container->getParameter('doctrine.dbal.connection_factory.types')
510
        );
511
        $this->assertEquals('%doctrine.dbal.connection_factory.types%', $container->getDefinition('doctrine.dbal.connection_factory')->getArgument(0));
512
    }
513
514
    public function testSetCustomFunctions() : void
515
    {
516
        $container = $this->loadContainer('orm_functions');
517
518
        $definition = $container->getDefinition('doctrine.orm.default_configuration');
519
        $this->assertDICDefinitionMethodCallOnce($definition, 'addCustomStringFunction', ['test_string', 'Symfony\Bundle\DoctrineBundle\Tests\DependencyInjection\TestStringFunction']);
520
        $this->assertDICDefinitionMethodCallOnce($definition, 'addCustomNumericFunction', ['test_numeric', 'Symfony\Bundle\DoctrineBundle\Tests\DependencyInjection\TestNumericFunction']);
521
        $this->assertDICDefinitionMethodCallOnce($definition, 'addCustomDatetimeFunction', ['test_datetime', 'Symfony\Bundle\DoctrineBundle\Tests\DependencyInjection\TestDatetimeFunction']);
522
    }
523
524 View Code Duplication
    public function testSetNamingStrategy() : void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
525
    {
526
        $container = $this->loadContainer('orm_namingstrategy');
527
528
        $def1 = $container->getDefinition('doctrine.orm.em1_configuration');
529
        $def2 = $container->getDefinition('doctrine.orm.em2_configuration');
530
531
        $this->assertDICDefinitionMethodCallOnce($def1, 'setNamingStrategy', [0 => new Reference('doctrine.orm.naming_strategy.default')]);
532
        $this->assertDICDefinitionMethodCallOnce($def2, 'setNamingStrategy', [0 => new Reference('doctrine.orm.naming_strategy.underscore')]);
533
    }
534
535 View Code Duplication
    public function testSetQuoteStrategy() : void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
536
    {
537
        $container = $this->loadContainer('orm_quotestrategy');
538
539
        $def1 = $container->getDefinition('doctrine.orm.em1_configuration');
540
        $def2 = $container->getDefinition('doctrine.orm.em2_configuration');
541
542
        $this->assertDICDefinitionMethodCallOnce($def1, 'setQuoteStrategy', [0 => new Reference('doctrine.orm.quote_strategy.default')]);
543
        $this->assertDICDefinitionMethodCallOnce($def2, 'setQuoteStrategy', [0 => new Reference('doctrine.orm.quote_strategy.ansi')]);
544
    }
545
546
    public function testSecondLevelCache() : void
547
    {
548
        $container = $this->loadContainer('orm_second_level_cache');
549
550
        $this->assertTrue($container->has('doctrine.orm.default_configuration'));
551
        $this->assertTrue($container->has('doctrine.orm.default_second_level_cache.cache_configuration'));
552
        $this->assertTrue($container->has('doctrine.orm.default_second_level_cache.region_cache_driver'));
553
        $this->assertTrue($container->has('doctrine.orm.default_second_level_cache.regions_configuration'));
554
        $this->assertTrue($container->has('doctrine.orm.default_second_level_cache.default_cache_factory'));
555
556
        $this->assertTrue($container->has('doctrine.orm.default_second_level_cache.logger_chain'));
557
        $this->assertTrue($container->has('doctrine.orm.default_second_level_cache.logger_statistics'));
558
        $this->assertTrue($container->has('doctrine.orm.default_second_level_cache.logger.my_service_logger1'));
559
        $this->assertTrue($container->has('doctrine.orm.default_second_level_cache.logger.my_service_logger2'));
560
561
        $this->assertTrue($container->has('doctrine.orm.default_second_level_cache.region.my_entity_region'));
562
        $this->assertTrue($container->has('doctrine.orm.default_second_level_cache.region.my_service_region'));
563
        $this->assertTrue($container->has('doctrine.orm.default_second_level_cache.region.my_query_region_filelock'));
564
565
        $slcFactoryDef       = $container->getDefinition('doctrine.orm.default_second_level_cache.default_cache_factory');
566
        $myEntityRegionDef   = $container->getDefinition('doctrine.orm.default_second_level_cache.region.my_entity_region');
567
        $loggerChainDef      = $container->getDefinition('doctrine.orm.default_second_level_cache.logger_chain');
568
        $loggerStatisticsDef = $container->getDefinition('doctrine.orm.default_second_level_cache.logger_statistics');
569
        $myQueryRegionDef    = $container->getDefinition('doctrine.orm.default_second_level_cache.region.my_query_region_filelock');
570
        $cacheDriverDef      = $container->getDefinition((string) $container->getAlias('doctrine.orm.default_second_level_cache.region_cache_driver'));
571
        $configDef           = $container->getDefinition('doctrine.orm.default_configuration');
572
        $myEntityRegionArgs  = $myEntityRegionDef->getArguments();
573
        $myQueryRegionArgs   = $myQueryRegionDef->getArguments();
574
        $slcFactoryArgs      = $slcFactoryDef->getArguments();
575
576
        $this->assertDICDefinitionClass($slcFactoryDef, '%doctrine.orm.second_level_cache.default_cache_factory.class%');
577
        $this->assertDICDefinitionClass($myQueryRegionDef, '%doctrine.orm.second_level_cache.filelock_region.class%');
578
        $this->assertDICDefinitionClass($myEntityRegionDef, '%doctrine.orm.second_level_cache.default_region.class%');
579
        $this->assertDICDefinitionClass($loggerChainDef, '%doctrine.orm.second_level_cache.logger_chain.class%');
580
        $this->assertDICDefinitionClass($loggerStatisticsDef, '%doctrine.orm.second_level_cache.logger_statistics.class%');
581
        $this->assertDICDefinitionClass($cacheDriverDef, DoctrineProvider::class);
582
        $this->assertDICDefinitionMethodCallOnce($configDef, 'setSecondLevelCacheConfiguration');
583
        $this->assertDICDefinitionMethodCallCount($slcFactoryDef, 'setRegion', [], 3);
584
        $this->assertDICDefinitionMethodCallCount($loggerChainDef, 'setLogger', [], 3);
585
586
        $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $slcFactoryArgs[0]);
587
        $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $slcFactoryArgs[1]);
588
589
        $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $myEntityRegionArgs[1]);
590
        $this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $myQueryRegionArgs[0]);
591
592
        $this->assertEquals('my_entity_region', $myEntityRegionArgs[0]);
593
        $this->assertEquals('doctrine.orm.default_second_level_cache.region.my_entity_region_driver', $myEntityRegionArgs[1]);
594
        $this->assertEquals(600, $myEntityRegionArgs[2]);
595
596
        $this->assertEquals('doctrine.orm.default_second_level_cache.region.my_query_region', $myQueryRegionArgs[0]);
597
        $this->assertContains('/doctrine/orm/slc/filelock', $myQueryRegionArgs[1]);
598
        $this->assertEquals(60, $myQueryRegionArgs[2]);
599
600
        $this->assertEquals('doctrine.orm.default_second_level_cache.regions_configuration', $slcFactoryArgs[0]);
601
        $this->assertEquals('doctrine.orm.default_second_level_cache.region_cache_driver', $slcFactoryArgs[1]);
602
    }
603
604
    public function testSingleEMSetCustomFunctions() : void
605
    {
606
        $container = $this->loadContainer('orm_single_em_dql_functions');
607
608
        $definition = $container->getDefinition('doctrine.orm.default_configuration');
609
        $this->assertDICDefinitionMethodCallOnce($definition, 'addCustomStringFunction', ['test_string', 'Symfony\Bundle\DoctrineBundle\Tests\DependencyInjection\TestStringFunction']);
610
    }
611
612
    public function testAddCustomHydrationMode() : void
613
    {
614
        $container = $this->loadContainer('orm_hydration_mode');
615
616
        $definition = $container->getDefinition('doctrine.orm.default_configuration');
617
        $this->assertDICDefinitionMethodCallOnce($definition, 'addCustomHydrationMode', ['test_hydrator', 'Symfony\Bundle\DoctrineBundle\Tests\DependencyInjection\TestHydrator']);
618
    }
619
620
    public function testAddFilter() : void
621
    {
622
        $container = $this->loadContainer('orm_filters');
623
624
        $definition = $container->getDefinition('doctrine.orm.default_configuration');
625
        $args       = [
626
            ['soft_delete', 'Doctrine\Bundle\DoctrineBundle\Tests\DependencyInjection\TestFilter'],
627
            ['myFilter', 'Doctrine\Bundle\DoctrineBundle\Tests\DependencyInjection\TestFilter'],
628
        ];
629
        $this->assertDICDefinitionMethodCallCount($definition, 'addFilter', $args, 2);
630
631
        $definition = $container->getDefinition('doctrine.orm.default_manager_configurator');
632
        $this->assertDICConstructorArguments($definition, [['soft_delete', 'myFilter'], ['myFilter' => ['myParameter' => 'myValue', 'mySecondParameter' => 'mySecondValue']]]);
633
634
        // Let's create the instance to check the configurator work.
635
        /** @var EntityManager $entityManager */
636
        $entityManager = $container->get('doctrine.orm.entity_manager');
637
        $this->assertCount(2, $entityManager->getFilters()->getEnabledFilters());
0 ignored issues
show
Documentation introduced by
$entityManager->getFilters()->getEnabledFilters() is of type array<integer,object<Doc...uery\Filter\SQLFilter>>, but the function expects a object<Countable>|object...nit\Framework\iterable>.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
638
    }
639
640
    public function testResolveTargetEntity() : void
641
    {
642
        $container = $this->loadContainer('orm_resolve_target_entity');
643
644
        $definition = $container->getDefinition('doctrine.orm.listeners.resolve_target_entity');
645
        $this->assertDICDefinitionMethodCallOnce($definition, 'addResolveTargetEntity', ['Symfony\Component\Security\Core\User\UserInterface', 'MyUserClass', []]);
646
647
        $this->assertEquals(['doctrine.event_subscriber' => [[]]], $definition->getTags());
648
    }
649
650
    public function testAttachEntityListeners() : void
651
    {
652
        $container = $this->loadContainer('orm_attach_entity_listener');
653
654
        $definition  = $container->getDefinition('doctrine.orm.default_listeners.attach_entity_listeners');
655
        $methodCalls = $definition->getMethodCalls();
656
657
        $this->assertDICDefinitionMethodCallCount($definition, 'addEntityListener', [], 6);
658
        $this->assertEquals(['doctrine.event_listener' => [ ['event' => 'loadClassMetadata'] ] ], $definition->getTags());
659
660
        $this->assertEquals($methodCalls[0], [
661
            'addEntityListener',
662
            [
663
                'ExternalBundles\Entities\FooEntity',
664
                'MyBundles\Listeners\FooEntityListener',
665
                'prePersist',
666
                null,
667
            ],
668
        ]);
669
670
        $this->assertEquals($methodCalls[1], [
671
            'addEntityListener',
672
            [
673
                'ExternalBundles\Entities\FooEntity',
674
                'MyBundles\Listeners\FooEntityListener',
675
                'postPersist',
676
                'postPersist',
677
            ],
678
        ]);
679
680
        $this->assertEquals($methodCalls[2], [
681
            'addEntityListener',
682
            [
683
                'ExternalBundles\Entities\FooEntity',
684
                'MyBundles\Listeners\FooEntityListener',
685
                'postLoad',
686
                'postLoadHandler',
687
            ],
688
        ]);
689
690
        $this->assertEquals($methodCalls[3], [
691
            'addEntityListener',
692
            [
693
                'ExternalBundles\Entities\BarEntity',
694
                'MyBundles\Listeners\BarEntityListener',
695
                'prePersist',
696
                'prePersist',
697
            ],
698
        ]);
699
700
        $this->assertEquals($methodCalls[4], [
701
            'addEntityListener',
702
            [
703
                'ExternalBundles\Entities\BarEntity',
704
                'MyBundles\Listeners\BarEntityListener',
705
                'prePersist',
706
                'prePersistHandler',
707
            ],
708
        ]);
709
710
        $this->assertEquals($methodCalls[5], [
711
            'addEntityListener',
712
            [
713
                'ExternalBundles\Entities\BarEntity',
714
                'MyBundles\Listeners\LogDeleteEntityListener',
715
                'postDelete',
716
                'postDelete',
717
            ],
718
        ]);
719
    }
720
721
    public function testDbalAutoCommit() : void
722
    {
723
        $container = $this->loadContainer('dbal_auto_commit');
724
725
        $definition = $container->getDefinition('doctrine.dbal.default_connection.configuration');
726
        $this->assertDICDefinitionMethodCallOnce($definition, 'setAutoCommit', [false]);
727
    }
728
729 View Code Duplication
    public function testDbalOracleConnectstring() : void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
730
    {
731
        $container = $this->loadContainer('dbal_oracle_connectstring');
732
733
        $config = $container->getDefinition('doctrine.dbal.default_connection')->getArgument(0);
734
        $this->assertSame('scott@sales-server:1521/sales.us.example.com', $config['connectstring']);
735
    }
736
737 View Code Duplication
    public function testDbalOracleInstancename() : void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
738
    {
739
        $container = $this->loadContainer('dbal_oracle_instancename');
740
741
        $config = $container->getDefinition('doctrine.dbal.default_connection')->getArgument(0);
742
        $this->assertSame('mySuperInstance', $config['instancename']);
743
    }
744
745
    public function testDbalSchemaFilterNewConfig() : void
746
    {
747
        $container = $this->getContainer([]);
748
        $loader    = new DoctrineExtension();
749
        $container->registerExtension($loader);
750
        $container->addCompilerPass(new WellKnownSchemaFilterPass());
751
        $container->addCompilerPass(new DbalSchemaFilterPass());
752
753
        // ignore table1 table on "default" connection
754
        $container->register('dummy_filter1', DummySchemaAssetsFilter::class)
755
            ->setArguments(['table1'])
756
            ->addTag('doctrine.dbal.schema_filter');
757
758
        // ignore table2 table on "connection2" connection
759
        $container->register('dummy_filter2', DummySchemaAssetsFilter::class)
760
            ->setArguments(['table2'])
761
            ->addTag('doctrine.dbal.schema_filter', ['connection' => 'connection2']);
762
763
        $this->loadFromFile($container, 'dbal_schema_filter');
764
765
        $assetNames               = ['table1', 'table2', 'table3', 't_ignored'];
766
        $expectedConnectionAssets = [
767
            // ignores table1 + schema_filter applies
768
            'connection1' => ['table2', 'table3'],
769
            // ignores table2, no schema_filter applies
770
            'connection2' => ['table1', 'table3', 't_ignored'],
771
            // connection3 has no ignores, handled separately
772
        ];
773
774
        $this->compileContainer($container);
775
776
        $getConfiguration = static function (string $connectionName) use ($container) : Configuration {
777
            return $container->get(sprintf('doctrine.dbal.%s_connection', $connectionName))->getConfiguration();
778
        };
779
780
        foreach ($expectedConnectionAssets as $connectionName => $expectedTables) {
781
            $connConfig = $getConfiguration($connectionName);
782
            $this->assertSame($expectedTables, array_values(array_filter($assetNames, $connConfig->getSchemaAssetsFilter())), sprintf('Filtering for connection "%s"', $connectionName));
783
        }
784
785
        $this->assertNull($connConfig = $getConfiguration('connection3')->getSchemaAssetsFilter());
786
    }
787
788
    public static function dataWellKnownSchemaFilterServices()
789
    {
790
        yield ['cache', 'cache_items'];
791
        yield ['lock', 'lock_keys'];
792
        yield ['messenger', 'messenger_messages'];
793
        yield ['session', 'sessions'];
794
    }
795
796
    /**
797
     * @dataProvider dataWellKnownSchemaFilterServices
798
     */
799
    public function testWellKnownSchemaFilterDefaultTables(string $fileName, string $tableName) : void
800
    {
801
        $container = $this->getContainer([]);
802
        $loader    = new DoctrineExtension();
803
        $container->registerExtension($loader);
804
        $container->addCompilerPass(new WellKnownSchemaFilterPass());
805
        $container->addCompilerPass(new DbalSchemaFilterPass());
806
807
        $this->loadFromFile($container, 'well_known_schema_filter_default_tables_' . $fileName);
808
809
        $this->compileContainer($container);
810
811
        $definition = $container->getDefinition('doctrine.dbal.well_known_schema_asset_filter');
812
813
        $this->assertSame([[$tableName]], $definition->getArguments());
814
        $this->assertSame([['connection' => 'connection1'], ['connection' => 'connection2'], ['connection' => 'connection3']], $definition->getTag('doctrine.dbal.schema_filter'));
815
816
        $definition = $container->getDefinition('doctrine.dbal.connection1_schema_asset_filter_manager');
817
818
        $this->assertEquals([new Reference('doctrine.dbal.well_known_schema_asset_filter'), new Reference('doctrine.dbal.connection1_regex_schema_filter')], $definition->getArgument(0));
819
820
        $filter = $container->get('well_known_filter');
821
822
        $this->assertFalse($filter($tableName));
823
        $this->assertTrue($filter('anything_else'));
824
    }
825
826
    public static function dataWellKnownSchemaOverriddenTablesFilterServices()
827
    {
828
        yield ['cache', 'app_cache'];
829
        yield ['lock', 'app_locks'];
830
        yield ['messenger', 'app_messages'];
831
        yield ['session', 'app_session'];
832
    }
833
834
    /**
835
     * @dataProvider dataWellKnownSchemaOverriddenTablesFilterServices
836
     */
837
    public function testWellKnownSchemaFilterOverriddenTables(string $fileName, string $tableName) : void
838
    {
839
        $container = $this->getContainer([]);
840
        $loader    = new DoctrineExtension();
841
        $container->registerExtension($loader);
842
        $container->addCompilerPass(new WellKnownSchemaFilterPass());
843
        $container->addCompilerPass(new DbalSchemaFilterPass());
844
845
        $this->loadFromFile($container, 'well_known_schema_filter_overridden_tables_' . $fileName);
846
847
        $this->compileContainer($container);
848
849
        $filter = $container->get('well_known_filter');
850
851
        $this->assertFalse($filter($tableName));
852
    }
853
854
    public function testEntityListenerResolver() : void
855
    {
856
        $container = $this->loadContainer('orm_entity_listener_resolver', ['YamlBundle'], new EntityListenerPass());
857
858
        $definition = $container->getDefinition('doctrine.orm.em1_configuration');
859
        $this->assertDICDefinitionMethodCallOnce($definition, 'setEntityListenerResolver', [new Reference('doctrine.orm.em1_entity_listener_resolver')]);
860
861
        $definition = $container->getDefinition('doctrine.orm.em2_configuration');
862
        $this->assertDICDefinitionMethodCallOnce($definition, 'setEntityListenerResolver', [new Reference('doctrine.orm.em2_entity_listener_resolver')]);
863
864
        $listener = $container->getDefinition('doctrine.orm.em1_entity_listener_resolver');
865
        $this->assertDICDefinitionMethodCallOnce($listener, 'registerService', ['EntityListener', 'entity_listener1']);
866
867
        $listener = $container->getDefinition('entity_listener_resolver');
868
        $this->assertDICDefinitionMethodCallOnce($listener, 'register', [new Reference('entity_listener2')]);
869
    }
870
871
    public function testAttachEntityListenerTag() : void
872
    {
873
        $container = $this->getContainer([]);
874
        $loader    = new DoctrineExtension();
875
        $container->registerExtension($loader);
876
        $container->addCompilerPass(new EntityListenerPass());
877
878
        $this->loadFromFile($container, 'orm_attach_entity_listener_tag');
879
880
        $this->compileContainer($container);
881
882
        $listener = $container->getDefinition('doctrine.orm.em1_entity_listener_resolver');
883
        $this->assertDICDefinitionMethodCallCount($listener, 'registerService', [
884
            ['ParentEntityListener', 'children_entity_listener'],
885
            ['EntityListener1', 'entity_listener1'],
886
            ['Doctrine\Bundle\DoctrineBundle\Tests\DependencyInjection\Fixtures\InvokableEntityListener', 'invokable_entity_listener'],
887
            ['Doctrine\Bundle\DoctrineBundle\Tests\DependencyInjection\Fixtures\InvokableEntityListener', 'invokable_entity_listener'],
888
        ], 4);
889
890
        $listener = $container->getDefinition('doctrine.orm.em2_entity_listener_resolver');
891
        $this->assertDICDefinitionMethodCallOnce($listener, 'registerService', ['EntityListener2', 'entity_listener2']);
892
893
        $attachListener = $container->getDefinition('doctrine.orm.em1_listeners.attach_entity_listeners');
894
        $this->assertDICDefinitionMethodCallAt(1, $attachListener, 'addEntityListener', ['My/Entity1', 'EntityListener1', 'postLoad']);
895
        $this->assertDICDefinitionMethodCallAt(2, $attachListener, 'addEntityListener', ['My/Entity1', 'Doctrine\Bundle\DoctrineBundle\Tests\DependencyInjection\Fixtures\InvokableEntityListener', 'loadClassMetadata', '__invoke']);
896
        $this->assertDICDefinitionMethodCallAt(3, $attachListener, 'addEntityListener', ['My/Entity1', 'Doctrine\Bundle\DoctrineBundle\Tests\DependencyInjection\Fixtures\InvokableEntityListener', 'postPersist']);
897
        $this->assertDICDefinitionMethodCallAt(0, $attachListener, 'addEntityListener', ['My/Entity3', 'ParentEntityListener', 'postLoad']);
898
899
        $attachListener = $container->getDefinition('doctrine.orm.em2_listeners.attach_entity_listeners');
900
        $this->assertDICDefinitionMethodCallOnce($attachListener, 'addEntityListener', ['My/Entity2', 'EntityListener2', 'preFlush', 'preFlushHandler']);
901
    }
902
903
    public function testAttachEntityListenersTwoConnections() : void
904
    {
905
        $container = $this->getContainer(['YamlBundle']);
906
        $loader    = new DoctrineExtension();
907
        $container->registerExtension($loader);
908
        $container->addCompilerPass(new RegisterEventListenersAndSubscribersPass('doctrine.connections', 'doctrine.dbal.%s_connection.event_manager', 'doctrine'));
909
910
        $this->loadFromFile($container, 'orm_attach_entity_listeners_two_connections');
911
912
        $this->compileContainer($container);
913
914
        $defaultEventManager = $container->getDefinition('doctrine.dbal.default_connection.event_manager');
915
        $this->assertDICDefinitionNoMethodCall($defaultEventManager, 'addEventListener', [['loadClassMetadata'], new Reference('doctrine.orm.em2_listeners.attach_entity_listeners')]);
916
        $this->assertDICDefinitionMethodCallOnce($defaultEventManager, 'addEventListener', [['loadClassMetadata'], new Reference('doctrine.orm.em1_listeners.attach_entity_listeners')]);
917
918
        $foobarEventManager = $container->getDefinition('doctrine.dbal.foobar_connection.event_manager');
919
        $this->assertDICDefinitionNoMethodCall($foobarEventManager, 'addEventListener', [['loadClassMetadata'], new Reference('doctrine.orm.em1_listeners.attach_entity_listeners')]);
920
        $this->assertDICDefinitionMethodCallOnce($foobarEventManager, 'addEventListener', [['loadClassMetadata'], new Reference('doctrine.orm.em2_listeners.attach_entity_listeners')]);
921
    }
922
923
    public function testAttachLazyEntityListener() : void
924
    {
925
        $container = $this->getContainer([]);
926
        $loader    = new DoctrineExtension();
927
        $container->registerExtension($loader);
928
        $container->addCompilerPass(new EntityListenerPass());
929
930
        $this->loadFromFile($container, 'orm_attach_lazy_entity_listener');
931
932
        $this->compileContainer($container);
933
934
        $resolver1 = $container->getDefinition('doctrine.orm.em1_entity_listener_resolver');
935
        $this->assertDICDefinitionMethodCallAt(0, $resolver1, 'registerService', ['EntityListener1', 'entity_listener1']);
936
        $this->assertDICDefinitionMethodCallAt(1, $resolver1, 'register', [new Reference('entity_listener3')]);
937
        $this->assertDICDefinitionMethodCallAt(2, $resolver1, 'registerService', ['EntityListener4', 'entity_listener4']);
938
939
        $serviceLocatorReference = $resolver1->getArgument(0);
940
        $this->assertInstanceOf(Reference::class, $serviceLocatorReference);
941
        $serviceLocatorDefinition = $container->getDefinition((string) $serviceLocatorReference);
942
        $this->assertSame(ServiceLocator::class, $serviceLocatorDefinition->getClass());
943
        $serviceLocatorMap = $serviceLocatorDefinition->getArgument(0);
944
        $this->assertSame(['entity_listener1', 'entity_listener4'], array_keys($serviceLocatorMap));
945
946
        $resolver2 = $container->findDefinition('custom_entity_listener_resolver');
947
        $this->assertDICDefinitionMethodCallOnce($resolver2, 'registerService', ['EntityListener2', 'entity_listener2']);
948
    }
949
950
    public function testAttachLazyEntityListenerForCustomResolver() : void
951
    {
952
        $container = $this->getContainer([]);
953
        $loader    = new DoctrineExtension();
954
        $container->registerExtension($loader);
955
        $container->addCompilerPass(new EntityListenerPass());
956
957
        $this->loadFromFile($container, 'orm_entity_listener_custom_resolver');
958
959
        $this->compileContainer($container);
960
961
        $resolver = $container->getDefinition('custom_entity_listener_resolver');
962
        $this->assertTrue($resolver->isPublic());
963
        $this->assertEmpty($resolver->getArguments(), 'We must not change the arguments for custom services.');
964
        $this->assertDICDefinitionMethodCallOnce($resolver, 'registerService', ['EntityListener', 'entity_listener']);
965
        $this->assertTrue($container->getDefinition('entity_listener')->isPublic());
966
    }
967
968
    /**
969
     * @expectedException \InvalidArgumentException
970
     * @expectedExceptionMessage EntityListenerServiceResolver
971
     */
972 View Code Duplication
    public function testLazyEntityListenerResolverWithoutCorrectInterface() : void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
973
    {
974
        $container = $this->getContainer([]);
975
        $loader    = new DoctrineExtension();
976
        $container->registerExtension($loader);
977
        $container->addCompilerPass(new EntityListenerPass());
978
979
        $this->loadFromFile($container, 'orm_entity_listener_lazy_resolver_without_interface');
980
981
        $this->compileContainer($container);
982
    }
983
984
    public function testPrivateLazyEntityListener() : void
985
    {
986
        $container = $this->getContainer([]);
987
        $loader    = new DoctrineExtension();
988
        $container->registerExtension($loader);
989
        $container->addCompilerPass(new EntityListenerPass());
990
991
        $this->loadFromFile($container, 'orm_entity_listener_lazy_private');
992
993
        $this->compileContainer($container);
994
995
        $this->assertTrue($container->getDefinition('doctrine.orm.em1_entity_listener_resolver')->isPublic());
996
    }
997
998
    /**
999
     * @expectedException \InvalidArgumentException
1000
     * @expectedExceptionMessageRegExp /The service ".*" must not be abstract\./
1001
     */
1002 View Code Duplication
    public function testAbstractEntityListener() : void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1003
    {
1004
        $container = $this->getContainer([]);
1005
        $loader    = new DoctrineExtension();
1006
        $container->registerExtension($loader);
1007
        $container->addCompilerPass(new EntityListenerPass());
1008
1009
        $this->loadFromFile($container, 'orm_entity_listener_abstract');
1010
1011
        $this->compileContainer($container);
1012
    }
1013
1014
    public function testRepositoryFactory() : void
1015
    {
1016
        $container = $this->loadContainer('orm_repository_factory');
1017
1018
        $definition = $container->getDefinition('doctrine.orm.default_configuration');
1019
        $this->assertDICDefinitionMethodCallOnce($definition, 'setRepositoryFactory', ['repository_factory']);
1020
    }
1021
1022
    private function loadContainer(
1023
        string $fixture,
1024
        array $bundles = ['YamlBundle'],
1025
        CompilerPassInterface $compilerPass = null
1026
    ) : ContainerBuilder {
1027
        $container = $this->getContainer($bundles);
1028
        $container->registerExtension(new DoctrineExtension());
1029
1030
        $this->loadFromFile($container, $fixture);
1031
1032
        if ($compilerPass !== null) {
1033
            $container->addCompilerPass($compilerPass);
1034
        }
1035
1036
        $this->compileContainer($container);
1037
1038
        return $container;
1039
    }
1040
1041
    private function getContainer(array $bundles) : ContainerBuilder
1042
    {
1043
        $map = [];
1044
        foreach ($bundles as $bundle) {
1045
            require_once __DIR__ . '/Fixtures/Bundles/' . $bundle . '/' . $bundle . '.php';
1046
1047
            $map[$bundle] = 'Fixtures\\Bundles\\' . $bundle . '\\' . $bundle;
1048
        }
1049
1050
        $container = new ContainerBuilder(new ParameterBag([
1051
            'kernel.name' => 'app',
1052
            'kernel.debug' => false,
1053
            'kernel.bundles' => $map,
1054
            'kernel.cache_dir' => sys_get_temp_dir(),
1055
            'kernel.environment' => 'test',
1056
            'kernel.root_dir' => __DIR__ . '/../../', // src dir
1057
            'kernel.project_dir' => __DIR__ . '/../../', // src dir
1058
            'kernel.bundles_metadata' => [],
1059
            'container.build_id' => uniqid(),
1060
        ]));
1061
1062
        // Register dummy cache services so we don't have to load the FrameworkExtension
1063
        $container->setDefinition('cache.system', (new Definition(ArrayAdapter::class))->setPublic(true));
1064
        $container->setDefinition('cache.app', (new Definition(ArrayAdapter::class))->setPublic(true));
1065
1066
        return $container;
1067
    }
1068
1069
    /**
1070
     * Assertion on the Class of a DIC Service Definition.
1071
     */
1072
    private function assertDICDefinitionClass(Definition $definition, string $expectedClass) : void
1073
    {
1074
        $this->assertEquals($expectedClass, $definition->getClass(), 'Expected Class of the DIC Container Service Definition is wrong.');
1075
    }
1076
1077
    private function assertDICConstructorArguments(Definition $definition, array $args) : void
1078
    {
1079
        $this->assertEquals($args, $definition->getArguments(), "Expected and actual DIC Service constructor arguments of definition '" . $definition->getClass() . "' don't match.");
1080
    }
1081
1082 View Code Duplication
    private function assertDICDefinitionMethodCallAt(
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...
1083
        int $pos,
1084
        Definition $definition,
1085
        string $methodName,
1086
        array $params = null
1087
    ) : void {
1088
        $calls = $definition->getMethodCalls();
1089
        if (! isset($calls[$pos][0])) {
1090
            $this->fail(sprintf('Method call at position %s not found!', $pos));
1091
1092
            return;
1093
        }
1094
1095
        $this->assertEquals($methodName, $calls[$pos][0], "Method '" . $methodName . "' is expected to be called at position " . $pos . '.');
1096
1097
        if ($params === null) {
1098
            return;
1099
        }
1100
1101
        $this->assertEquals($params, $calls[$pos][1], "Expected parameters to methods '" . $methodName . "' do not match the actual parameters.");
1102
    }
1103
1104
    /**
1105
     * Assertion for the DI Container, check if the given definition contains a method call with the given parameters.
1106
     */
1107 View Code Duplication
    private function assertDICDefinitionMethodCallOnce(
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...
1108
        Definition $definition,
1109
        string $methodName,
1110
        array $params = null
1111
    ) : void {
1112
        $calls  = $definition->getMethodCalls();
1113
        $called = false;
1114
        foreach ($calls as $call) {
1115
            if ($call[0] !== $methodName) {
1116
                continue;
1117
            }
1118
1119
            if ($called) {
1120
                $this->fail("Method '" . $methodName . "' is expected to be called only once, a second call was registered though.");
1121
            } else {
1122
                $called = true;
1123
                if ($params !== null) {
1124
                    $this->assertEquals($params, $call[1], "Expected parameters to methods '" . $methodName . "' do not match the actual parameters.");
1125
                }
1126
            }
1127
        }
1128
        if ($called) {
1129
            return;
1130
        }
1131
1132
        $this->fail("Method '" . $methodName . "' is expected to be called once, definition does not contain a call though.");
1133
    }
1134
1135
    private function assertDICDefinitionMethodCallCount(
1136
        Definition $definition,
1137
        string $methodName,
1138
        array $params = [],
1139
        int $nbCalls = 1
1140
    ) : void {
1141
        $calls  = $definition->getMethodCalls();
1142
        $called = 0;
1143
        foreach ($calls as $call) {
1144
            if ($call[0] !== $methodName) {
1145
                continue;
1146
            }
1147
1148
            if ($called > $nbCalls) {
1149
                break;
1150
            }
1151
1152
            if (isset($params[$called])) {
1153
                $this->assertEquals($params[$called], $call[1], "Expected parameters to methods '" . $methodName . "' do not match the actual parameters.");
1154
            }
1155
            $called++;
1156
        }
1157
1158
        $this->assertEquals($nbCalls, $called, sprintf('The method "%s" should be called %d times', $methodName, $nbCalls));
1159
    }
1160
1161
    /**
1162
     * Assertion for the DI Container, check if the given definition does not contain a method call with the given parameters.
1163
     */
1164
    private function assertDICDefinitionNoMethodCall(
1165
        Definition $definition,
1166
        string $methodName,
1167
        array $params = null
1168
    ) : void {
1169
        $calls = $definition->getMethodCalls();
1170
        foreach ($calls as $call) {
1171
            if ($call[0] !== $methodName) {
1172
                continue;
1173
            }
1174
1175
            if ($params !== null) {
1176
                $this->assertNotEquals($params, $call[1], "Method '" . $methodName . "' is not expected to be called with the given parameters.");
1177
            } else {
1178
                $this->fail("Method '" . $methodName . "' is not expected to be called");
1179
            }
1180
        }
1181
    }
1182
1183
    private function compileContainer(ContainerBuilder $container) : void
1184
    {
1185
        $container->getCompilerPassConfig()->setOptimizationPasses([new ResolveChildDefinitionsPass()]);
1186
        $container->getCompilerPassConfig()->setRemovingPasses([]);
1187
        $container->compile();
1188
    }
1189
}
1190
1191
class DummySchemaAssetsFilter
1192
{
1193
    /** @var string */
1194
    private $tableToIgnore;
1195
1196
    public function __construct(string $tableToIgnore)
1197
    {
1198
        $this->tableToIgnore = $tableToIgnore;
1199
    }
1200
1201
    public function __invoke($assetName) : bool
1202
    {
1203
        if ($assetName instanceof AbstractAsset) {
1204
            $assetName = $assetName->getName();
1205
        }
1206
1207
        return $assetName !== $this->tableToIgnore;
1208
    }
1209
}
1210