Completed
Pull Request — master (#6481)
by Luís
15:39
created

AbstractMappingDriverTest::testLoadMapping()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
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\DDC869\DDC869ChequePayment;
32
use Doctrine\Tests\Models\DDC869\DDC869CreditCardPayment;
33
use Doctrine\Tests\Models\DDC869\DDC869PaymentRepository;
34
use Doctrine\Tests\Models\DDC889\DDC889Class;
35
use Doctrine\Tests\Models\DDC889\DDC889Entity;
36
use Doctrine\Tests\Models\DDC964\DDC964Admin;
37
use Doctrine\Tests\Models\DDC964\DDC964Guest;
38
use Doctrine\Tests\OrmTestCase;
39
40
abstract class AbstractMappingDriverTest extends OrmTestCase
41
{
42
    abstract protected function _loadDriver();
43
44
    public function createClassMetadata($entityClassName)
45
    {
46
        $mappingDriver = $this->_loadDriver();
47
48
        $class = new ClassMetadata($entityClassName);
49
        $class->initializeReflection(new RuntimeReflectionService());
50
        $mappingDriver->loadMetadataForClass($entityClassName, $class);
51
52
        return $class;
53
    }
54
55
    /**
56
     * @param \Doctrine\ORM\EntityManager $entityClassName
57
     * @return \Doctrine\ORM\Mapping\ClassMetadataFactory
58
     */
59
    protected function createClassMetadataFactory(EntityManager $em = null)
60
    {
61
        $driver     = $this->_loadDriver();
62
        $em         = $em ?: $this->_getTestEntityManager();
63
        $factory    = new ClassMetadataFactory();
64
        $em->getConfiguration()->setMetadataDriverImpl($driver);
65
        $factory->setEntityManager($em);
66
67
        return $factory;
68
    }
69
70
    public function testEntityTableNameAndInheritance()
71
    {
72
        $class = $this->createClassMetadata(User::class);
73
74
        $this->assertEquals('cms_users', $class->getTableName());
75
        $this->assertEquals(ClassMetadata::INHERITANCE_TYPE_NONE, $class->inheritanceType);
76
77
        return $class;
78
    }
79
80
    /**
81
     * @depends testEntityTableNameAndInheritance
82
     * @param ClassMetadata $class
83
     */
84
    public function testEntityIndexes($class)
85
    {
86
        $this->assertArrayHasKey('indexes', $class->table, 'ClassMetadata should have indexes key in table property.');
87
        $this->assertEquals(
88
            [
89
            'name_idx' => ['columns' => ['name']],
90
            0 => ['columns' => ['user_email']]
91
            ], $class->table['indexes']);
92
93
        return $class;
94
    }
95
96
    public function testEntityIndexFlagsAndPartialIndexes()
97
    {
98
        $class = $this->createClassMetadata(Comment::class);
99
100
        $this->assertEquals(
101
            [
102
            0 => [
103
                'columns' => ['content'],
104
                'flags' => ['fulltext'],
105
                'options' => ['where' => 'content IS NOT NULL'],
106
            ]
107
            ], $class->table['indexes']);
108
    }
109
110
    /**
111
     * @depends testEntityTableNameAndInheritance
112
     * @param ClassMetadata $class
113
     */
114
    public function testEntityUniqueConstraints($class)
115
    {
116
        $this->assertArrayHasKey('uniqueConstraints', $class->table,
117
            'ClassMetadata should have uniqueConstraints key in table property when Unique Constraints are set.');
118
119
        $this->assertEquals(
120
            [
121
            "search_idx" => ["columns" => ["name", "user_email"], 'options' => ['where' => 'name IS NOT NULL']]
122
            ], $class->table['uniqueConstraints']);
123
124
        return $class;
125
    }
126
127
    /**
128
     * @depends testEntityTableNameAndInheritance
129
     * @param ClassMetadata $class
130
     */
131
    public function testEntityOptions($class)
132
    {
133
        $this->assertArrayHasKey('options', $class->table, 'ClassMetadata should have options key in table property.');
134
135
        $this->assertEquals(
136
            [
137
            'foo' => 'bar', 'baz' => ['key' => 'val']
138
            ], $class->table['options']);
139
140
        return $class;
141
    }
142
143
    /**
144
     * @depends testEntityOptions
145
     * @param ClassMetadata $class
146
     */
147
    public function testEntitySequence($class)
148
    {
149
        $this->assertInternalType('array', $class->sequenceGeneratorDefinition, 'No Sequence Definition set on this driver.');
150
        $this->assertEquals(
151
            [
152
                'sequenceName' => 'tablename_seq',
153
                'allocationSize' => 100,
154
                'initialValue' => 1,
155
            ],
156
            $class->sequenceGeneratorDefinition
157
        );
158
    }
159
160
    public function testEntityCustomGenerator()
161
    {
162
        $class = $this->createClassMetadata(Animal::class);
163
164
        $this->assertEquals(ClassMetadata::GENERATOR_TYPE_CUSTOM,
165
            $class->generatorType, "Generator Type");
166
        $this->assertEquals(
167
            ["class" => "stdClass"],
168
            $class->customGeneratorDefinition,
169
            "Custom Generator Definition");
170
    }
171
172
173
    /**
174
     * @depends testEntityTableNameAndInheritance
175
     * @param ClassMetadata $class
176
     */
177
    public function testFieldMappings($class)
178
    {
179
        $this->assertEquals(4, count($class->fieldMappings));
180
        $this->assertTrue(isset($class->fieldMappings['id']));
181
        $this->assertTrue(isset($class->fieldMappings['name']));
182
        $this->assertTrue(isset($class->fieldMappings['email']));
183
        $this->assertTrue(isset($class->fieldMappings['version']));
184
185
        return $class;
186
    }
187
188
    /**
189
     * @depends testFieldMappings
190
     * @param ClassMetadata $class
191
     */
192
    public function testVersionedField($class)
193
    {
194
        $this->assertTrue($class->isVersioned);
195
        $this->assertEquals("version", $class->versionField);
196
197
        $this->assertFalse(isset($class->fieldMappings['version']['version']));
198
    }
199
200
    /**
201
     * @depends testEntityTableNameAndInheritance
202
     * @param ClassMetadata $class
203
     */
204
    public function testFieldMappingsColumnNames($class)
205
    {
206
        $this->assertEquals("id", $class->fieldMappings['id']['columnName']);
207
        $this->assertEquals("name", $class->fieldMappings['name']['columnName']);
208
        $this->assertEquals("user_email", $class->fieldMappings['email']['columnName']);
209
210
        return $class;
211
    }
212
213
    /**
214
     * @depends testEntityTableNameAndInheritance
215
     * @param ClassMetadata $class
216
     */
217
    public function testStringFieldMappings($class)
218
    {
219
        $this->assertEquals('string', $class->fieldMappings['name']['type']);
220
        $this->assertEquals(50, $class->fieldMappings['name']['length']);
221
        $this->assertTrue($class->fieldMappings['name']['nullable']);
222
        $this->assertTrue($class->fieldMappings['name']['unique']);
223
224
        return $class;
225
    }
226
227
    /**
228
     * @depends testEntityTableNameAndInheritance
229
     *
230
     * @param ClassMetadata $class
231
     *
232
     * @return ClassMetadata
233
     */
234
    public function testFieldOptions(ClassMetadata $class)
235
    {
236
        $expected = ['foo' => 'bar', 'baz' => ['key' => 'val'], 'fixed' => false];
237
        $this->assertEquals($expected, $class->fieldMappings['name']['options']);
238
239
        return $class;
240
    }
241
242
    /**
243
     * @depends testEntityTableNameAndInheritance
244
     * @param ClassMetadata $class
245
     */
246
    public function testIdFieldOptions($class)
247
    {
248
        $this->assertEquals(['foo' => 'bar', 'unsigned' => false], $class->fieldMappings['id']['options']);
249
250
        return $class;
251
    }
252
253
    /**
254
     * @depends testFieldMappings
255
     * @param ClassMetadata $class
256
     */
257
    public function testIdentifier($class)
258
    {
259
        $this->assertEquals(['id'], $class->identifier);
260
        $this->assertEquals('integer', $class->fieldMappings['id']['type']);
261
        $this->assertEquals(ClassMetadata::GENERATOR_TYPE_AUTO, $class->generatorType, "ID-Generator is not ClassMetadata::GENERATOR_TYPE_AUTO");
262
263
        return $class;
264
    }
265
266
    /**
267
     * @group #6129
268
     *
269
     * @return ClassMetadata
270
     */
271
    public function testBooleanValuesForOptionIsSetCorrectly()
272
    {
273
        $class = $this->createClassMetadata(User::class);
274
275
        $this->assertInternalType('bool', $class->fieldMappings['id']['options']['unsigned']);
276
        $this->assertFalse($class->fieldMappings['id']['options']['unsigned']);
277
278
        $this->assertInternalType('bool', $class->fieldMappings['name']['options']['fixed']);
279
        $this->assertFalse($class->fieldMappings['name']['options']['fixed']);
280
281
        return $class;
282
    }
283
284
    /**
285
     * @depends testIdentifier
286
     * @param ClassMetadata $class
287
     */
288
    public function testAssociations($class)
289
    {
290
        $this->assertEquals(3, count($class->associationMappings));
291
292
        return $class;
293
    }
294
295
    /**
296
     * @depends testAssociations
297
     * @param ClassMetadata $class
298
     */
299
    public function testOwningOneToOneAssociation($class)
300
    {
301
        $this->assertTrue(isset($class->associationMappings['address']));
302
        $this->assertTrue($class->associationMappings['address']['isOwningSide']);
303
        $this->assertEquals('user', $class->associationMappings['address']['inversedBy']);
304
        // Check cascading
305
        $this->assertTrue($class->associationMappings['address']['isCascadeRemove']);
306
        $this->assertFalse($class->associationMappings['address']['isCascadePersist']);
307
        $this->assertFalse($class->associationMappings['address']['isCascadeRefresh']);
308
        $this->assertFalse($class->associationMappings['address']['isCascadeDetach']);
309
        $this->assertFalse($class->associationMappings['address']['isCascadeMerge']);
310
311
        return $class;
312
    }
313
314
    /**
315
     * @depends testOwningOneToOneAssociation
316
     * @param ClassMetadata $class
317
     */
318
    public function testInverseOneToManyAssociation($class)
319
    {
320
        $this->assertTrue(isset($class->associationMappings['phonenumbers']));
321
        $this->assertFalse($class->associationMappings['phonenumbers']['isOwningSide']);
322
        $this->assertTrue($class->associationMappings['phonenumbers']['isCascadePersist']);
323
        $this->assertTrue($class->associationMappings['phonenumbers']['isCascadeRemove']);
324
        $this->assertFalse($class->associationMappings['phonenumbers']['isCascadeRefresh']);
325
        $this->assertFalse($class->associationMappings['phonenumbers']['isCascadeDetach']);
326
        $this->assertFalse($class->associationMappings['phonenumbers']['isCascadeMerge']);
327
        $this->assertTrue($class->associationMappings['phonenumbers']['orphanRemoval']);
328
329
        // Test Order By
330
        $this->assertEquals(['number' => 'ASC'], $class->associationMappings['phonenumbers']['orderBy']);
331
332
        return $class;
333
    }
334
335
    /**
336
     * @depends testInverseOneToManyAssociation
337
     * @param ClassMetadata $class
338
     */
339
    public function testManyToManyAssociationWithCascadeAll($class)
340
    {
341
        $this->assertTrue(isset($class->associationMappings['groups']));
342
        $this->assertTrue($class->associationMappings['groups']['isOwningSide']);
343
        // Make sure that cascade-all works as expected
344
        $this->assertTrue($class->associationMappings['groups']['isCascadeRemove']);
345
        $this->assertTrue($class->associationMappings['groups']['isCascadePersist']);
346
        $this->assertTrue($class->associationMappings['groups']['isCascadeRefresh']);
347
        $this->assertTrue($class->associationMappings['groups']['isCascadeDetach']);
348
        $this->assertTrue($class->associationMappings['groups']['isCascadeMerge']);
349
350
        $this->assertFalse(isset($class->associationMappings['groups']['orderBy']));
351
352
        return $class;
353
    }
354
355
    /**
356
     * @depends testManyToManyAssociationWithCascadeAll
357
     * @param ClassMetadata $class
358
     */
359
    public function testLifecycleCallbacks($class)
360
    {
361
        $this->assertEquals(count($class->lifecycleCallbacks), 2);
362
        $this->assertEquals($class->lifecycleCallbacks['prePersist'][0], 'doStuffOnPrePersist');
363
        $this->assertEquals($class->lifecycleCallbacks['postPersist'][0], 'doStuffOnPostPersist');
364
365
        return $class;
366
    }
367
368
    /**
369
     * @depends testManyToManyAssociationWithCascadeAll
370
     * @param ClassMetadata $class
371
     */
372
    public function testLifecycleCallbacksSupportMultipleMethodNames($class)
373
    {
374
        $this->assertEquals(count($class->lifecycleCallbacks['prePersist']), 2);
375
        $this->assertEquals($class->lifecycleCallbacks['prePersist'][1], 'doOtherStuffOnPrePersistToo');
376
377
        return $class;
378
    }
379
380
    /**
381
     * @depends testLifecycleCallbacksSupportMultipleMethodNames
382
     * @param ClassMetadata $class
383
     */
384
    public function testJoinColumnUniqueAndNullable($class)
385
    {
386
        // Non-Nullability of Join Column
387
        $this->assertFalse($class->associationMappings['groups']['joinTable']['joinColumns'][0]['nullable']);
388
        $this->assertFalse($class->associationMappings['groups']['joinTable']['joinColumns'][0]['unique']);
389
390
        return $class;
391
    }
392
393
    /**
394
     * @depends testJoinColumnUniqueAndNullable
395
     * @param ClassMetadata $class
396
     */
397
    public function testColumnDefinition($class)
398
    {
399
        $this->assertEquals("CHAR(32) NOT NULL", $class->fieldMappings['email']['columnDefinition']);
400
        $this->assertEquals("INT NULL", $class->associationMappings['groups']['joinTable']['inverseJoinColumns'][0]['columnDefinition']);
401
402
        return $class;
403
    }
404
405
    /**
406
     * @depends testColumnDefinition
407
     * @param ClassMetadata $class
408
     */
409
    public function testJoinColumnOnDelete($class)
410
    {
411
        $this->assertEquals('CASCADE', $class->associationMappings['address']['joinColumns'][0]['onDelete']);
412
413
        return $class;
414
    }
415
416
    /**
417
     * @group DDC-514
418
     */
419
    public function testDiscriminatorColumnDefaults()
420
    {
421
        if (strpos(get_class($this), 'PHPMappingDriver') !== false) {
422
            $this->markTestSkipped('PHP Mapping Drivers have no defaults.');
423
        }
424
425
        $class = $this->createClassMetadata(Animal::class);
426
427
        $this->assertEquals(
428
            ['name' => 'discr', 'type' => 'string', 'length' => '32', 'fieldName' => 'discr', 'columnDefinition' => null],
429
            $class->discriminatorColumn
430
        );
431
    }
432
433
    /**
434
     * @group DDC-869
435
     */
436
    public function testMappedSuperclassWithRepository()
437
    {
438
        $em         = $this->_getTestEntityManager();
439
        $factory    = $this->createClassMetadataFactory($em);
440
441
442
        $class = $factory->getMetadataFor(DDC869CreditCardPayment::class);
443
444
        $this->assertTrue(isset($class->fieldMappings['id']));
445
        $this->assertTrue(isset($class->fieldMappings['value']));
446
        $this->assertTrue(isset($class->fieldMappings['creditCardNumber']));
447
        $this->assertEquals($class->customRepositoryClassName, DDC869PaymentRepository::class);
448
        $this->assertInstanceOf(DDC869PaymentRepository::class, $em->getRepository(DDC869CreditCardPayment::class));
449
        $this->assertTrue($em->getRepository(DDC869ChequePayment::class)->isTrue());
450
451
452
453
        $class = $factory->getMetadataFor(DDC869ChequePayment::class);
454
455
        $this->assertTrue(isset($class->fieldMappings['id']));
456
        $this->assertTrue(isset($class->fieldMappings['value']));
457
        $this->assertTrue(isset($class->fieldMappings['serialNumber']));
458
        $this->assertEquals($class->customRepositoryClassName, DDC869PaymentRepository::class);
459
        $this->assertInstanceOf(DDC869PaymentRepository::class, $em->getRepository(DDC869ChequePayment::class));
460
        $this->assertTrue($em->getRepository(DDC869ChequePayment::class)->isTrue());
461
    }
462
463
    /**
464
     * @group DDC-1476
465
     */
466
    public function testDefaultFieldType()
467
    {
468
        $factory    = $this->createClassMetadataFactory();
469
        $class      = $factory->getMetadataFor(DDC1476EntityWithDefaultFieldType::class);
470
471
472
        $this->assertArrayHasKey('id', $class->fieldMappings);
473
        $this->assertArrayHasKey('name', $class->fieldMappings);
474
475
476
        $this->assertArrayHasKey('type', $class->fieldMappings['id']);
477
        $this->assertArrayHasKey('type', $class->fieldMappings['name']);
478
479
        $this->assertEquals('string', $class->fieldMappings['id']['type']);
480
        $this->assertEquals('string', $class->fieldMappings['name']['type']);
481
482
483
484
        $this->assertArrayHasKey('fieldName', $class->fieldMappings['id']);
485
        $this->assertArrayHasKey('fieldName', $class->fieldMappings['name']);
486
487
        $this->assertEquals('id', $class->fieldMappings['id']['fieldName']);
488
        $this->assertEquals('name', $class->fieldMappings['name']['fieldName']);
489
490
491
492
        $this->assertArrayHasKey('columnName', $class->fieldMappings['id']);
493
        $this->assertArrayHasKey('columnName', $class->fieldMappings['name']);
494
495
        $this->assertEquals('id', $class->fieldMappings['id']['columnName']);
496
        $this->assertEquals('name', $class->fieldMappings['name']['columnName']);
497
498
        $this->assertEquals(ClassMetadataInfo::GENERATOR_TYPE_NONE, $class->generatorType);
499
    }
500
501
    /**
502
     * @group DDC-1170
503
     */
504
    public function testIdentifierColumnDefinition()
505
    {
506
        $class = $this->createClassMetadata(DDC1170Entity::class);
507
508
509
        $this->assertArrayHasKey('id', $class->fieldMappings);
510
        $this->assertArrayHasKey('value', $class->fieldMappings);
511
512
        $this->assertArrayHasKey('columnDefinition', $class->fieldMappings['id']);
513
        $this->assertArrayHasKey('columnDefinition', $class->fieldMappings['value']);
514
515
        $this->assertEquals("INT unsigned NOT NULL", $class->fieldMappings['id']['columnDefinition']);
516
        $this->assertEquals("VARCHAR(255) NOT NULL", $class->fieldMappings['value']['columnDefinition']);
517
    }
518
519
    /**
520
     * @group DDC-559
521
     */
522
    public function testNamingStrategy()
523
    {
524
        $em         = $this->_getTestEntityManager();
525
        $factory    = $this->createClassMetadataFactory($em);
526
527
528
        $this->assertInstanceOf(DefaultNamingStrategy::class, $em->getConfiguration()->getNamingStrategy());
529
        $em->getConfiguration()->setNamingStrategy(new UnderscoreNamingStrategy(CASE_UPPER));
530
        $this->assertInstanceOf(UnderscoreNamingStrategy::class, $em->getConfiguration()->getNamingStrategy());
531
532
        $class = $factory->getMetadataFor(DDC1476EntityWithDefaultFieldType::class);
533
534
        $this->assertEquals('ID', $class->getColumnName('id'));
535
        $this->assertEquals('NAME', $class->getColumnName('name'));
536
        $this->assertEquals('DDC1476ENTITY_WITH_DEFAULT_FIELD_TYPE', $class->table['name']);
537
    }
538
539
    /**
540
     * @group DDC-807
541
     * @group DDC-553
542
     */
543
    public function testDiscriminatorColumnDefinition()
544
    {
545
        $class = $this->createClassMetadata(DDC807Entity::class);
546
547
        $this->assertArrayHasKey('columnDefinition', $class->discriminatorColumn);
548
        $this->assertArrayHasKey('name', $class->discriminatorColumn);
549
550
        $this->assertEquals("ENUM('ONE','TWO')", $class->discriminatorColumn['columnDefinition']);
551
        $this->assertEquals("dtype", $class->discriminatorColumn['name']);
552
    }
553
554
    /**
555
     * @group DDC-889
556
     */
557
    public function testInvalidEntityOrMappedSuperClassShouldMentionParentClasses()
558
    {
559
        $this->expectException(MappingException::class);
560
        $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.');
561
562
        $this->createClassMetadata(DDC889Class::class);
563
    }
564
565
    /**
566
     * @group DDC-889
567
     */
568
    public function testIdentifierRequiredShouldMentionParentClasses()
569
    {
570
        $factory = $this->createClassMetadataFactory();
571
572
        $this->expectException(MappingException::class);
573
        $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.');
574
575
        $factory->getMetadataFor(DDC889Entity::class);
576
    }
577
578
    public function testNamedQuery()
579
    {
580
        $driver = $this->_loadDriver();
581
        $class = $this->createClassMetadata(User::class);
582
583
        $this->assertCount(1, $class->getNamedQueries(), sprintf("Named queries not processed correctly by driver %s", get_class($driver)));
584
    }
585
586
    /**
587
     * @group DDC-1663
588
     */
589
    public function testNamedNativeQuery()
590
    {
591
592
        $class = $this->createClassMetadata(CmsAddress::class);
593
594
        //named native query
595
        $this->assertCount(3, $class->namedNativeQueries);
596
        $this->assertArrayHasKey('find-all', $class->namedNativeQueries);
597
        $this->assertArrayHasKey('find-by-id', $class->namedNativeQueries);
598
599
600
        $findAllQuery = $class->getNamedNativeQuery('find-all');
601
        $this->assertEquals('find-all', $findAllQuery['name']);
602
        $this->assertEquals('mapping-find-all', $findAllQuery['resultSetMapping']);
603
        $this->assertEquals('SELECT id, country, city FROM cms_addresses', $findAllQuery['query']);
604
605
        $findByIdQuery = $class->getNamedNativeQuery('find-by-id');
606
        $this->assertEquals('find-by-id', $findByIdQuery['name']);
607
        $this->assertEquals(CmsAddress::class,$findByIdQuery['resultClass']);
608
        $this->assertEquals('SELECT * FROM cms_addresses WHERE id = ?',  $findByIdQuery['query']);
609
610
        $countQuery = $class->getNamedNativeQuery('count');
611
        $this->assertEquals('count', $countQuery['name']);
612
        $this->assertEquals('mapping-count', $countQuery['resultSetMapping']);
613
        $this->assertEquals('SELECT COUNT(*) AS count FROM cms_addresses',  $countQuery['query']);
614
615
        // result set mapping
616
        $this->assertCount(3, $class->sqlResultSetMappings);
617
        $this->assertArrayHasKey('mapping-count', $class->sqlResultSetMappings);
618
        $this->assertArrayHasKey('mapping-find-all', $class->sqlResultSetMappings);
619
        $this->assertArrayHasKey('mapping-without-fields', $class->sqlResultSetMappings);
620
621
        $findAllMapping = $class->getSqlResultSetMapping('mapping-find-all');
622
        $this->assertEquals('mapping-find-all', $findAllMapping['name']);
623
        $this->assertEquals(CmsAddress::class, $findAllMapping['entities'][0]['entityClass']);
624
        $this->assertEquals(['name'=>'id','column'=>'id'], $findAllMapping['entities'][0]['fields'][0]);
625
        $this->assertEquals(['name'=>'city','column'=>'city'], $findAllMapping['entities'][0]['fields'][1]);
626
        $this->assertEquals(['name'=>'country','column'=>'country'], $findAllMapping['entities'][0]['fields'][2]);
627
628
        $withoutFieldsMapping = $class->getSqlResultSetMapping('mapping-without-fields');
629
        $this->assertEquals('mapping-without-fields', $withoutFieldsMapping['name']);
630
        $this->assertEquals(CmsAddress::class, $withoutFieldsMapping['entities'][0]['entityClass']);
631
        $this->assertEquals([], $withoutFieldsMapping['entities'][0]['fields']);
632
633
        $countMapping = $class->getSqlResultSetMapping('mapping-count');
634
        $this->assertEquals('mapping-count', $countMapping['name']);
635
        $this->assertEquals(['name'=>'count'], $countMapping['columns'][0]);
636
637
    }
638
639
    /**
640
     * @group DDC-1663
641
     */
642
    public function testSqlResultSetMapping()
643
    {
644
645
        $userMetadata   = $this->createClassMetadata(CmsUser::class);
646
        $personMetadata = $this->createClassMetadata(CompanyPerson::class);
647
648
        // user asserts
649
        $this->assertCount(4, $userMetadata->getSqlResultSetMappings());
650
651
        $mapping = $userMetadata->getSqlResultSetMapping('mappingJoinedAddress');
652
        $this->assertEquals([],$mapping['columns']);
653
        $this->assertEquals('mappingJoinedAddress', $mapping['name']);
654
        $this->assertNull($mapping['entities'][0]['discriminatorColumn']);
655
        $this->assertEquals(['name'=>'id','column'=>'id'],                     $mapping['entities'][0]['fields'][0]);
656
        $this->assertEquals(['name'=>'name','column'=>'name'],                 $mapping['entities'][0]['fields'][1]);
657
        $this->assertEquals(['name'=>'status','column'=>'status'],             $mapping['entities'][0]['fields'][2]);
658
        $this->assertEquals(['name'=>'address.zip','column'=>'zip'],           $mapping['entities'][0]['fields'][3]);
659
        $this->assertEquals(['name'=>'address.city','column'=>'city'],         $mapping['entities'][0]['fields'][4]);
660
        $this->assertEquals(['name'=>'address.country','column'=>'country'],   $mapping['entities'][0]['fields'][5]);
661
        $this->assertEquals(['name'=>'address.id','column'=>'a_id'],           $mapping['entities'][0]['fields'][6]);
662
        $this->assertEquals($userMetadata->name,                                    $mapping['entities'][0]['entityClass']);
663
664
665
        $mapping = $userMetadata->getSqlResultSetMapping('mappingJoinedPhonenumber');
666
        $this->assertEquals([],$mapping['columns']);
667
        $this->assertEquals('mappingJoinedPhonenumber', $mapping['name']);
668
        $this->assertNull($mapping['entities'][0]['discriminatorColumn']);
669
        $this->assertEquals(['name'=>'id','column'=>'id'],                             $mapping['entities'][0]['fields'][0]);
670
        $this->assertEquals(['name'=>'name','column'=>'name'],                         $mapping['entities'][0]['fields'][1]);
671
        $this->assertEquals(['name'=>'status','column'=>'status'],                     $mapping['entities'][0]['fields'][2]);
672
        $this->assertEquals(['name'=>'phonenumbers.phonenumber','column'=>'number'],   $mapping['entities'][0]['fields'][3]);
673
        $this->assertEquals($userMetadata->name,                                            $mapping['entities'][0]['entityClass']);
674
675
        $mapping = $userMetadata->getSqlResultSetMapping('mappingUserPhonenumberCount');
676
        $this->assertEquals(['name'=>'numphones'],$mapping['columns'][0]);
677
        $this->assertEquals('mappingUserPhonenumberCount', $mapping['name']);
678
        $this->assertNull($mapping['entities'][0]['discriminatorColumn']);
679
        $this->assertEquals(['name'=>'id','column'=>'id'],         $mapping['entities'][0]['fields'][0]);
680
        $this->assertEquals(['name'=>'name','column'=>'name'],     $mapping['entities'][0]['fields'][1]);
681
        $this->assertEquals(['name'=>'status','column'=>'status'], $mapping['entities'][0]['fields'][2]);
682
        $this->assertEquals($userMetadata->name,                        $mapping['entities'][0]['entityClass']);
683
684
        $mapping = $userMetadata->getSqlResultSetMapping('mappingMultipleJoinsEntityResults');
685
        $this->assertEquals(['name'=>'numphones'],$mapping['columns'][0]);
686
        $this->assertEquals('mappingMultipleJoinsEntityResults', $mapping['name']);
687
        $this->assertNull($mapping['entities'][0]['discriminatorColumn']);
688
        $this->assertEquals(['name'=>'id','column'=>'u_id'],           $mapping['entities'][0]['fields'][0]);
689
        $this->assertEquals(['name'=>'name','column'=>'u_name'],       $mapping['entities'][0]['fields'][1]);
690
        $this->assertEquals(['name'=>'status','column'=>'u_status'],   $mapping['entities'][0]['fields'][2]);
691
        $this->assertEquals($userMetadata->name,                            $mapping['entities'][0]['entityClass']);
692
        $this->assertNull($mapping['entities'][1]['discriminatorColumn']);
693
        $this->assertEquals(['name'=>'id','column'=>'a_id'],           $mapping['entities'][1]['fields'][0]);
694
        $this->assertEquals(['name'=>'zip','column'=>'a_zip'],         $mapping['entities'][1]['fields'][1]);
695
        $this->assertEquals(['name'=>'country','column'=>'a_country'], $mapping['entities'][1]['fields'][2]);
696
        $this->assertEquals(CmsAddress::class,         $mapping['entities'][1]['entityClass']);
697
698
        //person asserts
699
        $this->assertCount(1, $personMetadata->getSqlResultSetMappings());
700
701
        $mapping = $personMetadata->getSqlResultSetMapping('mappingFetchAll');
702
        $this->assertEquals([],$mapping['columns']);
703
        $this->assertEquals('mappingFetchAll', $mapping['name']);
704
        $this->assertEquals('discriminator',                            $mapping['entities'][0]['discriminatorColumn']);
705
        $this->assertEquals(['name'=>'id','column'=>'id'],         $mapping['entities'][0]['fields'][0]);
706
        $this->assertEquals(['name'=>'name','column'=>'name'],     $mapping['entities'][0]['fields'][1]);
707
        $this->assertEquals($personMetadata->name,                      $mapping['entities'][0]['entityClass']);
708
    }
709
710
    /*
711
     * @group DDC-964
712
     */
713
    public function testAssociationOverridesMapping()
714
    {
715
716
        $factory        = $this->createClassMetadataFactory();
717
        $adminMetadata  = $factory->getMetadataFor(DDC964Admin::class);
718
        $guestMetadata  = $factory->getMetadataFor(DDC964Guest::class);
719
720
721
        // assert groups association mappings
722
        $this->assertArrayHasKey('groups', $guestMetadata->associationMappings);
723
        $this->assertArrayHasKey('groups', $adminMetadata->associationMappings);
724
725
        $guestGroups = $guestMetadata->associationMappings['groups'];
726
        $adminGroups = $adminMetadata->associationMappings['groups'];
727
728
        // assert not override attributes
729
        $this->assertEquals($guestGroups['fieldName'], $adminGroups['fieldName']);
730
        $this->assertEquals($guestGroups['type'], $adminGroups['type']);
731
        $this->assertEquals($guestGroups['mappedBy'], $adminGroups['mappedBy']);
732
        $this->assertEquals($guestGroups['inversedBy'], $adminGroups['inversedBy']);
733
        $this->assertEquals($guestGroups['isOwningSide'], $adminGroups['isOwningSide']);
734
        $this->assertEquals($guestGroups['fetch'], $adminGroups['fetch']);
735
        $this->assertEquals($guestGroups['isCascadeRemove'], $adminGroups['isCascadeRemove']);
736
        $this->assertEquals($guestGroups['isCascadePersist'], $adminGroups['isCascadePersist']);
737
        $this->assertEquals($guestGroups['isCascadeRefresh'], $adminGroups['isCascadeRefresh']);
738
        $this->assertEquals($guestGroups['isCascadeMerge'], $adminGroups['isCascadeMerge']);
739
        $this->assertEquals($guestGroups['isCascadeDetach'], $adminGroups['isCascadeDetach']);
740
741
         // assert not override attributes
742
        $this->assertEquals('ddc964_users_groups', $guestGroups['joinTable']['name']);
743
        $this->assertEquals('user_id', $guestGroups['joinTable']['joinColumns'][0]['name']);
744
        $this->assertEquals('group_id', $guestGroups['joinTable']['inverseJoinColumns'][0]['name']);
745
746
        $this->assertEquals(['user_id'=>'id'], $guestGroups['relationToSourceKeyColumns']);
747
        $this->assertEquals(['group_id'=>'id'], $guestGroups['relationToTargetKeyColumns']);
748
        $this->assertEquals(['user_id','group_id'], $guestGroups['joinTableColumns']);
749
750
751
        $this->assertEquals('ddc964_users_admingroups', $adminGroups['joinTable']['name']);
752
        $this->assertEquals('adminuser_id', $adminGroups['joinTable']['joinColumns'][0]['name']);
753
        $this->assertEquals('admingroup_id', $adminGroups['joinTable']['inverseJoinColumns'][0]['name']);
754
755
        $this->assertEquals(['adminuser_id'=>'id'], $adminGroups['relationToSourceKeyColumns']);
756
        $this->assertEquals(['admingroup_id'=>'id'], $adminGroups['relationToTargetKeyColumns']);
757
        $this->assertEquals(['adminuser_id','admingroup_id'], $adminGroups['joinTableColumns']);
758
759
760
        // assert address association mappings
761
        $this->assertArrayHasKey('address', $guestMetadata->associationMappings);
762
        $this->assertArrayHasKey('address', $adminMetadata->associationMappings);
763
764
        $guestAddress = $guestMetadata->associationMappings['address'];
765
        $adminAddress = $adminMetadata->associationMappings['address'];
766
767
        // assert not override attributes
768
        $this->assertEquals($guestAddress['fieldName'], $adminAddress['fieldName']);
769
        $this->assertEquals($guestAddress['type'], $adminAddress['type']);
770
        $this->assertEquals($guestAddress['mappedBy'], $adminAddress['mappedBy']);
771
        $this->assertEquals($guestAddress['inversedBy'], $adminAddress['inversedBy']);
772
        $this->assertEquals($guestAddress['isOwningSide'], $adminAddress['isOwningSide']);
773
        $this->assertEquals($guestAddress['fetch'], $adminAddress['fetch']);
774
        $this->assertEquals($guestAddress['isCascadeRemove'], $adminAddress['isCascadeRemove']);
775
        $this->assertEquals($guestAddress['isCascadePersist'], $adminAddress['isCascadePersist']);
776
        $this->assertEquals($guestAddress['isCascadeRefresh'], $adminAddress['isCascadeRefresh']);
777
        $this->assertEquals($guestAddress['isCascadeMerge'], $adminAddress['isCascadeMerge']);
778
        $this->assertEquals($guestAddress['isCascadeDetach'], $adminAddress['isCascadeDetach']);
779
780
        // assert override
781
        $this->assertEquals('address_id', $guestAddress['joinColumns'][0]['name']);
782
        $this->assertEquals(['address_id'=>'id'], $guestAddress['sourceToTargetKeyColumns']);
783
        $this->assertEquals(['address_id'=>'address_id'], $guestAddress['joinColumnFieldNames']);
784
        $this->assertEquals(['id'=>'address_id'], $guestAddress['targetToSourceKeyColumns']);
785
786
787
        $this->assertEquals('adminaddress_id', $adminAddress['joinColumns'][0]['name']);
788
        $this->assertEquals(['adminaddress_id'=>'id'], $adminAddress['sourceToTargetKeyColumns']);
789
        $this->assertEquals(['adminaddress_id'=>'adminaddress_id'], $adminAddress['joinColumnFieldNames']);
790
        $this->assertEquals(['id'=>'adminaddress_id'], $adminAddress['targetToSourceKeyColumns']);
791
    }
792
793
    /*
794
     * @group DDC-3579
795
     */
796
    public function testInversedByOverrideMapping()
797
    {
798
799
        $factory        = $this->createClassMetadataFactory();
800
        $adminMetadata  = $factory->getMetadataFor(DDC3579Admin::class);
801
802
        // assert groups association mappings
803
        $this->assertArrayHasKey('groups', $adminMetadata->associationMappings);
804
        $adminGroups = $adminMetadata->associationMappings['groups'];
805
806
        // assert override
807
        $this->assertEquals('admins', $adminGroups['inversedBy']);
808
    }
809
810
    /**
811
     * @group DDC-964
812
     */
813
    public function testAttributeOverridesMapping()
814
    {
815
816
        $factory       = $this->createClassMetadataFactory();
817
        $guestMetadata = $factory->getMetadataFor(DDC964Guest::class);
818
        $adminMetadata = $factory->getMetadataFor(DDC964Admin::class);
819
820
        $this->assertTrue($adminMetadata->fieldMappings['id']['id']);
821
        $this->assertEquals('id', $adminMetadata->fieldMappings['id']['fieldName']);
822
        $this->assertEquals('user_id', $adminMetadata->fieldMappings['id']['columnName']);
823
        $this->assertEquals(['user_id'=>'id','user_name'=>'name'], $adminMetadata->fieldNames);
824
        $this->assertEquals(['id'=>'user_id','name'=>'user_name'], $adminMetadata->columnNames);
825
        $this->assertEquals(150, $adminMetadata->fieldMappings['id']['length']);
826
827
828
        $this->assertEquals('name', $adminMetadata->fieldMappings['name']['fieldName']);
829
        $this->assertEquals('user_name', $adminMetadata->fieldMappings['name']['columnName']);
830
        $this->assertEquals(250, $adminMetadata->fieldMappings['name']['length']);
831
        $this->assertTrue($adminMetadata->fieldMappings['name']['nullable']);
832
        $this->assertFalse($adminMetadata->fieldMappings['name']['unique']);
833
834
835
        $this->assertTrue($guestMetadata->fieldMappings['id']['id']);
836
        $this->assertEquals('guest_id', $guestMetadata->fieldMappings['id']['columnName']);
837
        $this->assertEquals('id', $guestMetadata->fieldMappings['id']['fieldName']);
838
        $this->assertEquals(['guest_id'=>'id','guest_name'=>'name'], $guestMetadata->fieldNames);
839
        $this->assertEquals(['id'=>'guest_id','name'=>'guest_name'], $guestMetadata->columnNames);
840
        $this->assertEquals(140, $guestMetadata->fieldMappings['id']['length']);
841
842
        $this->assertEquals('name', $guestMetadata->fieldMappings['name']['fieldName']);
843
        $this->assertEquals('guest_name', $guestMetadata->fieldMappings['name']['columnName']);
844
        $this->assertEquals(240, $guestMetadata->fieldMappings['name']['length']);
845
        $this->assertFalse($guestMetadata->fieldMappings['name']['nullable']);
846
        $this->assertTrue($guestMetadata->fieldMappings['name']['unique']);
847
    }
848
849
    /**
850
     * @group DDC-1955
851
     */
852
    public function testEntityListeners()
853
    {
854
        $em         = $this->_getTestEntityManager();
855
        $factory    = $this->createClassMetadataFactory($em);
856
        $superClass = $factory->getMetadataFor(CompanyContract::class);
857
        $flexClass  = $factory->getMetadataFor(CompanyFixContract::class);
858
        $fixClass   = $factory->getMetadataFor(CompanyFlexContract::class);
859
        $ultraClass = $factory->getMetadataFor(CompanyFlexUltraContract::class);
860
861
        $this->assertArrayHasKey(Events::prePersist, $superClass->entityListeners);
862
        $this->assertArrayHasKey(Events::postPersist, $superClass->entityListeners);
863
864
        $this->assertCount(1, $superClass->entityListeners[Events::prePersist]);
865
        $this->assertCount(1, $superClass->entityListeners[Events::postPersist]);
866
867
        $postPersist = $superClass->entityListeners[Events::postPersist][0];
868
        $prePersist  = $superClass->entityListeners[Events::prePersist][0];
869
870
        $this->assertEquals(CompanyContractListener::class, $postPersist['class']);
871
        $this->assertEquals(CompanyContractListener::class, $prePersist['class']);
872
        $this->assertEquals('postPersistHandler', $postPersist['method']);
873
        $this->assertEquals('prePersistHandler', $prePersist['method']);
874
875
        //Inherited listeners
876
        $this->assertEquals($fixClass->entityListeners, $superClass->entityListeners);
877
        $this->assertEquals($flexClass->entityListeners, $superClass->entityListeners);
878
    }
879
880
    /**
881
     * @group DDC-1955
882
     */
883
    public function testEntityListenersOverride()
884
    {
885
        $em         = $this->_getTestEntityManager();
886
        $factory    = $this->createClassMetadataFactory($em);
887
        $ultraClass = $factory->getMetadataFor(CompanyFlexUltraContract::class);
888
889
        //overridden listeners
890
        $this->assertArrayHasKey(Events::postPersist, $ultraClass->entityListeners);
891
        $this->assertArrayHasKey(Events::prePersist, $ultraClass->entityListeners);
892
893
        $this->assertCount(1, $ultraClass->entityListeners[Events::postPersist]);
894
        $this->assertCount(3, $ultraClass->entityListeners[Events::prePersist]);
895
896
        $postPersist = $ultraClass->entityListeners[Events::postPersist][0];
897
        $prePersist  = $ultraClass->entityListeners[Events::prePersist][0];
898
899
        $this->assertEquals(CompanyContractListener::class, $postPersist['class']);
900
        $this->assertEquals(CompanyContractListener::class, $prePersist['class']);
901
        $this->assertEquals('postPersistHandler', $postPersist['method']);
902
        $this->assertEquals('prePersistHandler', $prePersist['method']);
903
904
        $prePersist = $ultraClass->entityListeners[Events::prePersist][1];
905
        $this->assertEquals(CompanyFlexUltraContractListener::class, $prePersist['class']);
906
        $this->assertEquals('prePersistHandler1', $prePersist['method']);
907
908
        $prePersist = $ultraClass->entityListeners[Events::prePersist][2];
909
        $this->assertEquals(CompanyFlexUltraContractListener::class, $prePersist['class']);
910
        $this->assertEquals('prePersistHandler2', $prePersist['method']);
911
    }
912
913
914
    /**
915
     * @group DDC-1955
916
     */
917
    public function testEntityListenersNamingConvention()
918
    {
919
        $em         = $this->_getTestEntityManager();
920
        $factory    = $this->createClassMetadataFactory($em);
921
        $metadata   = $factory->getMetadataFor(CmsAddress::class);
922
923
        $this->assertArrayHasKey(Events::postPersist, $metadata->entityListeners);
924
        $this->assertArrayHasKey(Events::prePersist, $metadata->entityListeners);
925
        $this->assertArrayHasKey(Events::postUpdate, $metadata->entityListeners);
926
        $this->assertArrayHasKey(Events::preUpdate, $metadata->entityListeners);
927
        $this->assertArrayHasKey(Events::postRemove, $metadata->entityListeners);
928
        $this->assertArrayHasKey(Events::preRemove, $metadata->entityListeners);
929
        $this->assertArrayHasKey(Events::postLoad, $metadata->entityListeners);
930
        $this->assertArrayHasKey(Events::preFlush, $metadata->entityListeners);
931
932
        $this->assertCount(1, $metadata->entityListeners[Events::postPersist]);
933
        $this->assertCount(1, $metadata->entityListeners[Events::prePersist]);
934
        $this->assertCount(1, $metadata->entityListeners[Events::postUpdate]);
935
        $this->assertCount(1, $metadata->entityListeners[Events::preUpdate]);
936
        $this->assertCount(1, $metadata->entityListeners[Events::postRemove]);
937
        $this->assertCount(1, $metadata->entityListeners[Events::preRemove]);
938
        $this->assertCount(1, $metadata->entityListeners[Events::postLoad]);
939
        $this->assertCount(1, $metadata->entityListeners[Events::preFlush]);
940
941
        $postPersist = $metadata->entityListeners[Events::postPersist][0];
942
        $prePersist  = $metadata->entityListeners[Events::prePersist][0];
943
        $postUpdate  = $metadata->entityListeners[Events::postUpdate][0];
944
        $preUpdate   = $metadata->entityListeners[Events::preUpdate][0];
945
        $postRemove  = $metadata->entityListeners[Events::postRemove][0];
946
        $preRemove   = $metadata->entityListeners[Events::preRemove][0];
947
        $postLoad    = $metadata->entityListeners[Events::postLoad][0];
948
        $preFlush    = $metadata->entityListeners[Events::preFlush][0];
949
950
951
        $this->assertEquals(CmsAddressListener::class, $postPersist['class']);
952
        $this->assertEquals(CmsAddressListener::class, $prePersist['class']);
953
        $this->assertEquals(CmsAddressListener::class, $postUpdate['class']);
954
        $this->assertEquals(CmsAddressListener::class, $preUpdate['class']);
955
        $this->assertEquals(CmsAddressListener::class, $postRemove['class']);
956
        $this->assertEquals(CmsAddressListener::class, $preRemove['class']);
957
        $this->assertEquals(CmsAddressListener::class, $postLoad['class']);
958
        $this->assertEquals(CmsAddressListener::class, $preFlush['class']);
959
960
        $this->assertEquals(Events::postPersist, $postPersist['method']);
961
        $this->assertEquals(Events::prePersist, $prePersist['method']);
962
        $this->assertEquals(Events::postUpdate, $postUpdate['method']);
963
        $this->assertEquals(Events::preUpdate, $preUpdate['method']);
964
        $this->assertEquals(Events::postRemove, $postRemove['method']);
965
        $this->assertEquals(Events::preRemove, $preRemove['method']);
966
        $this->assertEquals(Events::postLoad, $postLoad['method']);
967
        $this->assertEquals(Events::preFlush, $preFlush['method']);
968
    }
969
970
    /**
971
     * @group DDC-2183
972
     */
973
    public function testSecondLevelCacheMapping()
974
    {
975
        $em      = $this->_getTestEntityManager();
976
        $factory = $this->createClassMetadataFactory($em);
977
        $class   = $factory->getMetadataFor(City::class);
978
        $this->assertArrayHasKey('usage', $class->cache);
979
        $this->assertArrayHasKey('region', $class->cache);
980
        $this->assertEquals(ClassMetadata::CACHE_USAGE_READ_ONLY, $class->cache['usage']);
981
        $this->assertEquals('doctrine_tests_models_cache_city', $class->cache['region']);
982
983
        $this->assertArrayHasKey('state', $class->associationMappings);
984
        $this->assertArrayHasKey('cache', $class->associationMappings['state']);
985
        $this->assertArrayHasKey('usage', $class->associationMappings['state']['cache']);
986
        $this->assertArrayHasKey('region', $class->associationMappings['state']['cache']);
987
        $this->assertEquals(ClassMetadata::CACHE_USAGE_READ_ONLY, $class->associationMappings['state']['cache']['usage']);
988
        $this->assertEquals('doctrine_tests_models_cache_city__state', $class->associationMappings['state']['cache']['region']);
989
990
        $this->assertArrayHasKey('attractions', $class->associationMappings);
991
        $this->assertArrayHasKey('cache', $class->associationMappings['attractions']);
992
        $this->assertArrayHasKey('usage', $class->associationMappings['attractions']['cache']);
993
        $this->assertArrayHasKey('region', $class->associationMappings['attractions']['cache']);
994
        $this->assertEquals(ClassMetadata::CACHE_USAGE_READ_ONLY, $class->associationMappings['attractions']['cache']['usage']);
995
        $this->assertEquals('doctrine_tests_models_cache_city__attractions', $class->associationMappings['attractions']['cache']['region']);
996
    }
997
998
    /**
999
     * @group DDC-2825
1000
     * @group 881
1001
     */
1002
    public function testSchemaDefinitionViaExplicitTableSchemaAnnotationProperty()
1003
    {
1004
        /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadata */
1005
        $metadata = $this->createClassMetadataFactory()->getMetadataFor(ExplicitSchemaAndTable::class);
1006
1007
        $this->assertSame('explicit_schema', $metadata->getSchemaName());
1008
        $this->assertSame('explicit_table', $metadata->getTableName());
1009
    }
1010
1011
    /**
1012
     * @group DDC-2825
1013
     * @group 881
1014
     */
1015
    public function testSchemaDefinitionViaSchemaDefinedInTableNameInTableAnnotationProperty()
1016
    {
1017
        /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadata */
1018
        $metadata = $this->createClassMetadataFactory()->getMetadataFor(SchemaAndTableInTableName::class);
1019
1020
        $this->assertSame('implicit_schema', $metadata->getSchemaName());
1021
        $this->assertSame('implicit_table', $metadata->getTableName());
1022
    }
1023
1024
    /**
1025
     * @group DDC-514
1026
     * @group DDC-1015
1027
     */
1028
    public function testDiscriminatorColumnDefaultLength()
1029
    {
1030
        if (strpos(get_class($this), 'PHPMappingDriver') !== false) {
1031
            $this->markTestSkipped('PHP Mapping Drivers have no defaults.');
1032
        }
1033
        $class = $this->createClassMetadata(SingleTableEntityNoDiscriminatorColumnMapping::class);
1034
        $this->assertEquals(255, $class->discriminatorColumn['length']);
1035
        $class = $this->createClassMetadata(SingleTableEntityIncompleteDiscriminatorColumnMapping::class);
1036
        $this->assertEquals(255, $class->discriminatorColumn['length']);
1037
    }
1038
1039
    /**
1040
     * @group DDC-514
1041
     * @group DDC-1015
1042
     */
1043
    public function testDiscriminatorColumnDefaultType()
1044
    {
1045
        if (strpos(get_class($this), 'PHPMappingDriver') !== false) {
1046
            $this->markTestSkipped('PHP Mapping Drivers have no defaults.');
1047
        }
1048
        $class = $this->createClassMetadata(SingleTableEntityNoDiscriminatorColumnMapping::class);
1049
        $this->assertEquals('string', $class->discriminatorColumn['type']);
1050
        $class = $this->createClassMetadata(SingleTableEntityIncompleteDiscriminatorColumnMapping::class);
1051
        $this->assertEquals('string', $class->discriminatorColumn['type']);
1052
    }
1053
1054
    /**
1055
     * @group DDC-514
1056
     * @group DDC-1015
1057
     */
1058
    public function testDiscriminatorColumnDefaultName()
1059
    {
1060
        if (strpos(get_class($this), 'PHPMappingDriver') !== false) {
1061
            $this->markTestSkipped('PHP Mapping Drivers have no defaults.');
1062
        }
1063
        $class = $this->createClassMetadata(SingleTableEntityNoDiscriminatorColumnMapping::class);
1064
        $this->assertEquals('dtype', $class->discriminatorColumn['name']);
1065
        $class = $this->createClassMetadata(SingleTableEntityIncompleteDiscriminatorColumnMapping::class);
1066
        $this->assertEquals('dtype', $class->discriminatorColumn['name']);
1067
    }
1068
1069
}
1070
1071
/**
1072
 * @Entity
1073
 * @HasLifecycleCallbacks
1074
 * @Table(
1075
 *  name="cms_users",
1076
 *  uniqueConstraints={@UniqueConstraint(name="search_idx", columns={"name", "user_email"}, options={"where": "name IS NOT NULL"})},
1077
 *  indexes={@Index(name="name_idx", columns={"name"}), @Index(name="0", columns={"user_email"})},
1078
 *  options={"foo": "bar", "baz": {"key": "val"}}
1079
 * )
1080
 * @NamedQueries({@NamedQuery(name="all", query="SELECT u FROM __CLASS__ u")})
1081
 */
1082
class User
1083
{
1084
    /**
1085
     * @Id
1086
     * @Column(type="integer", options={"foo": "bar", "unsigned": false})
1087
     * @generatedValue(strategy="AUTO")
1088
     * @SequenceGenerator(sequenceName="tablename_seq", initialValue=1, allocationSize=100)
1089
     **/
1090
    public $id;
1091
1092
    /**
1093
     * @Column(length=50, nullable=true, unique=true, options={"foo": "bar", "baz": {"key": "val"}, "fixed": false})
1094
     */
1095
    public $name;
1096
1097
    /**
1098
     * @Column(name="user_email", columnDefinition="CHAR(32) NOT NULL")
1099
     */
1100
    public $email;
1101
1102
    /**
1103
     * @OneToOne(targetEntity="Address", cascade={"remove"}, inversedBy="user")
1104
     * @JoinColumn(onDelete="CASCADE")
1105
     */
1106
    public $address;
1107
1108
    /**
1109
     * @OneToMany(targetEntity="Phonenumber", mappedBy="user", cascade={"persist"}, orphanRemoval=true)
1110
     * @OrderBy({"number"="ASC"})
1111
     */
1112
    public $phonenumbers;
1113
1114
    /**
1115
     * @ManyToMany(targetEntity="Group", cascade={"all"})
1116
     * @JoinTable(name="cms_user_groups",
1117
     *    joinColumns={@JoinColumn(name="user_id", referencedColumnName="id", nullable=false, unique=false)},
1118
     *    inverseJoinColumns={@JoinColumn(name="group_id", referencedColumnName="id", columnDefinition="INT NULL")}
1119
     * )
1120
     */
1121
    public $groups;
1122
1123
    /**
1124
     * @Column(type="integer")
1125
     * @Version
1126
     */
1127
    public $version;
1128
1129
1130
    /**
1131
     * @PrePersist
1132
     */
1133
    public function doStuffOnPrePersist()
1134
    {
1135
    }
1136
1137
    /**
1138
     * @PrePersist
1139
     */
1140
    public function doOtherStuffOnPrePersistToo() {
1141
    }
1142
1143
    /**
1144
     * @PostPersist
1145
     */
1146
    public function doStuffOnPostPersist()
1147
    {
1148
1149
    }
1150
1151
    public static function loadMetadata(ClassMetadataInfo $metadata)
1152
    {
1153
        $metadata->setInheritanceType(ClassMetadataInfo::INHERITANCE_TYPE_NONE);
1154
        $metadata->setPrimaryTable(
1155
            [
1156
           'name' => 'cms_users',
1157
           'options' => ['foo' => 'bar', 'baz' => ['key' => 'val']],
1158
            ]
1159
        );
1160
        $metadata->setChangeTrackingPolicy(ClassMetadataInfo::CHANGETRACKING_DEFERRED_IMPLICIT);
1161
        $metadata->addLifecycleCallback('doStuffOnPrePersist', 'prePersist');
1162
        $metadata->addLifecycleCallback('doOtherStuffOnPrePersistToo', 'prePersist');
1163
        $metadata->addLifecycleCallback('doStuffOnPostPersist', 'postPersist');
1164
        $metadata->mapField(
1165
            [
1166
           'id' => true,
1167
           'fieldName' => 'id',
1168
           'type' => 'integer',
1169
           'columnName' => 'id',
1170
           'options' => ['foo' => 'bar', 'unsigned' => false],
1171
            ]
1172
        );
1173
        $metadata->mapField(
1174
            [
1175
           'fieldName' => 'name',
1176
           'type' => 'string',
1177
           'length' => 50,
1178
           'unique' => true,
1179
           'nullable' => true,
1180
           'columnName' => 'name',
1181
           'options' => ['foo' => 'bar', 'baz' => ['key' => 'val'], 'fixed' => false],
1182
            ]
1183
        );
1184
        $metadata->mapField(
1185
            [
1186
           'fieldName' => 'email',
1187
           'type' => 'string',
1188
           'columnName' => 'user_email',
1189
           'columnDefinition' => 'CHAR(32) NOT NULL',
1190
            ]
1191
        );
1192
        $mapping = ['fieldName' => 'version', 'type' => 'integer'];
1193
        $metadata->setVersionMapping($mapping);
1194
        $metadata->mapField($mapping);
1195
        $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO);
1196
        $metadata->mapOneToOne(
1197
            [
1198
           'fieldName' => 'address',
1199
           'targetEntity' => Address::class,
1200
           'cascade' =>
1201
           [
1202
           0 => 'remove',
1203
           ],
1204
           'mappedBy' => NULL,
1205
           'inversedBy' => 'user',
1206
           'joinColumns' =>
1207
           [
1208
           0 =>
1209
           [
1210
            'name' => 'address_id',
1211
            'referencedColumnName' => 'id',
1212
            'onDelete' => 'CASCADE',
1213
           ],
1214
           ],
1215
           'orphanRemoval' => false,
1216
            ]
1217
        );
1218
        $metadata->mapOneToMany(
1219
            [
1220
           'fieldName' => 'phonenumbers',
1221
           'targetEntity' => Phonenumber::class,
1222
           'cascade' =>
1223
           [
1224
           1 => 'persist',
1225
           ],
1226
           'mappedBy' => 'user',
1227
           'orphanRemoval' => true,
1228
           'orderBy' =>
1229
           [
1230
           'number' => 'ASC',
1231
           ],
1232
            ]
1233
        );
1234
        $metadata->mapManyToMany(
1235
            [
1236
           'fieldName' => 'groups',
1237
           'targetEntity' => Group::class,
1238
           'cascade' =>
1239
           [
1240
           0 => 'remove',
1241
           1 => 'persist',
1242
           2 => 'refresh',
1243
           3 => 'merge',
1244
           4 => 'detach',
1245
           ],
1246
           'mappedBy' => NULL,
1247
           'joinTable' =>
1248
           [
1249
           'name' => 'cms_users_groups',
1250
           'joinColumns' =>
1251
           [
1252
            0 =>
1253
            [
1254
            'name' => 'user_id',
1255
            'referencedColumnName' => 'id',
1256
            'unique' => false,
1257
            'nullable' => false,
1258
            ],
1259
           ],
1260
           'inverseJoinColumns' =>
1261
           [
1262
            0 =>
1263
            [
1264
            'name' => 'group_id',
1265
            'referencedColumnName' => 'id',
1266
            'columnDefinition' => 'INT NULL',
1267
            ],
1268
           ],
1269
           ],
1270
           'orderBy' => NULL,
1271
            ]
1272
        );
1273
        $metadata->table['uniqueConstraints'] = [
1274
            'search_idx' => ['columns' => ['name', 'user_email'], 'options'=> ['where' => 'name IS NOT NULL']],
1275
        ];
1276
        $metadata->table['indexes'] = [
1277
            'name_idx' => ['columns' => ['name']], 0 => ['columns' => ['user_email']]
1278
        ];
1279
        $metadata->setSequenceGeneratorDefinition(
1280
            [
1281
                'sequenceName' => 'tablename_seq',
1282
                'allocationSize' => 100,
1283
                'initialValue' => 1,
1284
            ]
1285
        );
1286
        $metadata->addNamedQuery(
1287
            [
1288
                'name' => 'all',
1289
                'query' => 'SELECT u FROM __CLASS__ u'
1290
            ]
1291
        );
1292
    }
1293
}
1294
1295
/**
1296
 * @Entity
1297
 * @InheritanceType("SINGLE_TABLE")
1298
 * @DiscriminatorMap({"cat" = "Cat", "dog" = "Dog"})
1299
 * @DiscriminatorColumn(name="discr", length=32, type="string")
1300
 */
1301
abstract class Animal
1302
{
1303
    /**
1304
     * @Id @Column(type="string") @GeneratedValue(strategy="CUSTOM")
1305
     * @CustomIdGenerator(class="stdClass")
1306
     */
1307
    public $id;
1308
1309
    public static function loadMetadata(ClassMetadataInfo $metadata)
1310
    {
1311
        $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_CUSTOM);
1312
        $metadata->setCustomGeneratorDefinition(["class" => "stdClass"]);
1313
    }
1314
}
1315
1316
/** @Entity */
1317
class Cat extends Animal
1318
{
1319
    public static function loadMetadata(ClassMetadataInfo $metadata)
1320
    {
1321
1322
    }
1323
}
1324
1325
/** @Entity */
1326
class Dog extends Animal
1327
{
1328
    public static function loadMetadata(ClassMetadataInfo $metadata)
1329
    {
1330
1331
    }
1332
}
1333
1334
1335
/**
1336
 * @Entity
1337
 */
1338
class DDC1170Entity
1339
{
1340
1341
    /**
1342
     * @param string $value
1343
     */
1344
    function __construct($value = null)
1345
    {
1346
        $this->value = $value;
1347
    }
1348
1349
    /**
1350
     * @Id
1351
     * @GeneratedValue(strategy="NONE")
1352
     * @Column(type="integer", columnDefinition = "INT unsigned NOT NULL")
1353
     **/
1354
    private $id;
1355
1356
    /**
1357
     * @Column(columnDefinition = "VARCHAR(255) NOT NULL")
1358
     */
1359
    private $value;
1360
1361
    /**
1362
     * @return int
1363
     */
1364
    public function getId()
1365
    {
1366
        return $this->id;
1367
    }
1368
1369
    /**
1370
     * @return string
1371
     */
1372
    public function getValue()
1373
    {
1374
        return $this->value;
1375
    }
1376
1377
    public static function loadMetadata(ClassMetadataInfo $metadata)
1378
    {
1379
        $metadata->mapField(
1380
            [
1381
           'id'                 => true,
1382
           'fieldName'          => 'id',
1383
           'columnDefinition'   => 'INT unsigned NOT NULL',
1384
            ]
1385
        );
1386
1387
        $metadata->mapField(
1388
            [
1389
            'fieldName'         => 'value',
1390
            'columnDefinition'  => 'VARCHAR(255) NOT NULL'
1391
            ]
1392
        );
1393
1394
        $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_NONE);
1395
    }
1396
1397
}
1398
1399
/**
1400
 * @Entity
1401
 * @InheritanceType("SINGLE_TABLE")
1402
 * @DiscriminatorMap({"ONE" = "DDC807SubClasse1", "TWO" = "DDC807SubClasse2"})
1403
 * @DiscriminatorColumn(name = "dtype", columnDefinition="ENUM('ONE','TWO')")
1404
 */
1405
class DDC807Entity
1406
{
1407
    /**
1408
     * @Id
1409
     * @Column(type="integer")
1410
     * @GeneratedValue(strategy="NONE")
1411
     **/
1412
   public $id;
1413
1414
   public static function loadMetadata(ClassMetadataInfo $metadata)
1415
    {
1416
         $metadata->mapField(
1417
             [
1418
           'id'                 => true,
1419
           'fieldName'          => 'id',
1420
             ]
1421
         );
1422
1423
        $metadata->setDiscriminatorColumn(
1424
            [
1425
            'name'              => "dtype",
1426
            'type'              => "string",
1427
            'columnDefinition'  => "ENUM('ONE','TWO')"
1428
            ]
1429
        );
1430
1431
        $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_NONE);
1432
    }
1433
}
1434
1435
class DDC807SubClasse1 {}
1436
class DDC807SubClasse2 {}
1437
1438
class Address {}
1439
class Phonenumber {}
1440
class Group {}
1441
1442
/**
1443
 * @Entity
1444
 * @Table(indexes={@Index(columns={"content"}, flags={"fulltext"}, options={"where": "content IS NOT NULL"})})
1445
 */
1446
class Comment
1447
{
1448
    /**
1449
     * @Column(type="text")
1450
     */
1451
    private $content;
1452
1453
    public static function loadMetadata(ClassMetadataInfo $metadata)
1454
    {
1455
        $metadata->setInheritanceType(ClassMetadataInfo::INHERITANCE_TYPE_NONE);
1456
        $metadata->setPrimaryTable(
1457
            [
1458
            'indexes' => [
1459
                ['columns' => ['content'], 'flags' => ['fulltext'], 'options' => ['where' => 'content IS NOT NULL']]
1460
            ]
1461
            ]
1462
        );
1463
1464
        $metadata->mapField(
1465
            [
1466
            'fieldName' => 'content',
1467
            'type' => 'text',
1468
            'scale' => 0,
1469
            'length' => NULL,
1470
            'unique' => false,
1471
            'nullable' => false,
1472
            'precision' => 0,
1473
            'columnName' => 'content',
1474
            ]
1475
        );
1476
    }
1477
}
1478
1479
/**
1480
 * @Entity
1481
 * @InheritanceType("SINGLE_TABLE")
1482
 * @DiscriminatorMap({
1483
 *     "ONE" = "SingleTableEntityNoDiscriminatorColumnMappingSub1",
1484
 *     "TWO" = "SingleTableEntityNoDiscriminatorColumnMappingSub2"
1485
 * })
1486
 */
1487
class SingleTableEntityNoDiscriminatorColumnMapping
1488
{
1489
    /**
1490
     * @Id
1491
     * @Column(type="integer")
1492
     * @GeneratedValue(strategy="NONE")
1493
     */
1494
    public $id;
1495
1496
    public static function loadMetadata(ClassMetadataInfo $metadata)
1497
    {
1498
        $metadata->mapField(
1499
            [
1500
            'id' => true,
1501
            'fieldName' => 'id',
1502
            ]
1503
        );
1504
1505
        $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_NONE);
1506
    }
1507
}
1508
1509
class SingleTableEntityNoDiscriminatorColumnMappingSub1 extends SingleTableEntityNoDiscriminatorColumnMapping {}
1510
class SingleTableEntityNoDiscriminatorColumnMappingSub2 extends SingleTableEntityNoDiscriminatorColumnMapping {}
1511
1512
/**
1513
 * @Entity
1514
 * @InheritanceType("SINGLE_TABLE")
1515
 * @DiscriminatorMap({
1516
 *     "ONE" = "SingleTableEntityIncompleteDiscriminatorColumnMappingSub1",
1517
 *     "TWO" = "SingleTableEntityIncompleteDiscriminatorColumnMappingSub2"
1518
 * })
1519
 * @DiscriminatorColumn(name="dtype")
1520
 */
1521
class SingleTableEntityIncompleteDiscriminatorColumnMapping
1522
{
1523
    /**
1524
     * @Id
1525
     * @Column(type="integer")
1526
     * @GeneratedValue(strategy="NONE")
1527
     */
1528
    public $id;
1529
1530
    public static function loadMetadata(ClassMetadataInfo $metadata)
1531
    {
1532
        $metadata->mapField(
1533
            [
1534
            'id' => true,
1535
            'fieldName' => 'id',
1536
            ]
1537
        );
1538
1539
        $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_NONE);
1540
    }
1541
}
1542
1543
class SingleTableEntityIncompleteDiscriminatorColumnMappingSub1
1544
    extends SingleTableEntityIncompleteDiscriminatorColumnMapping {}
1545
class SingleTableEntityIncompleteDiscriminatorColumnMappingSub2
1546
    extends SingleTableEntityIncompleteDiscriminatorColumnMapping {}
1547