Completed
Push — master ( 22ecc2...971c40 )
by Marco
14:47
created

testFetchOverrideMapping()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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