Failed Conditions
Push — master ( 6744b4...2b8acb )
by Marco
60:45 queued 60:36
created

Tests/ORM/Mapping/AbstractMappingDriverTest.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Doctrine\Tests\ORM\Mapping;
4
5
use Doctrine\Common\Persistence\Mapping\RuntimeReflectionService;
6
use Doctrine\ORM\EntityManager;
7
use Doctrine\ORM\Events;
8
use Doctrine\ORM\Mapping\ClassMetadata;
9
use Doctrine\ORM\Mapping\ClassMetadataFactory;
10
use Doctrine\ORM\Mapping\ClassMetadataInfo;
11
use Doctrine\ORM\Mapping\DefaultNamingStrategy;
12
use Doctrine\ORM\Mapping\DiscriminatorColumn;
13
use Doctrine\ORM\Mapping\Id;
14
use Doctrine\ORM\Mapping\MappingException;
15
use Doctrine\ORM\Mapping\UnderscoreNamingStrategy;
16
use Doctrine\Tests\Models\Cache\City;
17
use Doctrine\Tests\Models\CMS\CmsAddress;
18
use Doctrine\Tests\Models\CMS\CmsAddressListener;
19
use Doctrine\Tests\Models\CMS\CmsUser;
20
use Doctrine\Tests\Models\Company\CompanyContract;
21
use Doctrine\Tests\Models\Company\CompanyContractListener;
22
use Doctrine\Tests\Models\Company\CompanyFixContract;
23
use Doctrine\Tests\Models\Company\CompanyFlexContract;
24
use Doctrine\Tests\Models\Company\CompanyFlexUltraContract;
25
use Doctrine\Tests\Models\Company\CompanyFlexUltraContractListener;
26
use Doctrine\Tests\Models\Company\CompanyPerson;
27
use Doctrine\Tests\Models\DDC1476\DDC1476EntityWithDefaultFieldType;
28
use Doctrine\Tests\Models\DDC2825\ExplicitSchemaAndTable;
29
use Doctrine\Tests\Models\DDC2825\SchemaAndTableInTableName;
30
use Doctrine\Tests\Models\DDC3579\DDC3579Admin;
31
use Doctrine\Tests\Models\DDC5934\DDC5934Contract;
32
use Doctrine\Tests\Models\DDC869\DDC869ChequePayment;
33
use Doctrine\Tests\Models\DDC869\DDC869CreditCardPayment;
34
use Doctrine\Tests\Models\DDC869\DDC869PaymentRepository;
35
use Doctrine\Tests\Models\DDC889\DDC889Class;
36
use Doctrine\Tests\Models\DDC889\DDC889Entity;
37
use Doctrine\Tests\Models\DDC964\DDC964Admin;
38
use Doctrine\Tests\Models\DDC964\DDC964Guest;
39
use Doctrine\Tests\OrmTestCase;
40
41
abstract class AbstractMappingDriverTest extends OrmTestCase
42
{
43
    abstract protected function _loadDriver();
44
45
    public function createClassMetadata($entityClassName)
46
    {
47
        $mappingDriver = $this->_loadDriver();
48
49
        $class = new ClassMetadata($entityClassName);
50
        $class->initializeReflection(new RuntimeReflectionService());
51
        $mappingDriver->loadMetadataForClass($entityClassName, $class);
52
53
        return $class;
54
    }
55
56
    /**
57
     * @param \Doctrine\ORM\EntityManager $entityClassName
58
     * @return \Doctrine\ORM\Mapping\ClassMetadataFactory
59
     */
60
    protected function createClassMetadataFactory(EntityManager $em = null)
61
    {
62
        $driver     = $this->_loadDriver();
63
        $em         = $em ?: $this->_getTestEntityManager();
64
        $factory    = new ClassMetadataFactory();
65
        $em->getConfiguration()->setMetadataDriverImpl($driver);
66
        $factory->setEntityManager($em);
67
68
        return $factory;
69
    }
70
71
    public function testEntityTableNameAndInheritance()
72
    {
73
        $class = $this->createClassMetadata(User::class);
74
75
        $this->assertEquals('cms_users', $class->getTableName());
76
        $this->assertEquals(ClassMetadata::INHERITANCE_TYPE_NONE, $class->inheritanceType);
77
78
        return $class;
79
    }
80
81
    /**
82
     * @depends testEntityTableNameAndInheritance
83
     * @param ClassMetadata $class
84
     */
85 View Code Duplication
    public function testEntityIndexes($class)
86
    {
87
        $this->assertArrayHasKey('indexes', $class->table, 'ClassMetadata should have indexes key in table property.');
88
        $this->assertEquals(
89
            [
90
            'name_idx' => ['columns' => ['name']],
91
            0 => ['columns' => ['user_email']]
92
            ], $class->table['indexes']);
93
94
        return $class;
95
    }
96
97 View Code Duplication
    public function testEntityIndexFlagsAndPartialIndexes()
98
    {
99
        $class = $this->createClassMetadata(Comment::class);
100
101
        $this->assertEquals(
102
            [
103
            0 => [
104
                'columns' => ['content'],
105
                'flags' => ['fulltext'],
106
                'options' => ['where' => 'content IS NOT NULL'],
107
            ]
108
            ], $class->table['indexes']);
109
    }
110
111
    /**
112
     * @depends testEntityTableNameAndInheritance
113
     * @param ClassMetadata $class
114
     */
115 View Code Duplication
    public function testEntityUniqueConstraints($class)
116
    {
117
        $this->assertArrayHasKey('uniqueConstraints', $class->table,
118
            'ClassMetadata should have uniqueConstraints key in table property when Unique Constraints are set.');
119
120
        $this->assertEquals(
121
            [
122
            "search_idx" => ["columns" => ["name", "user_email"], 'options' => ['where' => 'name IS NOT NULL']]
123
            ], $class->table['uniqueConstraints']);
124
125
        return $class;
126
    }
127
128
    /**
129
     * @depends testEntityTableNameAndInheritance
130
     * @param ClassMetadata $class
131
     */
132
    public function testEntityOptions($class)
133
    {
134
        $this->assertArrayHasKey('options', $class->table, 'ClassMetadata should have options key in table property.');
135
136
        $this->assertEquals(
137
            [
138
            'foo' => 'bar', 'baz' => ['key' => 'val']
139
            ], $class->table['options']);
140
141
        return $class;
142
    }
143
144
    /**
145
     * @depends testEntityOptions
146
     * @param ClassMetadata $class
147
     */
148
    public function testEntitySequence($class)
149
    {
150
        $this->assertInternalType('array', $class->sequenceGeneratorDefinition, 'No Sequence Definition set on this driver.');
151
        $this->assertEquals(
152
            [
153
                'sequenceName' => 'tablename_seq',
154
                'allocationSize' => 100,
155
                'initialValue' => 1,
156
            ],
157
            $class->sequenceGeneratorDefinition
158
        );
159
    }
160
161
    public function testEntityCustomGenerator()
162
    {
163
        $class = $this->createClassMetadata(Animal::class);
164
165
        $this->assertEquals(ClassMetadata::GENERATOR_TYPE_CUSTOM,
166
            $class->generatorType, "Generator Type");
167
        $this->assertEquals(
168
            ["class" => "stdClass"],
169
            $class->customGeneratorDefinition,
170
            "Custom Generator Definition");
171
    }
172
173
174
    /**
175
     * @depends testEntityTableNameAndInheritance
176
     * @param ClassMetadata $class
177
     */
178
    public function testFieldMappings($class)
179
    {
180
        $this->assertEquals(4, count($class->fieldMappings));
181
        $this->assertTrue(isset($class->fieldMappings['id']));
182
        $this->assertTrue(isset($class->fieldMappings['name']));
183
        $this->assertTrue(isset($class->fieldMappings['email']));
184
        $this->assertTrue(isset($class->fieldMappings['version']));
185
186
        return $class;
187
    }
188
189
    /**
190
     * @depends testFieldMappings
191
     * @param ClassMetadata $class
192
     */
193
    public function testVersionedField($class)
194
    {
195
        $this->assertTrue($class->isVersioned);
196
        $this->assertEquals("version", $class->versionField);
197
198
        $this->assertFalse(isset($class->fieldMappings['version']['version']));
199
    }
200
201
    /**
202
     * @depends testEntityTableNameAndInheritance
203
     * @param ClassMetadata $class
204
     */
205
    public function testFieldMappingsColumnNames($class)
206
    {
207
        $this->assertEquals("id", $class->fieldMappings['id']['columnName']);
208
        $this->assertEquals("name", $class->fieldMappings['name']['columnName']);
209
        $this->assertEquals("user_email", $class->fieldMappings['email']['columnName']);
210
211
        return $class;
212
    }
213
214
    /**
215
     * @depends testEntityTableNameAndInheritance
216
     * @param ClassMetadata $class
217
     */
218
    public function testStringFieldMappings($class)
219
    {
220
        $this->assertEquals('string', $class->fieldMappings['name']['type']);
221
        $this->assertEquals(50, $class->fieldMappings['name']['length']);
222
        $this->assertTrue($class->fieldMappings['name']['nullable']);
223
        $this->assertTrue($class->fieldMappings['name']['unique']);
224
225
        return $class;
226
    }
227
228
    /**
229
     * @depends testEntityTableNameAndInheritance
230
     *
231
     * @param ClassMetadata $class
232
     *
233
     * @return ClassMetadata
234
     */
235
    public function testFieldOptions(ClassMetadata $class)
236
    {
237
        $expected = ['foo' => 'bar', 'baz' => ['key' => 'val'], 'fixed' => false];
238
        $this->assertEquals($expected, $class->fieldMappings['name']['options']);
239
240
        return $class;
241
    }
242
243
    /**
244
     * @depends testEntityTableNameAndInheritance
245
     * @param ClassMetadata $class
246
     */
247
    public function testIdFieldOptions($class)
248
    {
249
        $this->assertEquals(['foo' => 'bar', 'unsigned' => false], $class->fieldMappings['id']['options']);
250
251
        return $class;
252
    }
253
254
    /**
255
     * @depends testFieldMappings
256
     * @param ClassMetadata $class
257
     */
258
    public function testIdentifier($class)
259
    {
260
        $this->assertEquals(['id'], $class->identifier);
261
        $this->assertEquals('integer', $class->fieldMappings['id']['type']);
262
        $this->assertEquals(ClassMetadata::GENERATOR_TYPE_AUTO, $class->generatorType, "ID-Generator is not ClassMetadata::GENERATOR_TYPE_AUTO");
263
264
        return $class;
265
    }
266
267
    /**
268
     * @group #6129
269
     *
270
     * @return ClassMetadata
271
     */
272
    public function testBooleanValuesForOptionIsSetCorrectly()
273
    {
274
        $class = $this->createClassMetadata(User::class);
275
276
        $this->assertInternalType('bool', $class->fieldMappings['id']['options']['unsigned']);
277
        $this->assertFalse($class->fieldMappings['id']['options']['unsigned']);
278
279
        $this->assertInternalType('bool', $class->fieldMappings['name']['options']['fixed']);
280
        $this->assertFalse($class->fieldMappings['name']['options']['fixed']);
281
282
        return $class;
283
    }
284
285
    /**
286
     * @depends testIdentifier
287
     * @param ClassMetadata $class
288
     */
289
    public function testAssociations($class)
290
    {
291
        $this->assertEquals(3, count($class->associationMappings));
292
293
        return $class;
294
    }
295
296
    /**
297
     * @depends testAssociations
298
     * @param ClassMetadata $class
299
     */
300 View Code Duplication
    public function testOwningOneToOneAssociation($class)
301
    {
302
        $this->assertTrue(isset($class->associationMappings['address']));
303
        $this->assertTrue($class->associationMappings['address']['isOwningSide']);
304
        $this->assertEquals('user', $class->associationMappings['address']['inversedBy']);
305
        // Check cascading
306
        $this->assertTrue($class->associationMappings['address']['isCascadeRemove']);
307
        $this->assertFalse($class->associationMappings['address']['isCascadePersist']);
308
        $this->assertFalse($class->associationMappings['address']['isCascadeRefresh']);
309
        $this->assertFalse($class->associationMappings['address']['isCascadeDetach']);
310
        $this->assertFalse($class->associationMappings['address']['isCascadeMerge']);
311
312
        return $class;
313
    }
314
315
    /**
316
     * @depends testOwningOneToOneAssociation
317
     * @param ClassMetadata $class
318
     */
319
    public function testInverseOneToManyAssociation($class)
320
    {
321
        $this->assertTrue(isset($class->associationMappings['phonenumbers']));
322
        $this->assertFalse($class->associationMappings['phonenumbers']['isOwningSide']);
323
        $this->assertTrue($class->associationMappings['phonenumbers']['isCascadePersist']);
324
        $this->assertTrue($class->associationMappings['phonenumbers']['isCascadeRemove']);
325
        $this->assertFalse($class->associationMappings['phonenumbers']['isCascadeRefresh']);
326
        $this->assertFalse($class->associationMappings['phonenumbers']['isCascadeDetach']);
327
        $this->assertFalse($class->associationMappings['phonenumbers']['isCascadeMerge']);
328
        $this->assertTrue($class->associationMappings['phonenumbers']['orphanRemoval']);
329
330
        // Test Order By
331
        $this->assertEquals(['number' => 'ASC'], $class->associationMappings['phonenumbers']['orderBy']);
332
333
        return $class;
334
    }
335
336
    /**
337
     * @depends testInverseOneToManyAssociation
338
     * @param ClassMetadata $class
339
     */
340 View Code Duplication
    public function testManyToManyAssociationWithCascadeAll($class)
341
    {
342
        $this->assertTrue(isset($class->associationMappings['groups']));
343
        $this->assertTrue($class->associationMappings['groups']['isOwningSide']);
344
        // Make sure that cascade-all works as expected
345
        $this->assertTrue($class->associationMappings['groups']['isCascadeRemove']);
346
        $this->assertTrue($class->associationMappings['groups']['isCascadePersist']);
347
        $this->assertTrue($class->associationMappings['groups']['isCascadeRefresh']);
348
        $this->assertTrue($class->associationMappings['groups']['isCascadeDetach']);
349
        $this->assertTrue($class->associationMappings['groups']['isCascadeMerge']);
350
351
        $this->assertFalse(isset($class->associationMappings['groups']['orderBy']));
352
353
        return $class;
354
    }
355
356
    /**
357
     * @depends testManyToManyAssociationWithCascadeAll
358
     * @param ClassMetadata $class
359
     */
360
    public function testLifecycleCallbacks($class)
361
    {
362
        $this->assertEquals(count($class->lifecycleCallbacks), 2);
363
        $this->assertEquals($class->lifecycleCallbacks['prePersist'][0], 'doStuffOnPrePersist');
364
        $this->assertEquals($class->lifecycleCallbacks['postPersist'][0], 'doStuffOnPostPersist');
365
366
        return $class;
367
    }
368
369
    /**
370
     * @depends testManyToManyAssociationWithCascadeAll
371
     * @param ClassMetadata $class
372
     */
373
    public function testLifecycleCallbacksSupportMultipleMethodNames($class)
374
    {
375
        $this->assertEquals(count($class->lifecycleCallbacks['prePersist']), 2);
376
        $this->assertEquals($class->lifecycleCallbacks['prePersist'][1], 'doOtherStuffOnPrePersistToo');
377
378
        return $class;
379
    }
380
381
    /**
382
     * @depends testLifecycleCallbacksSupportMultipleMethodNames
383
     * @param ClassMetadata $class
384
     */
385
    public function testJoinColumnUniqueAndNullable($class)
386
    {
387
        // Non-Nullability of Join Column
388
        $this->assertFalse($class->associationMappings['groups']['joinTable']['joinColumns'][0]['nullable']);
389
        $this->assertFalse($class->associationMappings['groups']['joinTable']['joinColumns'][0]['unique']);
390
391
        return $class;
392
    }
393
394
    /**
395
     * @depends testJoinColumnUniqueAndNullable
396
     * @param ClassMetadata $class
397
     */
398
    public function testColumnDefinition($class)
399
    {
400
        $this->assertEquals("CHAR(32) NOT NULL", $class->fieldMappings['email']['columnDefinition']);
401
        $this->assertEquals("INT NULL", $class->associationMappings['groups']['joinTable']['inverseJoinColumns'][0]['columnDefinition']);
402
403
        return $class;
404
    }
405
406
    /**
407
     * @depends testColumnDefinition
408
     * @param ClassMetadata $class
409
     */
410
    public function testJoinColumnOnDelete($class)
411
    {
412
        $this->assertEquals('CASCADE', $class->associationMappings['address']['joinColumns'][0]['onDelete']);
413
414
        return $class;
415
    }
416
417
    /**
418
     * @group DDC-514
419
     */
420
    public function testDiscriminatorColumnDefaults()
421
    {
422
        if (strpos(get_class($this), 'PHPMappingDriver') !== false) {
423
            $this->markTestSkipped('PHP Mapping Drivers have no defaults.');
424
        }
425
426
        $class = $this->createClassMetadata(Animal::class);
427
428
        $this->assertEquals(
429
            ['name' => 'discr', 'type' => 'string', 'length' => '32', 'fieldName' => 'discr', 'columnDefinition' => null],
430
            $class->discriminatorColumn
431
        );
432
    }
433
434
    /**
435
     * @group DDC-869
436
     */
437
    public function testMappedSuperclassWithRepository()
438
    {
439
        $em         = $this->_getTestEntityManager();
440
        $factory    = $this->createClassMetadataFactory($em);
441
442
443
        $class = $factory->getMetadataFor(DDC869CreditCardPayment::class);
444
445
        $this->assertTrue(isset($class->fieldMappings['id']));
446
        $this->assertTrue(isset($class->fieldMappings['value']));
447
        $this->assertTrue(isset($class->fieldMappings['creditCardNumber']));
448
        $this->assertEquals($class->customRepositoryClassName, DDC869PaymentRepository::class);
449
        $this->assertInstanceOf(DDC869PaymentRepository::class, $em->getRepository(DDC869CreditCardPayment::class));
450
        $this->assertTrue($em->getRepository(DDC869ChequePayment::class)->isTrue());
451
452
453
454
        $class = $factory->getMetadataFor(DDC869ChequePayment::class);
455
456
        $this->assertTrue(isset($class->fieldMappings['id']));
457
        $this->assertTrue(isset($class->fieldMappings['value']));
458
        $this->assertTrue(isset($class->fieldMappings['serialNumber']));
459
        $this->assertEquals($class->customRepositoryClassName, DDC869PaymentRepository::class);
460
        $this->assertInstanceOf(DDC869PaymentRepository::class, $em->getRepository(DDC869ChequePayment::class));
461
        $this->assertTrue($em->getRepository(DDC869ChequePayment::class)->isTrue());
462
    }
463
464
    /**
465
     * @group DDC-1476
466
     */
467
    public function testDefaultFieldType()
468
    {
469
        $factory    = $this->createClassMetadataFactory();
470
        $class      = $factory->getMetadataFor(DDC1476EntityWithDefaultFieldType::class);
471
472
473
        $this->assertArrayHasKey('id', $class->fieldMappings);
474
        $this->assertArrayHasKey('name', $class->fieldMappings);
475
476
477
        $this->assertArrayHasKey('type', $class->fieldMappings['id']);
478
        $this->assertArrayHasKey('type', $class->fieldMappings['name']);
479
480
        $this->assertEquals('string', $class->fieldMappings['id']['type']);
481
        $this->assertEquals('string', $class->fieldMappings['name']['type']);
482
483
484
485
        $this->assertArrayHasKey('fieldName', $class->fieldMappings['id']);
486
        $this->assertArrayHasKey('fieldName', $class->fieldMappings['name']);
487
488
        $this->assertEquals('id', $class->fieldMappings['id']['fieldName']);
489
        $this->assertEquals('name', $class->fieldMappings['name']['fieldName']);
490
491
492
493
        $this->assertArrayHasKey('columnName', $class->fieldMappings['id']);
494
        $this->assertArrayHasKey('columnName', $class->fieldMappings['name']);
495
496
        $this->assertEquals('id', $class->fieldMappings['id']['columnName']);
497
        $this->assertEquals('name', $class->fieldMappings['name']['columnName']);
498
499
        $this->assertEquals(ClassMetadataInfo::GENERATOR_TYPE_NONE, $class->generatorType);
500
    }
501
502
    /**
503
     * @group DDC-1170
504
     */
505
    public function testIdentifierColumnDefinition()
506
    {
507
        $class = $this->createClassMetadata(DDC1170Entity::class);
508
509
510
        $this->assertArrayHasKey('id', $class->fieldMappings);
511
        $this->assertArrayHasKey('value', $class->fieldMappings);
512
513
        $this->assertArrayHasKey('columnDefinition', $class->fieldMappings['id']);
514
        $this->assertArrayHasKey('columnDefinition', $class->fieldMappings['value']);
515
516
        $this->assertEquals("INT unsigned NOT NULL", $class->fieldMappings['id']['columnDefinition']);
517
        $this->assertEquals("VARCHAR(255) NOT NULL", $class->fieldMappings['value']['columnDefinition']);
518
    }
519
520
    /**
521
     * @group DDC-559
522
     */
523
    public function testNamingStrategy()
524
    {
525
        $em         = $this->_getTestEntityManager();
526
        $factory    = $this->createClassMetadataFactory($em);
527
528
529
        $this->assertInstanceOf(DefaultNamingStrategy::class, $em->getConfiguration()->getNamingStrategy());
530
        $em->getConfiguration()->setNamingStrategy(new UnderscoreNamingStrategy(CASE_UPPER));
531
        $this->assertInstanceOf(UnderscoreNamingStrategy::class, $em->getConfiguration()->getNamingStrategy());
532
533
        $class = $factory->getMetadataFor(DDC1476EntityWithDefaultFieldType::class);
534
535
        $this->assertEquals('ID', $class->getColumnName('id'));
536
        $this->assertEquals('NAME', $class->getColumnName('name'));
537
        $this->assertEquals('DDC1476ENTITY_WITH_DEFAULT_FIELD_TYPE', $class->table['name']);
538
    }
539
540
    /**
541
     * @group DDC-807
542
     * @group DDC-553
543
     */
544
    public function testDiscriminatorColumnDefinition()
545
    {
546
        $class = $this->createClassMetadata(DDC807Entity::class);
547
548
        $this->assertArrayHasKey('columnDefinition', $class->discriminatorColumn);
549
        $this->assertArrayHasKey('name', $class->discriminatorColumn);
550
551
        $this->assertEquals("ENUM('ONE','TWO')", $class->discriminatorColumn['columnDefinition']);
552
        $this->assertEquals("dtype", $class->discriminatorColumn['name']);
553
    }
554
555
    /**
556
     * @group DDC-889
557
     */
558
    public function testInvalidEntityOrMappedSuperClassShouldMentionParentClasses()
559
    {
560
        $this->expectException(MappingException::class);
561
        $this->expectExceptionMessage('Class "Doctrine\Tests\Models\DDC889\DDC889Class" sub class of "Doctrine\Tests\Models\DDC889\DDC889SuperClass" is not a valid entity or mapped super class.');
562
563
        $this->createClassMetadata(DDC889Class::class);
564
    }
565
566
    /**
567
     * @group DDC-889
568
     */
569
    public function testIdentifierRequiredShouldMentionParentClasses()
570
    {
571
        $factory = $this->createClassMetadataFactory();
572
573
        $this->expectException(MappingException::class);
574
        $this->expectExceptionMessage('No identifier/primary key specified for Entity "Doctrine\Tests\Models\DDC889\DDC889Entity" sub class of "Doctrine\Tests\Models\DDC889\DDC889SuperClass". Every Entity must have an identifier/primary key.');
575
576
        $factory->getMetadataFor(DDC889Entity::class);
577
    }
578
579
    public function testNamedQuery()
580
    {
581
        $driver = $this->_loadDriver();
582
        $class = $this->createClassMetadata(User::class);
583
584
        $this->assertCount(1, $class->getNamedQueries(), sprintf("Named queries not processed correctly by driver %s", get_class($driver)));
585
    }
586
587
    /**
588
     * @group DDC-1663
589
     */
590
    public function testNamedNativeQuery()
591
    {
592
593
        $class = $this->createClassMetadata(CmsAddress::class);
594
595
        //named native query
596
        $this->assertCount(3, $class->namedNativeQueries);
597
        $this->assertArrayHasKey('find-all', $class->namedNativeQueries);
598
        $this->assertArrayHasKey('find-by-id', $class->namedNativeQueries);
599
600
601
        $findAllQuery = $class->getNamedNativeQuery('find-all');
602
        $this->assertEquals('find-all', $findAllQuery['name']);
603
        $this->assertEquals('mapping-find-all', $findAllQuery['resultSetMapping']);
604
        $this->assertEquals('SELECT id, country, city FROM cms_addresses', $findAllQuery['query']);
605
606
        $findByIdQuery = $class->getNamedNativeQuery('find-by-id');
607
        $this->assertEquals('find-by-id', $findByIdQuery['name']);
608
        $this->assertEquals(CmsAddress::class,$findByIdQuery['resultClass']);
609
        $this->assertEquals('SELECT * FROM cms_addresses WHERE id = ?',  $findByIdQuery['query']);
610
611
        $countQuery = $class->getNamedNativeQuery('count');
612
        $this->assertEquals('count', $countQuery['name']);
613
        $this->assertEquals('mapping-count', $countQuery['resultSetMapping']);
614
        $this->assertEquals('SELECT COUNT(*) AS count FROM cms_addresses',  $countQuery['query']);
615
616
        // result set mapping
617
        $this->assertCount(3, $class->sqlResultSetMappings);
618
        $this->assertArrayHasKey('mapping-count', $class->sqlResultSetMappings);
619
        $this->assertArrayHasKey('mapping-find-all', $class->sqlResultSetMappings);
620
        $this->assertArrayHasKey('mapping-without-fields', $class->sqlResultSetMappings);
621
622
        $findAllMapping = $class->getSqlResultSetMapping('mapping-find-all');
623
        $this->assertEquals('mapping-find-all', $findAllMapping['name']);
624
        $this->assertEquals(CmsAddress::class, $findAllMapping['entities'][0]['entityClass']);
625
        $this->assertEquals(['name'=>'id','column'=>'id'], $findAllMapping['entities'][0]['fields'][0]);
626
        $this->assertEquals(['name'=>'city','column'=>'city'], $findAllMapping['entities'][0]['fields'][1]);
627
        $this->assertEquals(['name'=>'country','column'=>'country'], $findAllMapping['entities'][0]['fields'][2]);
628
629
        $withoutFieldsMapping = $class->getSqlResultSetMapping('mapping-without-fields');
630
        $this->assertEquals('mapping-without-fields', $withoutFieldsMapping['name']);
631
        $this->assertEquals(CmsAddress::class, $withoutFieldsMapping['entities'][0]['entityClass']);
632
        $this->assertEquals([], $withoutFieldsMapping['entities'][0]['fields']);
633
634
        $countMapping = $class->getSqlResultSetMapping('mapping-count');
635
        $this->assertEquals('mapping-count', $countMapping['name']);
636
        $this->assertEquals(['name'=>'count'], $countMapping['columns'][0]);
637
638
    }
639
640
    /**
641
     * @group DDC-1663
642
     */
643
    public function testSqlResultSetMapping()
644
    {
645
646
        $userMetadata   = $this->createClassMetadata(CmsUser::class);
647
        $personMetadata = $this->createClassMetadata(CompanyPerson::class);
648
649
        // user asserts
650
        $this->assertCount(4, $userMetadata->getSqlResultSetMappings());
651
652
        $mapping = $userMetadata->getSqlResultSetMapping('mappingJoinedAddress');
653
        $this->assertEquals([],$mapping['columns']);
654
        $this->assertEquals('mappingJoinedAddress', $mapping['name']);
655
        $this->assertNull($mapping['entities'][0]['discriminatorColumn']);
656
        $this->assertEquals(['name'=>'id','column'=>'id'],                     $mapping['entities'][0]['fields'][0]);
657
        $this->assertEquals(['name'=>'name','column'=>'name'],                 $mapping['entities'][0]['fields'][1]);
658
        $this->assertEquals(['name'=>'status','column'=>'status'],             $mapping['entities'][0]['fields'][2]);
659
        $this->assertEquals(['name'=>'address.zip','column'=>'zip'],           $mapping['entities'][0]['fields'][3]);
660
        $this->assertEquals(['name'=>'address.city','column'=>'city'],         $mapping['entities'][0]['fields'][4]);
661
        $this->assertEquals(['name'=>'address.country','column'=>'country'],   $mapping['entities'][0]['fields'][5]);
662
        $this->assertEquals(['name'=>'address.id','column'=>'a_id'],           $mapping['entities'][0]['fields'][6]);
663
        $this->assertEquals($userMetadata->name,                                    $mapping['entities'][0]['entityClass']);
664
665
666
        $mapping = $userMetadata->getSqlResultSetMapping('mappingJoinedPhonenumber');
667
        $this->assertEquals([],$mapping['columns']);
668
        $this->assertEquals('mappingJoinedPhonenumber', $mapping['name']);
669
        $this->assertNull($mapping['entities'][0]['discriminatorColumn']);
670
        $this->assertEquals(['name'=>'id','column'=>'id'],                             $mapping['entities'][0]['fields'][0]);
671
        $this->assertEquals(['name'=>'name','column'=>'name'],                         $mapping['entities'][0]['fields'][1]);
672
        $this->assertEquals(['name'=>'status','column'=>'status'],                     $mapping['entities'][0]['fields'][2]);
673
        $this->assertEquals(['name'=>'phonenumbers.phonenumber','column'=>'number'],   $mapping['entities'][0]['fields'][3]);
674
        $this->assertEquals($userMetadata->name,                                            $mapping['entities'][0]['entityClass']);
675
676
        $mapping = $userMetadata->getSqlResultSetMapping('mappingUserPhonenumberCount');
677
        $this->assertEquals(['name'=>'numphones'],$mapping['columns'][0]);
678
        $this->assertEquals('mappingUserPhonenumberCount', $mapping['name']);
679
        $this->assertNull($mapping['entities'][0]['discriminatorColumn']);
680
        $this->assertEquals(['name'=>'id','column'=>'id'],         $mapping['entities'][0]['fields'][0]);
681
        $this->assertEquals(['name'=>'name','column'=>'name'],     $mapping['entities'][0]['fields'][1]);
682
        $this->assertEquals(['name'=>'status','column'=>'status'], $mapping['entities'][0]['fields'][2]);
683
        $this->assertEquals($userMetadata->name,                        $mapping['entities'][0]['entityClass']);
684
685
        $mapping = $userMetadata->getSqlResultSetMapping('mappingMultipleJoinsEntityResults');
686
        $this->assertEquals(['name'=>'numphones'],$mapping['columns'][0]);
687
        $this->assertEquals('mappingMultipleJoinsEntityResults', $mapping['name']);
688
        $this->assertNull($mapping['entities'][0]['discriminatorColumn']);
689
        $this->assertEquals(['name'=>'id','column'=>'u_id'],           $mapping['entities'][0]['fields'][0]);
690
        $this->assertEquals(['name'=>'name','column'=>'u_name'],       $mapping['entities'][0]['fields'][1]);
691
        $this->assertEquals(['name'=>'status','column'=>'u_status'],   $mapping['entities'][0]['fields'][2]);
692
        $this->assertEquals($userMetadata->name,                            $mapping['entities'][0]['entityClass']);
693
        $this->assertNull($mapping['entities'][1]['discriminatorColumn']);
694
        $this->assertEquals(['name'=>'id','column'=>'a_id'],           $mapping['entities'][1]['fields'][0]);
695
        $this->assertEquals(['name'=>'zip','column'=>'a_zip'],         $mapping['entities'][1]['fields'][1]);
696
        $this->assertEquals(['name'=>'country','column'=>'a_country'], $mapping['entities'][1]['fields'][2]);
697
        $this->assertEquals(CmsAddress::class,         $mapping['entities'][1]['entityClass']);
698
699
        //person asserts
700
        $this->assertCount(1, $personMetadata->getSqlResultSetMappings());
701
702
        $mapping = $personMetadata->getSqlResultSetMapping('mappingFetchAll');
703
        $this->assertEquals([],$mapping['columns']);
704
        $this->assertEquals('mappingFetchAll', $mapping['name']);
705
        $this->assertEquals('discriminator',                            $mapping['entities'][0]['discriminatorColumn']);
706
        $this->assertEquals(['name'=>'id','column'=>'id'],         $mapping['entities'][0]['fields'][0]);
707
        $this->assertEquals(['name'=>'name','column'=>'name'],     $mapping['entities'][0]['fields'][1]);
708
        $this->assertEquals($personMetadata->name,                      $mapping['entities'][0]['entityClass']);
709
    }
710
711
    /*
712
     * @group DDC-964
713
     */
714
    public function testAssociationOverridesMapping()
715
    {
716
717
        $factory        = $this->createClassMetadataFactory();
718
        $adminMetadata  = $factory->getMetadataFor(DDC964Admin::class);
719
        $guestMetadata  = $factory->getMetadataFor(DDC964Guest::class);
720
721
722
        // assert groups association mappings
723
        $this->assertArrayHasKey('groups', $guestMetadata->associationMappings);
724
        $this->assertArrayHasKey('groups', $adminMetadata->associationMappings);
725
726
        $guestGroups = $guestMetadata->associationMappings['groups'];
727
        $adminGroups = $adminMetadata->associationMappings['groups'];
728
729
        // assert not override attributes
730
        $this->assertEquals($guestGroups['fieldName'], $adminGroups['fieldName']);
731
        $this->assertEquals($guestGroups['type'], $adminGroups['type']);
732
        $this->assertEquals($guestGroups['mappedBy'], $adminGroups['mappedBy']);
733
        $this->assertEquals($guestGroups['inversedBy'], $adminGroups['inversedBy']);
734
        $this->assertEquals($guestGroups['isOwningSide'], $adminGroups['isOwningSide']);
735
        $this->assertEquals($guestGroups['fetch'], $adminGroups['fetch']);
736
        $this->assertEquals($guestGroups['isCascadeRemove'], $adminGroups['isCascadeRemove']);
737
        $this->assertEquals($guestGroups['isCascadePersist'], $adminGroups['isCascadePersist']);
738
        $this->assertEquals($guestGroups['isCascadeRefresh'], $adminGroups['isCascadeRefresh']);
739
        $this->assertEquals($guestGroups['isCascadeMerge'], $adminGroups['isCascadeMerge']);
740
        $this->assertEquals($guestGroups['isCascadeDetach'], $adminGroups['isCascadeDetach']);
741
742
         // assert not override attributes
743
        $this->assertEquals('ddc964_users_groups', $guestGroups['joinTable']['name']);
744
        $this->assertEquals('user_id', $guestGroups['joinTable']['joinColumns'][0]['name']);
745
        $this->assertEquals('group_id', $guestGroups['joinTable']['inverseJoinColumns'][0]['name']);
746
747
        $this->assertEquals(['user_id'=>'id'], $guestGroups['relationToSourceKeyColumns']);
748
        $this->assertEquals(['group_id'=>'id'], $guestGroups['relationToTargetKeyColumns']);
749
        $this->assertEquals(['user_id','group_id'], $guestGroups['joinTableColumns']);
750
751
752
        $this->assertEquals('ddc964_users_admingroups', $adminGroups['joinTable']['name']);
753
        $this->assertEquals('adminuser_id', $adminGroups['joinTable']['joinColumns'][0]['name']);
754
        $this->assertEquals('admingroup_id', $adminGroups['joinTable']['inverseJoinColumns'][0]['name']);
755
756
        $this->assertEquals(['adminuser_id'=>'id'], $adminGroups['relationToSourceKeyColumns']);
757
        $this->assertEquals(['admingroup_id'=>'id'], $adminGroups['relationToTargetKeyColumns']);
758
        $this->assertEquals(['adminuser_id','admingroup_id'], $adminGroups['joinTableColumns']);
759
760
761
        // assert address association mappings
762
        $this->assertArrayHasKey('address', $guestMetadata->associationMappings);
763
        $this->assertArrayHasKey('address', $adminMetadata->associationMappings);
764
765
        $guestAddress = $guestMetadata->associationMappings['address'];
766
        $adminAddress = $adminMetadata->associationMappings['address'];
767
768
        // assert not override attributes
769
        $this->assertEquals($guestAddress['fieldName'], $adminAddress['fieldName']);
770
        $this->assertEquals($guestAddress['type'], $adminAddress['type']);
771
        $this->assertEquals($guestAddress['mappedBy'], $adminAddress['mappedBy']);
772
        $this->assertEquals($guestAddress['inversedBy'], $adminAddress['inversedBy']);
773
        $this->assertEquals($guestAddress['isOwningSide'], $adminAddress['isOwningSide']);
774
        $this->assertEquals($guestAddress['fetch'], $adminAddress['fetch']);
775
        $this->assertEquals($guestAddress['isCascadeRemove'], $adminAddress['isCascadeRemove']);
776
        $this->assertEquals($guestAddress['isCascadePersist'], $adminAddress['isCascadePersist']);
777
        $this->assertEquals($guestAddress['isCascadeRefresh'], $adminAddress['isCascadeRefresh']);
778
        $this->assertEquals($guestAddress['isCascadeMerge'], $adminAddress['isCascadeMerge']);
779
        $this->assertEquals($guestAddress['isCascadeDetach'], $adminAddress['isCascadeDetach']);
780
781
        // assert override
782
        $this->assertEquals('address_id', $guestAddress['joinColumns'][0]['name']);
783
        $this->assertEquals(['address_id'=>'id'], $guestAddress['sourceToTargetKeyColumns']);
784
        $this->assertEquals(['address_id'=>'address_id'], $guestAddress['joinColumnFieldNames']);
785
        $this->assertEquals(['id'=>'address_id'], $guestAddress['targetToSourceKeyColumns']);
786
787
788
        $this->assertEquals('adminaddress_id', $adminAddress['joinColumns'][0]['name']);
789
        $this->assertEquals(['adminaddress_id'=>'id'], $adminAddress['sourceToTargetKeyColumns']);
790
        $this->assertEquals(['adminaddress_id'=>'adminaddress_id'], $adminAddress['joinColumnFieldNames']);
791
        $this->assertEquals(['id'=>'adminaddress_id'], $adminAddress['targetToSourceKeyColumns']);
792
    }
793
794
    /*
795
     * @group DDC-3579
796
     */
797
    public function testInversedByOverrideMapping()
798
    {
799
800
        $factory        = $this->createClassMetadataFactory();
801
        $adminMetadata  = $factory->getMetadataFor(DDC3579Admin::class);
802
803
        // assert groups association mappings
804
        $this->assertArrayHasKey('groups', $adminMetadata->associationMappings);
805
        $adminGroups = $adminMetadata->associationMappings['groups'];
806
807
        // assert override
808
        $this->assertEquals('admins', $adminGroups['inversedBy']);
809
    }
810
811
    /**
812
     * @group DDC-5934
813
     */
814
    public function testFetchOverrideMapping()
815
    {
816
        // check override metadata
817
        $contractMetadata = $this->createClassMetadataFactory()->getMetadataFor(DDC5934Contract::class);
818
819
        $this->assertArrayHasKey('members', $contractMetadata->associationMappings);
0 ignored issues
show
Accessing associationMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
820
        $this->assertSame(ClassMetadata::FETCH_EXTRA_LAZY, $contractMetadata->associationMappings['members']['fetch']);
0 ignored issues
show
Accessing associationMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
821
    }
822
823
    /**
824
     * @group DDC-964
825
     */
826
    public function testAttributeOverridesMapping()
827
    {
828
829
        $factory       = $this->createClassMetadataFactory();
830
        $guestMetadata = $factory->getMetadataFor(DDC964Guest::class);
831
        $adminMetadata = $factory->getMetadataFor(DDC964Admin::class);
832
833
        $this->assertTrue($adminMetadata->fieldMappings['id']['id']);
834
        $this->assertEquals('id', $adminMetadata->fieldMappings['id']['fieldName']);
835
        $this->assertEquals('user_id', $adminMetadata->fieldMappings['id']['columnName']);
836
        $this->assertEquals(['user_id'=>'id','user_name'=>'name'], $adminMetadata->fieldNames);
837
        $this->assertEquals(['id'=>'user_id','name'=>'user_name'], $adminMetadata->columnNames);
838
        $this->assertEquals(150, $adminMetadata->fieldMappings['id']['length']);
839
840
841
        $this->assertEquals('name', $adminMetadata->fieldMappings['name']['fieldName']);
842
        $this->assertEquals('user_name', $adminMetadata->fieldMappings['name']['columnName']);
843
        $this->assertEquals(250, $adminMetadata->fieldMappings['name']['length']);
844
        $this->assertTrue($adminMetadata->fieldMappings['name']['nullable']);
845
        $this->assertFalse($adminMetadata->fieldMappings['name']['unique']);
846
847
848
        $this->assertTrue($guestMetadata->fieldMappings['id']['id']);
849
        $this->assertEquals('guest_id', $guestMetadata->fieldMappings['id']['columnName']);
850
        $this->assertEquals('id', $guestMetadata->fieldMappings['id']['fieldName']);
851
        $this->assertEquals(['guest_id'=>'id','guest_name'=>'name'], $guestMetadata->fieldNames);
852
        $this->assertEquals(['id'=>'guest_id','name'=>'guest_name'], $guestMetadata->columnNames);
853
        $this->assertEquals(140, $guestMetadata->fieldMappings['id']['length']);
854
855
        $this->assertEquals('name', $guestMetadata->fieldMappings['name']['fieldName']);
856
        $this->assertEquals('guest_name', $guestMetadata->fieldMappings['name']['columnName']);
857
        $this->assertEquals(240, $guestMetadata->fieldMappings['name']['length']);
858
        $this->assertFalse($guestMetadata->fieldMappings['name']['nullable']);
859
        $this->assertTrue($guestMetadata->fieldMappings['name']['unique']);
860
    }
861
862
    /**
863
     * @group DDC-1955
864
     */
865
    public function testEntityListeners()
866
    {
867
        $em         = $this->_getTestEntityManager();
868
        $factory    = $this->createClassMetadataFactory($em);
869
        $superClass = $factory->getMetadataFor(CompanyContract::class);
870
        $flexClass  = $factory->getMetadataFor(CompanyFixContract::class);
871
        $fixClass   = $factory->getMetadataFor(CompanyFlexContract::class);
872
        $ultraClass = $factory->getMetadataFor(CompanyFlexUltraContract::class);
873
874
        $this->assertArrayHasKey(Events::prePersist, $superClass->entityListeners);
875
        $this->assertArrayHasKey(Events::postPersist, $superClass->entityListeners);
876
877
        $this->assertCount(1, $superClass->entityListeners[Events::prePersist]);
878
        $this->assertCount(1, $superClass->entityListeners[Events::postPersist]);
879
880
        $postPersist = $superClass->entityListeners[Events::postPersist][0];
881
        $prePersist  = $superClass->entityListeners[Events::prePersist][0];
882
883
        $this->assertEquals(CompanyContractListener::class, $postPersist['class']);
884
        $this->assertEquals(CompanyContractListener::class, $prePersist['class']);
885
        $this->assertEquals('postPersistHandler', $postPersist['method']);
886
        $this->assertEquals('prePersistHandler', $prePersist['method']);
887
888
        //Inherited listeners
889
        $this->assertEquals($fixClass->entityListeners, $superClass->entityListeners);
890
        $this->assertEquals($flexClass->entityListeners, $superClass->entityListeners);
891
    }
892
893
    /**
894
     * @group DDC-1955
895
     */
896
    public function testEntityListenersOverride()
897
    {
898
        $em         = $this->_getTestEntityManager();
899
        $factory    = $this->createClassMetadataFactory($em);
900
        $ultraClass = $factory->getMetadataFor(CompanyFlexUltraContract::class);
901
902
        //overridden listeners
903
        $this->assertArrayHasKey(Events::postPersist, $ultraClass->entityListeners);
904
        $this->assertArrayHasKey(Events::prePersist, $ultraClass->entityListeners);
905
906
        $this->assertCount(1, $ultraClass->entityListeners[Events::postPersist]);
907
        $this->assertCount(3, $ultraClass->entityListeners[Events::prePersist]);
908
909
        $postPersist = $ultraClass->entityListeners[Events::postPersist][0];
910
        $prePersist  = $ultraClass->entityListeners[Events::prePersist][0];
911
912
        $this->assertEquals(CompanyContractListener::class, $postPersist['class']);
913
        $this->assertEquals(CompanyContractListener::class, $prePersist['class']);
914
        $this->assertEquals('postPersistHandler', $postPersist['method']);
915
        $this->assertEquals('prePersistHandler', $prePersist['method']);
916
917
        $prePersist = $ultraClass->entityListeners[Events::prePersist][1];
918
        $this->assertEquals(CompanyFlexUltraContractListener::class, $prePersist['class']);
919
        $this->assertEquals('prePersistHandler1', $prePersist['method']);
920
921
        $prePersist = $ultraClass->entityListeners[Events::prePersist][2];
922
        $this->assertEquals(CompanyFlexUltraContractListener::class, $prePersist['class']);
923
        $this->assertEquals('prePersistHandler2', $prePersist['method']);
924
    }
925
926
927
    /**
928
     * @group DDC-1955
929
     */
930
    public function testEntityListenersNamingConvention()
931
    {
932
        $em         = $this->_getTestEntityManager();
933
        $factory    = $this->createClassMetadataFactory($em);
934
        $metadata   = $factory->getMetadataFor(CmsAddress::class);
935
936
        $this->assertArrayHasKey(Events::postPersist, $metadata->entityListeners);
937
        $this->assertArrayHasKey(Events::prePersist, $metadata->entityListeners);
938
        $this->assertArrayHasKey(Events::postUpdate, $metadata->entityListeners);
939
        $this->assertArrayHasKey(Events::preUpdate, $metadata->entityListeners);
940
        $this->assertArrayHasKey(Events::postRemove, $metadata->entityListeners);
941
        $this->assertArrayHasKey(Events::preRemove, $metadata->entityListeners);
942
        $this->assertArrayHasKey(Events::postLoad, $metadata->entityListeners);
943
        $this->assertArrayHasKey(Events::preFlush, $metadata->entityListeners);
944
945
        $this->assertCount(1, $metadata->entityListeners[Events::postPersist]);
946
        $this->assertCount(1, $metadata->entityListeners[Events::prePersist]);
947
        $this->assertCount(1, $metadata->entityListeners[Events::postUpdate]);
948
        $this->assertCount(1, $metadata->entityListeners[Events::preUpdate]);
949
        $this->assertCount(1, $metadata->entityListeners[Events::postRemove]);
950
        $this->assertCount(1, $metadata->entityListeners[Events::preRemove]);
951
        $this->assertCount(1, $metadata->entityListeners[Events::postLoad]);
952
        $this->assertCount(1, $metadata->entityListeners[Events::preFlush]);
953
954
        $postPersist = $metadata->entityListeners[Events::postPersist][0];
955
        $prePersist  = $metadata->entityListeners[Events::prePersist][0];
956
        $postUpdate  = $metadata->entityListeners[Events::postUpdate][0];
957
        $preUpdate   = $metadata->entityListeners[Events::preUpdate][0];
958
        $postRemove  = $metadata->entityListeners[Events::postRemove][0];
959
        $preRemove   = $metadata->entityListeners[Events::preRemove][0];
960
        $postLoad    = $metadata->entityListeners[Events::postLoad][0];
961
        $preFlush    = $metadata->entityListeners[Events::preFlush][0];
962
963
964
        $this->assertEquals(CmsAddressListener::class, $postPersist['class']);
965
        $this->assertEquals(CmsAddressListener::class, $prePersist['class']);
966
        $this->assertEquals(CmsAddressListener::class, $postUpdate['class']);
967
        $this->assertEquals(CmsAddressListener::class, $preUpdate['class']);
968
        $this->assertEquals(CmsAddressListener::class, $postRemove['class']);
969
        $this->assertEquals(CmsAddressListener::class, $preRemove['class']);
970
        $this->assertEquals(CmsAddressListener::class, $postLoad['class']);
971
        $this->assertEquals(CmsAddressListener::class, $preFlush['class']);
972
973
        $this->assertEquals(Events::postPersist, $postPersist['method']);
974
        $this->assertEquals(Events::prePersist, $prePersist['method']);
975
        $this->assertEquals(Events::postUpdate, $postUpdate['method']);
976
        $this->assertEquals(Events::preUpdate, $preUpdate['method']);
977
        $this->assertEquals(Events::postRemove, $postRemove['method']);
978
        $this->assertEquals(Events::preRemove, $preRemove['method']);
979
        $this->assertEquals(Events::postLoad, $postLoad['method']);
980
        $this->assertEquals(Events::preFlush, $preFlush['method']);
981
    }
982
983
    /**
984
     * @group DDC-2183
985
     */
986
    public function testSecondLevelCacheMapping()
987
    {
988
        $em      = $this->_getTestEntityManager();
989
        $factory = $this->createClassMetadataFactory($em);
990
        $class   = $factory->getMetadataFor(City::class);
991
        $this->assertArrayHasKey('usage', $class->cache);
992
        $this->assertArrayHasKey('region', $class->cache);
993
        $this->assertEquals(ClassMetadata::CACHE_USAGE_READ_ONLY, $class->cache['usage']);
994
        $this->assertEquals('doctrine_tests_models_cache_city', $class->cache['region']);
995
996
        $this->assertArrayHasKey('state', $class->associationMappings);
997
        $this->assertArrayHasKey('cache', $class->associationMappings['state']);
998
        $this->assertArrayHasKey('usage', $class->associationMappings['state']['cache']);
999
        $this->assertArrayHasKey('region', $class->associationMappings['state']['cache']);
1000
        $this->assertEquals(ClassMetadata::CACHE_USAGE_READ_ONLY, $class->associationMappings['state']['cache']['usage']);
1001
        $this->assertEquals('doctrine_tests_models_cache_city__state', $class->associationMappings['state']['cache']['region']);
1002
1003
        $this->assertArrayHasKey('attractions', $class->associationMappings);
1004
        $this->assertArrayHasKey('cache', $class->associationMappings['attractions']);
1005
        $this->assertArrayHasKey('usage', $class->associationMappings['attractions']['cache']);
1006
        $this->assertArrayHasKey('region', $class->associationMappings['attractions']['cache']);
1007
        $this->assertEquals(ClassMetadata::CACHE_USAGE_READ_ONLY, $class->associationMappings['attractions']['cache']['usage']);
1008
        $this->assertEquals('doctrine_tests_models_cache_city__attractions', $class->associationMappings['attractions']['cache']['region']);
1009
    }
1010
1011
    /**
1012
     * @group DDC-2825
1013
     * @group 881
1014
     */
1015 View Code Duplication
    public function testSchemaDefinitionViaExplicitTableSchemaAnnotationProperty()
1016
    {
1017
        /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadata */
1018
        $metadata = $this->createClassMetadataFactory()->getMetadataFor(ExplicitSchemaAndTable::class);
1019
1020
        $this->assertSame('explicit_schema', $metadata->getSchemaName());
1021
        $this->assertSame('explicit_table', $metadata->getTableName());
1022
    }
1023
1024
    /**
1025
     * @group DDC-2825
1026
     * @group 881
1027
     */
1028 View Code Duplication
    public function testSchemaDefinitionViaSchemaDefinedInTableNameInTableAnnotationProperty()
1029
    {
1030
        /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadata */
1031
        $metadata = $this->createClassMetadataFactory()->getMetadataFor(SchemaAndTableInTableName::class);
1032
1033
        $this->assertSame('implicit_schema', $metadata->getSchemaName());
1034
        $this->assertSame('implicit_table', $metadata->getTableName());
1035
    }
1036
1037
    /**
1038
     * @group DDC-514
1039
     * @group DDC-1015
1040
     */
1041 View Code Duplication
    public function testDiscriminatorColumnDefaultLength()
1042
    {
1043
        if (strpos(get_class($this), 'PHPMappingDriver') !== false) {
1044
            $this->markTestSkipped('PHP Mapping Drivers have no defaults.');
1045
        }
1046
        $class = $this->createClassMetadata(SingleTableEntityNoDiscriminatorColumnMapping::class);
1047
        $this->assertEquals(255, $class->discriminatorColumn['length']);
1048
        $class = $this->createClassMetadata(SingleTableEntityIncompleteDiscriminatorColumnMapping::class);
1049
        $this->assertEquals(255, $class->discriminatorColumn['length']);
1050
    }
1051
1052
    /**
1053
     * @group DDC-514
1054
     * @group DDC-1015
1055
     */
1056 View Code Duplication
    public function testDiscriminatorColumnDefaultType()
1057
    {
1058
        if (strpos(get_class($this), 'PHPMappingDriver') !== false) {
1059
            $this->markTestSkipped('PHP Mapping Drivers have no defaults.');
1060
        }
1061
        $class = $this->createClassMetadata(SingleTableEntityNoDiscriminatorColumnMapping::class);
1062
        $this->assertEquals('string', $class->discriminatorColumn['type']);
1063
        $class = $this->createClassMetadata(SingleTableEntityIncompleteDiscriminatorColumnMapping::class);
1064
        $this->assertEquals('string', $class->discriminatorColumn['type']);
1065
    }
1066
1067
    /**
1068
     * @group DDC-514
1069
     * @group DDC-1015
1070
     */
1071 View Code Duplication
    public function testDiscriminatorColumnDefaultName()
1072
    {
1073
        if (strpos(get_class($this), 'PHPMappingDriver') !== false) {
1074
            $this->markTestSkipped('PHP Mapping Drivers have no defaults.');
1075
        }
1076
        $class = $this->createClassMetadata(SingleTableEntityNoDiscriminatorColumnMapping::class);
1077
        $this->assertEquals('dtype', $class->discriminatorColumn['name']);
1078
        $class = $this->createClassMetadata(SingleTableEntityIncompleteDiscriminatorColumnMapping::class);
1079
        $this->assertEquals('dtype', $class->discriminatorColumn['name']);
1080
    }
1081
1082
}
1083
1084
/**
1085
 * @Entity
1086
 * @HasLifecycleCallbacks
1087
 * @Table(
1088
 *  name="cms_users",
1089
 *  uniqueConstraints={@UniqueConstraint(name="search_idx", columns={"name", "user_email"}, options={"where": "name IS NOT NULL"})},
1090
 *  indexes={@Index(name="name_idx", columns={"name"}), @Index(name="0", columns={"user_email"})},
1091
 *  options={"foo": "bar", "baz": {"key": "val"}}
1092
 * )
1093
 * @NamedQueries({@NamedQuery(name="all", query="SELECT u FROM __CLASS__ u")})
1094
 */
1095
class User
1096
{
1097
    /**
1098
     * @Id
1099
     * @Column(type="integer", options={"foo": "bar", "unsigned": false})
1100
     * @generatedValue(strategy="AUTO")
1101
     * @SequenceGenerator(sequenceName="tablename_seq", initialValue=1, allocationSize=100)
1102
     **/
1103
    public $id;
1104
1105
    /**
1106
     * @Column(length=50, nullable=true, unique=true, options={"foo": "bar", "baz": {"key": "val"}, "fixed": false})
1107
     */
1108
    public $name;
1109
1110
    /**
1111
     * @Column(name="user_email", columnDefinition="CHAR(32) NOT NULL")
1112
     */
1113
    public $email;
1114
1115
    /**
1116
     * @OneToOne(targetEntity="Address", cascade={"remove"}, inversedBy="user")
1117
     * @JoinColumn(onDelete="CASCADE")
1118
     */
1119
    public $address;
1120
1121
    /**
1122
     * @OneToMany(targetEntity="Phonenumber", mappedBy="user", cascade={"persist"}, orphanRemoval=true)
1123
     * @OrderBy({"number"="ASC"})
1124
     */
1125
    public $phonenumbers;
1126
1127
    /**
1128
     * @ManyToMany(targetEntity="Group", cascade={"all"})
1129
     * @JoinTable(name="cms_user_groups",
1130
     *    joinColumns={@JoinColumn(name="user_id", referencedColumnName="id", nullable=false, unique=false)},
1131
     *    inverseJoinColumns={@JoinColumn(name="group_id", referencedColumnName="id", columnDefinition="INT NULL")}
1132
     * )
1133
     */
1134
    public $groups;
1135
1136
    /**
1137
     * @Column(type="integer")
1138
     * @Version
1139
     */
1140
    public $version;
1141
1142
1143
    /**
1144
     * @PrePersist
1145
     */
1146
    public function doStuffOnPrePersist()
1147
    {
1148
    }
1149
1150
    /**
1151
     * @PrePersist
1152
     */
1153
    public function doOtherStuffOnPrePersistToo() {
1154
    }
1155
1156
    /**
1157
     * @PostPersist
1158
     */
1159
    public function doStuffOnPostPersist()
1160
    {
1161
1162
    }
1163
1164
    public static function loadMetadata(ClassMetadataInfo $metadata)
1165
    {
1166
        $metadata->setInheritanceType(ClassMetadataInfo::INHERITANCE_TYPE_NONE);
1167
        $metadata->setPrimaryTable(
1168
            [
1169
           'name' => 'cms_users',
1170
           'options' => ['foo' => 'bar', 'baz' => ['key' => 'val']],
1171
            ]
1172
        );
1173
        $metadata->setChangeTrackingPolicy(ClassMetadataInfo::CHANGETRACKING_DEFERRED_IMPLICIT);
1174
        $metadata->addLifecycleCallback('doStuffOnPrePersist', 'prePersist');
1175
        $metadata->addLifecycleCallback('doOtherStuffOnPrePersistToo', 'prePersist');
1176
        $metadata->addLifecycleCallback('doStuffOnPostPersist', 'postPersist');
1177
        $metadata->mapField(
1178
            [
1179
           'id' => true,
1180
           'fieldName' => 'id',
1181
           'type' => 'integer',
1182
           'columnName' => 'id',
1183
           'options' => ['foo' => 'bar', 'unsigned' => false],
1184
            ]
1185
        );
1186
        $metadata->mapField(
1187
            [
1188
           'fieldName' => 'name',
1189
           'type' => 'string',
1190
           'length' => 50,
1191
           'unique' => true,
1192
           'nullable' => true,
1193
           'columnName' => 'name',
1194
           'options' => ['foo' => 'bar', 'baz' => ['key' => 'val'], 'fixed' => false],
1195
            ]
1196
        );
1197
        $metadata->mapField(
1198
            [
1199
           'fieldName' => 'email',
1200
           'type' => 'string',
1201
           'columnName' => 'user_email',
1202
           'columnDefinition' => 'CHAR(32) NOT NULL',
1203
            ]
1204
        );
1205
        $mapping = ['fieldName' => 'version', 'type' => 'integer'];
1206
        $metadata->setVersionMapping($mapping);
1207
        $metadata->mapField($mapping);
1208
        $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO);
1209
        $metadata->mapOneToOne(
1210
            [
1211
           'fieldName' => 'address',
1212
           'targetEntity' => Address::class,
1213
           'cascade' =>
1214
           [
1215
           0 => 'remove',
1216
           ],
1217
           'mappedBy' => NULL,
1218
           'inversedBy' => 'user',
1219
           'joinColumns' =>
1220
           [
1221
           0 =>
1222
           [
1223
            'name' => 'address_id',
1224
            'referencedColumnName' => 'id',
1225
            'onDelete' => 'CASCADE',
1226
           ],
1227
           ],
1228
           'orphanRemoval' => false,
1229
            ]
1230
        );
1231
        $metadata->mapOneToMany(
1232
            [
1233
           'fieldName' => 'phonenumbers',
1234
           'targetEntity' => Phonenumber::class,
1235
           'cascade' =>
1236
           [
1237
           1 => 'persist',
1238
           ],
1239
           'mappedBy' => 'user',
1240
           'orphanRemoval' => true,
1241
           'orderBy' =>
1242
           [
1243
           'number' => 'ASC',
1244
           ],
1245
            ]
1246
        );
1247
        $metadata->mapManyToMany(
1248
            [
1249
           'fieldName' => 'groups',
1250
           'targetEntity' => Group::class,
1251
           'cascade' =>
1252
           [
1253
           0 => 'remove',
1254
           1 => 'persist',
1255
           2 => 'refresh',
1256
           3 => 'merge',
1257
           4 => 'detach',
1258
           ],
1259
           'mappedBy' => NULL,
1260
           'joinTable' =>
1261
           [
1262
           'name' => 'cms_users_groups',
1263
           'joinColumns' =>
1264
           [
1265
            0 =>
1266
            [
1267
            'name' => 'user_id',
1268
            'referencedColumnName' => 'id',
1269
            'unique' => false,
1270
            'nullable' => false,
1271
            ],
1272
           ],
1273
           'inverseJoinColumns' =>
1274
           [
1275
            0 =>
1276
            [
1277
            'name' => 'group_id',
1278
            'referencedColumnName' => 'id',
1279
            'columnDefinition' => 'INT NULL',
1280
            ],
1281
           ],
1282
           ],
1283
           'orderBy' => NULL,
1284
            ]
1285
        );
1286
        $metadata->table['uniqueConstraints'] = [
1287
            'search_idx' => ['columns' => ['name', 'user_email'], 'options'=> ['where' => 'name IS NOT NULL']],
1288
        ];
1289
        $metadata->table['indexes'] = [
1290
            'name_idx' => ['columns' => ['name']], 0 => ['columns' => ['user_email']]
1291
        ];
1292
        $metadata->setSequenceGeneratorDefinition(
1293
            [
1294
                'sequenceName' => 'tablename_seq',
1295
                'allocationSize' => 100,
1296
                'initialValue' => 1,
1297
            ]
1298
        );
1299
        $metadata->addNamedQuery(
1300
            [
1301
                'name' => 'all',
1302
                'query' => 'SELECT u FROM __CLASS__ u'
1303
            ]
1304
        );
1305
    }
1306
}
1307
1308
/**
1309
 * @Entity
1310
 * @InheritanceType("SINGLE_TABLE")
1311
 * @DiscriminatorMap({"cat" = "Cat", "dog" = "Dog"})
1312
 * @DiscriminatorColumn(name="discr", length=32, type="string")
1313
 */
1314
abstract class Animal
1315
{
1316
    /**
1317
     * @Id @Column(type="string") @GeneratedValue(strategy="CUSTOM")
1318
     * @CustomIdGenerator(class="stdClass")
1319
     */
1320
    public $id;
1321
1322
    public static function loadMetadata(ClassMetadataInfo $metadata)
1323
    {
1324
        $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_CUSTOM);
1325
        $metadata->setCustomGeneratorDefinition(["class" => "stdClass"]);
1326
    }
1327
}
1328
1329
/** @Entity */
1330
class Cat extends Animal
1331
{
1332
    public static function loadMetadata(ClassMetadataInfo $metadata)
1333
    {
1334
1335
    }
1336
}
1337
1338
/** @Entity */
1339
class Dog extends Animal
1340
{
1341
    public static function loadMetadata(ClassMetadataInfo $metadata)
1342
    {
1343
1344
    }
1345
}
1346
1347
1348
/**
1349
 * @Entity
1350
 */
1351
class DDC1170Entity
1352
{
1353
1354
    /**
1355
     * @param string $value
1356
     */
1357
    function __construct($value = null)
1358
    {
1359
        $this->value = $value;
1360
    }
1361
1362
    /**
1363
     * @Id
1364
     * @GeneratedValue(strategy="NONE")
1365
     * @Column(type="integer", columnDefinition = "INT unsigned NOT NULL")
1366
     **/
1367
    private $id;
1368
1369
    /**
1370
     * @Column(columnDefinition = "VARCHAR(255) NOT NULL")
1371
     */
1372
    private $value;
1373
1374
    /**
1375
     * @return int
1376
     */
1377
    public function getId()
1378
    {
1379
        return $this->id;
1380
    }
1381
1382
    /**
1383
     * @return string
1384
     */
1385
    public function getValue()
1386
    {
1387
        return $this->value;
1388
    }
1389
1390
    public static function loadMetadata(ClassMetadataInfo $metadata)
1391
    {
1392
        $metadata->mapField(
1393
            [
1394
           'id'                 => true,
1395
           'fieldName'          => 'id',
1396
           'columnDefinition'   => 'INT unsigned NOT NULL',
1397
            ]
1398
        );
1399
1400
        $metadata->mapField(
1401
            [
1402
            'fieldName'         => 'value',
1403
            'columnDefinition'  => 'VARCHAR(255) NOT NULL'
1404
            ]
1405
        );
1406
1407
        $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_NONE);
1408
    }
1409
1410
}
1411
1412
/**
1413
 * @Entity
1414
 * @InheritanceType("SINGLE_TABLE")
1415
 * @DiscriminatorMap({"ONE" = "DDC807SubClasse1", "TWO" = "DDC807SubClasse2"})
1416
 * @DiscriminatorColumn(name = "dtype", columnDefinition="ENUM('ONE','TWO')")
1417
 */
1418 View Code Duplication
class DDC807Entity
1419
{
1420
    /**
1421
     * @Id
1422
     * @Column(type="integer")
1423
     * @GeneratedValue(strategy="NONE")
1424
     **/
1425
   public $id;
1426
1427
   public static function loadMetadata(ClassMetadataInfo $metadata)
1428
    {
1429
         $metadata->mapField(
1430
             [
1431
           'id'                 => true,
1432
           'fieldName'          => 'id',
1433
             ]
1434
         );
1435
1436
        $metadata->setDiscriminatorColumn(
1437
            [
1438
            'name'              => "dtype",
1439
            'type'              => "string",
1440
            'columnDefinition'  => "ENUM('ONE','TWO')"
1441
            ]
1442
        );
1443
1444
        $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_NONE);
1445
    }
1446
}
1447
1448
class DDC807SubClasse1 {}
1449
class DDC807SubClasse2 {}
1450
1451
class Address {}
1452
class Phonenumber {}
1453
class Group {}
1454
1455
/**
1456
 * @Entity
1457
 * @Table(indexes={@Index(columns={"content"}, flags={"fulltext"}, options={"where": "content IS NOT NULL"})})
1458
 */
1459
class Comment
1460
{
1461
    /**
1462
     * @Column(type="text")
1463
     */
1464
    private $content;
1465
1466
    public static function loadMetadata(ClassMetadataInfo $metadata)
1467
    {
1468
        $metadata->setInheritanceType(ClassMetadataInfo::INHERITANCE_TYPE_NONE);
1469
        $metadata->setPrimaryTable(
1470
            [
1471
            'indexes' => [
1472
                ['columns' => ['content'], 'flags' => ['fulltext'], 'options' => ['where' => 'content IS NOT NULL']]
1473
            ]
1474
            ]
1475
        );
1476
1477
        $metadata->mapField(
1478
            [
1479
            'fieldName' => 'content',
1480
            'type' => 'text',
1481
            'scale' => 0,
1482
            'length' => NULL,
1483
            'unique' => false,
1484
            'nullable' => false,
1485
            'precision' => 0,
1486
            'columnName' => 'content',
1487
            ]
1488
        );
1489
    }
1490
}
1491
1492
/**
1493
 * @Entity
1494
 * @InheritanceType("SINGLE_TABLE")
1495
 * @DiscriminatorMap({
1496
 *     "ONE" = "SingleTableEntityNoDiscriminatorColumnMappingSub1",
1497
 *     "TWO" = "SingleTableEntityNoDiscriminatorColumnMappingSub2"
1498
 * })
1499
 */
1500 View Code Duplication
class SingleTableEntityNoDiscriminatorColumnMapping
1501
{
1502
    /**
1503
     * @Id
1504
     * @Column(type="integer")
1505
     * @GeneratedValue(strategy="NONE")
1506
     */
1507
    public $id;
1508
1509
    public static function loadMetadata(ClassMetadataInfo $metadata)
1510
    {
1511
        $metadata->mapField(
1512
            [
1513
            'id' => true,
1514
            'fieldName' => 'id',
1515
            ]
1516
        );
1517
1518
        $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_NONE);
1519
    }
1520
}
1521
1522
class SingleTableEntityNoDiscriminatorColumnMappingSub1 extends SingleTableEntityNoDiscriminatorColumnMapping {}
1523
class SingleTableEntityNoDiscriminatorColumnMappingSub2 extends SingleTableEntityNoDiscriminatorColumnMapping {}
1524
1525
/**
1526
 * @Entity
1527
 * @InheritanceType("SINGLE_TABLE")
1528
 * @DiscriminatorMap({
1529
 *     "ONE" = "SingleTableEntityIncompleteDiscriminatorColumnMappingSub1",
1530
 *     "TWO" = "SingleTableEntityIncompleteDiscriminatorColumnMappingSub2"
1531
 * })
1532
 * @DiscriminatorColumn(name="dtype")
1533
 */
1534 View Code Duplication
class SingleTableEntityIncompleteDiscriminatorColumnMapping
1535
{
1536
    /**
1537
     * @Id
1538
     * @Column(type="integer")
1539
     * @GeneratedValue(strategy="NONE")
1540
     */
1541
    public $id;
1542
1543
    public static function loadMetadata(ClassMetadataInfo $metadata)
1544
    {
1545
        $metadata->mapField(
1546
            [
1547
            'id' => true,
1548
            'fieldName' => 'id',
1549
            ]
1550
        );
1551
1552
        $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_NONE);
1553
    }
1554
}
1555
1556
class SingleTableEntityIncompleteDiscriminatorColumnMappingSub1
1557
    extends SingleTableEntityIncompleteDiscriminatorColumnMapping {}
1558
class SingleTableEntityIncompleteDiscriminatorColumnMappingSub2
1559
    extends SingleTableEntityIncompleteDiscriminatorColumnMapping {}
1560