Failed Conditions
Push — master ( becf73...b9880b )
by Guilherme
09:53
created

testDuplicateColumnNameDiscriminatorColumn2ThrowsMappingException()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 11
nc 1
nop 0
dl 0
loc 20
rs 9.9
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Tests\ORM\Mapping;
6
7
use Doctrine\DBAL\Types\Type;
8
use Doctrine\ORM\Events;
9
use Doctrine\ORM\Mapping;
10
use Doctrine\ORM\Mapping\ClassMetadata;
11
use Doctrine\ORM\Mapping\DiscriminatorColumnMetadata;
12
use Doctrine\ORM\Mapping\Factory\DefaultNamingStrategy;
13
use Doctrine\ORM\Mapping\Factory\UnderscoreNamingStrategy;
14
use Doctrine\ORM\Mapping\JoinColumnMetadata;
15
use Doctrine\ORM\Mapping\MappingException;
16
use Doctrine\ORM\Reflection\RuntimeReflectionService;
17
use Doctrine\ORM\Reflection\StaticReflectionService;
18
use Doctrine\Tests\Models\CMS;
19
use Doctrine\Tests\Models\Company\CompanyContract;
20
use Doctrine\Tests\Models\Company\CompanyContractListener;
21
use Doctrine\Tests\Models\CustomType\CustomTypeParent;
22
use Doctrine\Tests\Models\DDC117\DDC117Article;
23
use Doctrine\Tests\Models\DDC117\DDC117ArticleDetails;
24
use Doctrine\Tests\Models\DDC6412\DDC6412File;
25
use Doctrine\Tests\Models\DDC964\DDC964Address;
26
use Doctrine\Tests\Models\DDC964\DDC964Admin;
27
use Doctrine\Tests\Models\DDC964\DDC964Guest;
28
use Doctrine\Tests\OrmTestCase;
29
use DoctrineGlobalArticle;
30
use PHPUnit_Framework_MockObject_MockObject;
31
use ReflectionClass;
32
use stdClass;
33
use const CASE_UPPER;
34
use function reset;
35
use function serialize;
36
use function str_replace;
37
use function strpos;
38
use function strtolower;
39
use function strtoupper;
40
use function unserialize;
41
42
require_once __DIR__ . '/../../Models/Global/GlobalNamespaceModel.php';
43
44
class ClassMetadataTest extends OrmTestCase
45
{
46
    /** @var Mapping\ClassMetadataBuildingContext|PHPUnit_Framework_MockObject_MockObject */
47
    private $metadataBuildingContext;
48
49
    public function setUp() : void
50
    {
51
        parent::setUp();
52
53
        $this->metadataBuildingContext = new Mapping\ClassMetadataBuildingContext(
54
            $this->createMock(Mapping\ClassMetadataFactory::class),
55
            new RuntimeReflectionService()
56
        );
57
    }
58
59
    public function testClassMetadataInstanceSimpleState() : void
60
    {
61
        $cm = new ClassMetadata(CMS\CmsUser::class, null, $this->metadataBuildingContext);
62
        $cm->setTable(new Mapping\TableMetadata('cms_users'));
63
64
        self::assertInstanceOf(ReflectionClass::class, $cm->getReflectionClass());
65
        self::assertEquals(CMS\CmsUser::class, $cm->getClassName());
66
        self::assertEquals(CMS\CmsUser::class, $cm->getRootClassName());
67
        self::assertEquals([], $cm->getSubClasses());
68
        self::assertCount(0, $cm->getAncestorsIterator());
69
        self::assertEquals(Mapping\InheritanceType::NONE, $cm->inheritanceType);
70
    }
71
72
    public function testClassMetadataInstanceSerialization() : void
73
    {
74
        $parent = new ClassMetadata(CMS\CmsEmployee::class, null, $this->metadataBuildingContext);
75
        $parent->setTable(new Mapping\TableMetadata('cms_employee'));
76
77
        $cm = new ClassMetadata(CMS\CmsUser::class, $parent, $this->metadataBuildingContext);
78
        $cm->setTable($parent->table);
79
        $cm->setParent($parent);
80
81
        $discrColumn = new DiscriminatorColumnMetadata();
82
83
        $discrColumn->setColumnName('disc');
84
        $discrColumn->setType(Type::getType('integer'));
85
86
        $cm->setInheritanceType(Mapping\InheritanceType::SINGLE_TABLE);
0 ignored issues
show
Bug introduced by
Doctrine\ORM\Mapping\InheritanceType::SINGLE_TABLE of type string is incompatible with the type integer expected by parameter $type of Doctrine\ORM\Mapping\Cla...a::setInheritanceType(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

86
        $cm->setInheritanceType(/** @scrutinizer ignore-type */ Mapping\InheritanceType::SINGLE_TABLE);
Loading history...
87
        $cm->setSubclasses([
88
            'Doctrine\Tests\Models\CMS\One',
89
            'Doctrine\Tests\Models\CMS\Two',
90
            'Doctrine\Tests\Models\CMS\Three',
91
        ]);
92
        $cm->setCustomRepositoryClassName('Doctrine\Tests\Models\CMS\UserRepository');
93
        $cm->setDiscriminatorColumn($discrColumn);
94
        $cm->asReadOnly();
95
96
        $association = new Mapping\OneToOneAssociationMetadata('phonenumbers');
97
98
        $association->setTargetEntity(CMS\CmsAddress::class);
99
        $association->setMappedBy('foo');
100
101
        $cm->addProperty($association);
102
103
        self::assertCount(1, $cm->getDeclaredPropertiesIterator());
104
105
        $serialized = serialize($cm);
106
        $cm         = unserialize($serialized);
107
108
        $cm->wakeupReflection(new RuntimeReflectionService());
109
110
        // Check state
111
        self::assertInstanceOf(ReflectionClass::class, $cm->getReflectionClass());
112
        self::assertEquals(CMS\CmsUser::class, $cm->getClassName());
113
        self::assertEquals(CMS\CmsEmployee::class, $cm->getRootClassName());
114
        self::assertEquals('Doctrine\Tests\Models\CMS\UserRepository', $cm->getCustomRepositoryClassName());
115
        self::assertEquals(
116
            [
117
                'Doctrine\Tests\Models\CMS\One',
118
                'Doctrine\Tests\Models\CMS\Two',
119
                'Doctrine\Tests\Models\CMS\Three',
120
            ],
121
            $cm->getSubClasses()
122
        );
123
        self::assertCount(1, $cm->getAncestorsIterator());
124
        self::assertEquals(CMS\CmsEmployee::class, $cm->getAncestorsIterator()->current()->getClassName());
125
        self::assertEquals($discrColumn, $cm->discriminatorColumn);
126
        self::assertTrue($cm->isReadOnly());
127
        self::assertCount(1, $cm->getDeclaredPropertiesIterator());
128
        self::assertInstanceOf(Mapping\OneToOneAssociationMetadata::class, $cm->getProperty('phonenumbers'));
129
130
        $oneOneMapping = $cm->getProperty('phonenumbers');
131
132
        self::assertEquals(Mapping\FetchMode::LAZY, $oneOneMapping->getFetchMode());
133
        self::assertEquals(CMS\CmsAddress::class, $oneOneMapping->getTargetEntity());
134
    }
135
136
    public function testFieldIsNullable() : void
137
    {
138
        $metadata = new ClassMetadata(CMS\CmsUser::class, null, $this->metadataBuildingContext);
139
        $metadata->setTable(new Mapping\TableMetadata('cms_users'));
140
141
        // Explicit Nullable
142
        $fieldMetadata = new Mapping\FieldMetadata('status');
143
144
        $fieldMetadata->setType(Type::getType('string'));
145
        $fieldMetadata->setLength(50);
146
        $fieldMetadata->setNullable(true);
147
148
        $metadata->addProperty($fieldMetadata);
149
150
        $property = $metadata->getProperty('status');
151
152
        self::assertTrue($property->isNullable());
0 ignored issues
show
Bug introduced by
The method isNullable() does not exist on Doctrine\ORM\Mapping\Property. It seems like you code against a sub-type of Doctrine\ORM\Mapping\Property such as Doctrine\ORM\Mapping\FieldMetadata. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

152
        self::assertTrue($property->/** @scrutinizer ignore-call */ isNullable());
Loading history...
153
154
        // Explicit Not Nullable
155
        $fieldMetadata = new Mapping\FieldMetadata('username');
156
157
        $fieldMetadata->setType(Type::getType('string'));
158
        $fieldMetadata->setLength(50);
159
        $fieldMetadata->setNullable(false);
160
161
        $metadata->addProperty($fieldMetadata);
162
163
        $property = $metadata->getProperty('username');
164
165
        self::assertFalse($property->isNullable());
166
167
        // Implicit Not Nullable
168
        $fieldMetadata = new Mapping\FieldMetadata('name');
169
170
        $fieldMetadata->setType(Type::getType('string'));
171
        $fieldMetadata->setLength(50);
172
173
        $metadata->addProperty($fieldMetadata);
174
175
        $property = $metadata->getProperty('name');
176
177
        self::assertFalse($property->isNullable(), 'By default a field should not be nullable.');
178
    }
179
180
    /**
181
     * @group DDC-115
182
     */
183
    public function testMapAssociationInGlobalNamespace() : void
184
    {
185
        require_once __DIR__ . '/../../Models/Global/GlobalNamespaceModel.php';
186
187
        $cm = new ClassMetadata(DoctrineGlobalArticle::class, null, $this->metadataBuildingContext);
188
        $cm->setTable(new Mapping\TableMetadata('doctrine_global_article'));
189
190
        $joinTable = new Mapping\JoinTableMetadata();
191
        $joinTable->setName('bar');
192
193
        $joinColumn = new Mapping\JoinColumnMetadata();
194
        $joinColumn->setColumnName('bar_id');
195
        $joinColumn->setReferencedColumnName('id');
196
197
        $joinTable->addJoinColumn($joinColumn);
198
199
        $joinColumn = new Mapping\JoinColumnMetadata();
200
        $joinColumn->setColumnName('baz_id');
201
        $joinColumn->setReferencedColumnName('id');
202
203
        $joinTable->addInverseJoinColumn($joinColumn);
204
205
        $association = new Mapping\ManyToManyAssociationMetadata('author');
206
207
        $association->setJoinTable($joinTable);
208
        $association->setTargetEntity('DoctrineGlobalUser');
209
210
        $cm->addProperty($association);
211
212
        self::assertEquals('DoctrineGlobalUser', $cm->getProperty('author')->getTargetEntity());
0 ignored issues
show
Bug introduced by
The method getTargetEntity() does not exist on Doctrine\ORM\Mapping\Property. It seems like you code against a sub-type of Doctrine\ORM\Mapping\Property such as Doctrine\ORM\Mapping\AssociationMetadata. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

212
        self::assertEquals('DoctrineGlobalUser', $cm->getProperty('author')->/** @scrutinizer ignore-call */ getTargetEntity());
Loading history...
213
    }
214
215
    public function testMapManyToManyJoinTableDefaults() : void
216
    {
217
        $cm = new ClassMetadata(CMS\CmsUser::class, null, $this->metadataBuildingContext);
218
        $cm->setTable(new Mapping\TableMetadata('cms_users'));
219
220
        $association = new Mapping\ManyToManyAssociationMetadata('groups');
221
222
        $association->setTargetEntity(CMS\CmsGroup::class);
223
224
        $cm->addProperty($association);
225
226
        $association = $cm->getProperty('groups');
227
228
        $joinColumns = [];
229
230
        $joinColumn = new Mapping\JoinColumnMetadata();
231
232
        $joinColumn->setColumnName('cmsuser_id');
233
        $joinColumn->setReferencedColumnName('id');
234
        $joinColumn->setOnDelete('CASCADE');
235
236
        $joinColumns[] = $joinColumn;
237
238
        $inverseJoinColumns = [];
239
240
        $joinColumn = new Mapping\JoinColumnMetadata();
241
242
        $joinColumn->setColumnName('cmsgroup_id');
243
        $joinColumn->setReferencedColumnName('id');
244
        $joinColumn->setOnDelete('CASCADE');
245
246
        $inverseJoinColumns[] = $joinColumn;
247
248
        $joinTable = $association->getJoinTable();
0 ignored issues
show
Bug introduced by
The method getJoinTable() does not exist on Doctrine\ORM\Mapping\Property. It seems like you code against a sub-type of Doctrine\ORM\Mapping\Property such as Doctrine\ORM\Mapping\ManyToManyAssociationMetadata. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

248
        /** @scrutinizer ignore-call */ 
249
        $joinTable = $association->getJoinTable();
Loading history...
249
250
        self::assertEquals('cmsuser_cmsgroup', $joinTable->getName());
251
        self::assertEquals($joinColumns, $joinTable->getJoinColumns());
252
        self::assertEquals($inverseJoinColumns, $joinTable->getInverseJoinColumns());
253
    }
254
255
    public function testSerializeManyToManyJoinTableCascade() : void
256
    {
257
        $cm = new ClassMetadata(CMS\CmsUser::class, null, $this->metadataBuildingContext);
258
        $cm->setTable(new Mapping\TableMetadata('cms_users'));
259
260
        $association = new Mapping\ManyToManyAssociationMetadata('groups');
261
262
        $association->setTargetEntity(CMS\CmsGroup::class);
263
264
        $cm->addProperty($association);
265
266
        $association = $cm->getProperty('groups');
267
        $association = unserialize(serialize($association));
268
269
        $joinTable = $association->getJoinTable();
270
271
        foreach ($joinTable->getJoinColumns() as $joinColumn) {
272
            self::assertEquals('CASCADE', $joinColumn->getOnDelete());
273
        }
274
    }
275
276
    /**
277
     * @group DDC-115
278
     */
279
    public function testSetDiscriminatorMapInGlobalNamespace() : void
280
    {
281
        require_once __DIR__ . '/../../Models/Global/GlobalNamespaceModel.php';
282
283
        $cm = new ClassMetadata('DoctrineGlobalUser', null, $this->metadataBuildingContext);
284
        $cm->setTable(new Mapping\TableMetadata('doctrine_global_user'));
285
286
        $cm->setDiscriminatorMap(['descr' => 'DoctrineGlobalArticle', 'foo' => 'DoctrineGlobalUser']);
287
288
        self::assertEquals('DoctrineGlobalArticle', $cm->discriminatorMap['descr']);
289
        self::assertEquals('DoctrineGlobalUser', $cm->discriminatorMap['foo']);
290
    }
291
292
    /**
293
     * @group DDC-115
294
     */
295
    public function testSetSubClassesInGlobalNamespace() : void
296
    {
297
        require_once __DIR__ . '/../../Models/Global/GlobalNamespaceModel.php';
298
299
        $cm = new ClassMetadata('DoctrineGlobalUser', null, $this->metadataBuildingContext);
300
        $cm->setTable(new Mapping\TableMetadata('doctrine_global_user'));
301
302
        $cm->setSubclasses(['DoctrineGlobalArticle']);
303
304
        self::assertEquals('DoctrineGlobalArticle', $cm->getSubClasses()[0]);
305
    }
306
307
    /**
308
     * @group DDC-268
309
     */
310
    public function testSetInvalidVersionMappingThrowsException() : void
311
    {
312
        $cm = new ClassMetadata(CMS\CmsUser::class, null, $this->metadataBuildingContext);
313
        $cm->setTable(new Mapping\TableMetadata('cms_users'));
314
315
        $property = new Mapping\FieldMetadata('foo');
316
317
        $property->setDeclaringClass($cm);
318
        $property->setColumnName('foo');
319
        $property->setType(Type::getType('string'));
320
        $property->setVersioned(true);
321
322
        $this->expectException(MappingException::class);
323
324
        $cm->addProperty($property);
325
    }
326
327
    public function testGetSingleIdentifierFieldNameMultipleIdentifierEntityThrowsException() : void
328
    {
329
        $cm = new ClassMetadata(CMS\CmsUser::class, null, $this->metadataBuildingContext);
330
        $cm->setTable(new Mapping\TableMetadata('cms_users'));
331
332
        $fieldMetadata = new Mapping\FieldMetadata('name');
333
        $fieldMetadata->setType(Type::getType('string'));
334
335
        $cm->addProperty($fieldMetadata);
336
337
        $fieldMetadata = new Mapping\FieldMetadata('username');
338
        $fieldMetadata->setType(Type::getType('string'));
339
340
        $cm->addProperty($fieldMetadata);
341
342
        $cm->setIdentifier(['name', 'username']);
343
344
        $this->expectException(MappingException::class);
345
346
        $cm->getSingleIdentifierFieldName();
347
    }
348
349
    public function testGetSingleIdentifierFieldNameNoIdEntityThrowsException() : void
350
    {
351
        $cm = new ClassMetadata(DDC6412File::class, null, $this->metadataBuildingContext);
352
        $cm->setTable(new Mapping\TableMetadata('ddc6412_file'));
353
354
        $this->expectException(MappingException::class);
355
356
        $cm->getSingleIdentifierFieldName();
357
    }
358
359
    public function testDuplicateAssociationMappingException() : void
360
    {
361
        $cm = new ClassMetadata(CMS\CmsUser::class, null, $this->metadataBuildingContext);
362
        $cm->setTable(new Mapping\TableMetadata('cms_users'));
363
364
        $association = new Mapping\OneToOneAssociationMetadata('foo');
365
366
        $association->setDeclaringClass($cm);
367
        $association->setSourceEntity(stdClass::class);
368
        $association->setTargetEntity(stdClass::class);
369
        $association->setMappedBy('foo');
370
371
        $cm->addInheritedProperty($association);
372
373
        $this->expectException(MappingException::class);
374
375
        $association = new Mapping\OneToOneAssociationMetadata('foo');
376
377
        $association->setDeclaringClass($cm);
378
        $association->setSourceEntity(stdClass::class);
379
        $association->setTargetEntity(stdClass::class);
380
        $association->setMappedBy('foo');
381
382
        $cm->addInheritedProperty($association);
383
    }
384
385
    public function testDuplicateColumnNameThrowsMappingException() : void
386
    {
387
        $cm = new ClassMetadata(CMS\CmsUser::class, null, $this->metadataBuildingContext);
388
        $cm->setTable(new Mapping\TableMetadata('cms_users'));
389
390
        $fieldMetadata = new Mapping\FieldMetadata('name');
391
392
        $fieldMetadata->setType(Type::getType('string'));
393
394
        $cm->addProperty($fieldMetadata);
395
396
        self::assertTrue($cm->checkPropertyDuplication($fieldMetadata->getColumnName()));
397
    }
398
399
    public function testDuplicateColumnNameDiscriminatorColumnThrowsMappingException() : void
400
    {
401
        $cm = new ClassMetadata(CMS\CmsUser::class, null, $this->metadataBuildingContext);
402
        $cm->setTable(new Mapping\TableMetadata('cms_users'));
403
404
        $discrColumn = new DiscriminatorColumnMetadata();
405
406
        $discrColumn->setColumnName('name');
407
        $discrColumn->setType(Type::getType('string'));
408
        $discrColumn->setLength(255);
409
410
        $cm->setDiscriminatorColumn($discrColumn);
411
412
        self::assertTrue($cm->checkPropertyDuplication($discrColumn->getColumnName()));
413
    }
414
415
    public function testDuplicateFieldAndAssociationMapping1ThrowsException() : void
416
    {
417
        $cm = new ClassMetadata(CMS\CmsUser::class, null, $this->metadataBuildingContext);
418
        $cm->setTable(new Mapping\TableMetadata('cms_users'));
419
420
        $fieldMetadata = new Mapping\FieldMetadata('name');
421
422
        $fieldMetadata->setType(Type::getType('string'));
423
424
        $cm->addProperty($fieldMetadata);
425
426
        $this->expectException(MappingException::class);
427
428
        $association = new Mapping\OneToOneAssociationMetadata('name');
429
430
        $association->setTargetEntity(CMS\CmsUser::class);
431
432
        $cm->addProperty($association);
433
    }
434
435
    public function testDuplicateFieldAndAssociationMapping2ThrowsException() : void
436
    {
437
        $cm = new ClassMetadata(CMS\CmsUser::class, null, $this->metadataBuildingContext);
438
        $cm->setTable(new Mapping\TableMetadata('cms_users'));
439
440
        $association = new Mapping\OneToOneAssociationMetadata('name');
441
442
        $association->setTargetEntity(CMS\CmsUser::class);
443
444
        $cm->addProperty($association);
445
446
        $this->expectException(MappingException::class);
447
448
        $fieldMetadata = new Mapping\FieldMetadata('name');
449
450
        $fieldMetadata->setType(Type::getType('string'));
451
452
        $cm->addProperty($fieldMetadata);
453
    }
454
455
    /**
456
     * @group DDC-1224
457
     */
458
    public function testGetTemporaryTableNameSchema() : void
459
    {
460
        $cm = new ClassMetadata(CMS\CmsUser::class, null, $this->metadataBuildingContext);
461
        $cm->setTable(new Mapping\TableMetadata('cms_users'));
462
463
        $tableMetadata = new Mapping\TableMetadata();
464
465
        $tableMetadata->setSchema('foo');
466
        $tableMetadata->setName('bar');
467
468
        $cm->setTable($tableMetadata);
469
470
        self::assertEquals('foo_bar_id_tmp', $cm->getTemporaryIdTableName());
471
    }
472
473
    public function testDefaultTableName() : void
474
    {
475
        $cm = new ClassMetadata(CMS\CmsUser::class, null, $this->metadataBuildingContext);
476
        $cm->setTable(new Mapping\TableMetadata('CmsUser'));
477
478
        // When table's name is not given
479
        self::assertEquals('CmsUser', $cm->getTableName());
480
        self::assertEquals('CmsUser', $cm->table->getName());
481
482
        $cm = new ClassMetadata(CMS\CmsAddress::class, null, $this->metadataBuildingContext);
483
484
        // When joinTable's name is not given
485
        $joinTable = new Mapping\JoinTableMetadata();
486
487
        $joinColumn = new Mapping\JoinColumnMetadata();
488
        $joinColumn->setReferencedColumnName('id');
489
490
        $joinTable->addJoinColumn($joinColumn);
491
492
        $joinColumn = new Mapping\JoinColumnMetadata();
493
        $joinColumn->setReferencedColumnName('id');
494
495
        $joinTable->addInverseJoinColumn($joinColumn);
496
497
        $association = new Mapping\ManyToManyAssociationMetadata('user');
498
499
        $association->setJoinTable($joinTable);
500
        $association->setTargetEntity(CMS\CmsUser::class);
501
        $association->setInversedBy('users');
502
503
        $cm->addProperty($association);
504
505
        $association = $cm->getProperty('user');
506
507
        self::assertEquals('cmsaddress_cmsuser', $association->getJoinTable()->getName());
508
    }
509
510
    public function testDefaultJoinColumnName() : void
511
    {
512
        $cm = new ClassMetadata(CMS\CmsAddress::class, null, $this->metadataBuildingContext);
513
        $cm->setTable(new Mapping\TableMetadata('cms_address'));
514
515
        // this is really dirty, but it's the simplest way to test whether
516
        // joinColumn's name will be automatically set to user_id
517
        $joinColumns = [];
518
519
        $joinColumn = new JoinColumnMetadata();
520
521
        $joinColumn->setReferencedColumnName('id');
522
523
        $joinColumns[] = $joinColumn;
524
525
        $association = new Mapping\OneToOneAssociationMetadata('user');
526
527
        $association->setJoinColumns($joinColumns);
528
        $association->setTargetEntity(CMS\CmsUser::class);
529
530
        $cm->addProperty($association);
531
532
        $association = $cm->getProperty('user');
533
        $joinColumns = $association->getJoinColumns();
0 ignored issues
show
Bug introduced by
The method getJoinColumns() does not exist on Doctrine\ORM\Mapping\Property. It seems like you code against a sub-type of Doctrine\ORM\Mapping\Property such as Doctrine\ORM\Mapping\ToOneAssociationMetadata. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

533
        /** @scrutinizer ignore-call */ 
534
        $joinColumns = $association->getJoinColumns();
Loading history...
534
        $joinColumn  = reset($joinColumns);
535
536
        self::assertEquals('user_id', $joinColumn->getColumnName());
537
538
        $cm = new ClassMetadata(CMS\CmsAddress::class, null, $this->metadataBuildingContext);
539
        $cm->setTable(new Mapping\TableMetadata('cms_address'));
540
541
        $joinTable = new Mapping\JoinTableMetadata();
542
        $joinTable->setName('user_CmsUser');
543
544
        $joinColumn = new JoinColumnMetadata();
545
        $joinColumn->setReferencedColumnName('id');
546
547
        $joinTable->addJoinColumn($joinColumn);
548
549
        $joinColumn = new JoinColumnMetadata();
550
        $joinColumn->setReferencedColumnName('id');
551
552
        $joinTable->addInverseJoinColumn($joinColumn);
553
554
        $association = new Mapping\ManyToManyAssociationMetadata('user');
555
556
        $association->setJoinTable($joinTable);
557
        $association->setTargetEntity(CMS\CmsUser::class);
558
        $association->setInversedBy('users');
559
560
        $cm->addProperty($association);
561
562
        $association        = $cm->getProperty('user');
563
        $joinTable          = $association->getJoinTable();
564
        $joinColumns        = $joinTable->getJoinColumns();
565
        $joinColumn         = reset($joinColumns);
566
        $inverseJoinColumns = $joinTable->getInverseJoinColumns();
567
        $inverseJoinColumn  = reset($inverseJoinColumns);
568
569
        self::assertEquals('cmsaddress_id', $joinColumn->getColumnName());
570
        self::assertEquals('cmsuser_id', $inverseJoinColumn->getColumnName());
571
    }
572
573
    /**
574
     * @group DDC-559
575
     */
576
    public function testOneToOneUnderscoreNamingStrategyDefaults() : void
577
    {
578
        $namingStrategy = new UnderscoreNamingStrategy(CASE_UPPER);
579
580
        $this->metadataBuildingContext = new Mapping\ClassMetadataBuildingContext(
581
            $this->createMock(Mapping\ClassMetadataFactory::class),
582
            new RuntimeReflectionService(),
583
            $namingStrategy
584
        );
585
586
        $metadata = new ClassMetadata(CMS\CmsAddress::class, null, $this->metadataBuildingContext);
587
        $metadata->setTable(new Mapping\TableMetadata('cms_address'));
588
589
        $association = new Mapping\OneToOneAssociationMetadata('user');
590
591
        $association->setTargetEntity(CMS\CmsUser::class);
592
593
        $metadata->addProperty($association);
594
595
        $association = $metadata->getProperty('user');
596
        $joinColumns = $association->getJoinColumns();
597
        $joinColumn  = reset($joinColumns);
598
599
        self::assertEquals('USER_ID', $joinColumn->getColumnName());
600
        self::assertEquals('ID', $joinColumn->getReferencedColumnName());
601
    }
602
603
    /**
604
     * @group DDC-559
605
     */
606
    public function testManyToManyUnderscoreNamingStrategyDefaults() : void
607
    {
608
        $namingStrategy = new UnderscoreNamingStrategy(CASE_UPPER);
609
610
        $this->metadataBuildingContext = new Mapping\ClassMetadataBuildingContext(
611
            $this->createMock(Mapping\ClassMetadataFactory::class),
612
            new RuntimeReflectionService(),
613
            $namingStrategy
614
        );
615
616
        $metadata = new ClassMetadata(CMS\CmsAddress::class, null, $this->metadataBuildingContext);
617
        $metadata->setTable(new Mapping\TableMetadata('cms_address'));
618
619
        $association = new Mapping\ManyToManyAssociationMetadata('user');
620
621
        $association->setTargetEntity(CMS\CmsUser::class);
622
623
        $metadata->addProperty($association);
624
625
        $association        = $metadata->getProperty('user');
626
        $joinTable          = $association->getJoinTable();
627
        $joinColumns        = $joinTable->getJoinColumns();
628
        $joinColumn         = reset($joinColumns);
629
        $inverseJoinColumns = $joinTable->getInverseJoinColumns();
630
        $inverseJoinColumn  = reset($inverseJoinColumns);
631
632
        self::assertEquals('CMS_ADDRESS_CMS_USER', $joinTable->getName());
633
634
        self::assertEquals('CMS_ADDRESS_ID', $joinColumn->getColumnName());
635
        self::assertEquals('ID', $joinColumn->getReferencedColumnName());
636
637
        self::assertEquals('CMS_USER_ID', $inverseJoinColumn->getColumnName());
638
        self::assertEquals('ID', $inverseJoinColumn->getReferencedColumnName());
639
640
        $cm = new ClassMetadata('DoctrineGlobalArticle', null, $this->metadataBuildingContext);
641
642
        $association = new Mapping\ManyToManyAssociationMetadata('author');
643
644
        $association->setTargetEntity(CMS\CmsUser::class);
645
646
        $cm->addProperty($association);
647
648
        $association = $cm->getProperty('author');
649
650
        self::assertEquals('DOCTRINE_GLOBAL_ARTICLE_CMS_USER', $association->getJoinTable()->getName());
651
    }
652
653
    /**
654
     * @group DDC-886
655
     */
656
    public function testSetMultipleIdentifierSetsComposite() : void
657
    {
658
        $cm = new ClassMetadata(CMS\CmsUser::class, null, $this->metadataBuildingContext);
659
        $cm->setTable(new Mapping\TableMetadata('cms_users'));
660
661
        $fieldMetadata = new Mapping\FieldMetadata('name');
662
        $fieldMetadata->setType(Type::getType('string'));
663
664
        $cm->addProperty($fieldMetadata);
665
666
        $fieldMetadata = new Mapping\FieldMetadata('username');
667
        $fieldMetadata->setType(Type::getType('string'));
668
669
        $cm->addProperty($fieldMetadata);
670
671
        $cm->setIdentifier(['name', 'username']);
672
673
        self::assertTrue($cm->isIdentifierComposite());
674
    }
675
676
    /**
677
     * @group DDC-961
678
     */
679
    public function testJoinTableMappingDefaults() : void
680
    {
681
        $cm = new ClassMetadata('DoctrineGlobalArticle', null, $this->metadataBuildingContext);
682
683
        $association = new Mapping\ManyToManyAssociationMetadata('author');
684
685
        $association->setTargetEntity(CMS\CmsUser::class);
686
687
        $cm->addProperty($association);
688
689
        $association = $cm->getProperty('author');
690
691
        self::assertEquals('doctrineglobalarticle_cmsuser', $association->getJoinTable()->getName());
692
    }
693
694
    /**
695
     * @group DDC-117
696
     */
697
    public function testMapIdentifierAssociation() : void
698
    {
699
        $cm = new ClassMetadata(DDC117ArticleDetails::class, null, $this->metadataBuildingContext);
700
        $cm->setTable(new Mapping\TableMetadata('ddc117_article_details'));
701
702
        $association = new Mapping\OneToOneAssociationMetadata('article');
703
704
        $association->setTargetEntity(DDC117Article::class);
705
        $association->setPrimaryKey(true);
706
707
        $cm->addProperty($association);
708
709
        self::assertEquals(['article'], $cm->identifier);
710
    }
711
712
    /**
713
     * @group DDC-117
714
     */
715
    public function testOrphanRemovalIdentifierAssociation() : void
716
    {
717
        $cm = new ClassMetadata(DDC117ArticleDetails::class, null, $this->metadataBuildingContext);
718
        $cm->setTable(new Mapping\TableMetadata('ddc117_article_details'));
719
720
        $this->expectException(MappingException::class);
721
        $this->expectExceptionMessage('The orphan removal option is not allowed on an association that');
722
723
        $association = new Mapping\OneToOneAssociationMetadata('article');
724
725
        $association->setTargetEntity(DDC117Article::class);
726
        $association->setPrimaryKey(true);
727
        $association->setOrphanRemoval(true);
728
729
        $cm->addProperty($association);
730
    }
731
732
    /**
733
     * @group DDC-117
734
     */
735
    public function testInverseIdentifierAssociation() : void
736
    {
737
        $cm = new ClassMetadata(DDC117ArticleDetails::class, null, $this->metadataBuildingContext);
738
        $cm->setTable(new Mapping\TableMetadata('ddc117_article_details'));
739
740
        $this->expectException(MappingException::class);
741
        $this->expectExceptionMessage('An inverse association is not allowed to be identifier in');
742
743
        $association = new Mapping\OneToOneAssociationMetadata('article');
744
745
        $association->setTargetEntity(DDC117Article::class);
746
        $association->setPrimaryKey(true);
747
        $association->setMappedBy('details');
748
        $association->setOwningSide(false);
749
750
        $cm->addProperty($association);
751
    }
752
753
    /**
754
     * @group DDC-117
755
     */
756
    public function testIdentifierAssociationManyToMany() : void
757
    {
758
        $cm = new ClassMetadata(DDC117ArticleDetails::class, null, $this->metadataBuildingContext);
759
        $cm->setTable(new Mapping\TableMetadata('ddc117_article_details'));
760
761
        $this->expectException(MappingException::class);
762
        $this->expectExceptionMessage('Many-to-many or one-to-many associations are not allowed to be identifier in');
763
764
        $association = new Mapping\ManyToManyAssociationMetadata('article');
765
766
        $association->setTargetEntity(DDC117Article::class);
767
        $association->setPrimaryKey(true);
768
769
        $cm->addProperty($association);
770
    }
771
772
    /**
773
     * @group DDC-996
774
     */
775
    public function testEmptyFieldNameThrowsException() : void
776
    {
777
        $this->expectException(MappingException::class);
778
        $this->expectExceptionMessage("The field or association mapping misses the 'fieldName' attribute in entity '" . CMS\CmsUser::class . "'.");
779
780
        $cm = new ClassMetadata(CMS\CmsUser::class, null, $this->metadataBuildingContext);
781
        $cm->setTable(new Mapping\TableMetadata('cms_users'));
782
783
        $fieldMetadata = new Mapping\FieldMetadata('');
784
785
        $fieldMetadata->setType(Type::getType('string'));
786
787
        $cm->addProperty($fieldMetadata);
788
    }
789
790
    /**
791
     * @group DDC-2451
792
     */
793
    public function testSerializeEntityListeners() : void
794
    {
795
        $metadata = new ClassMetadata(CompanyContract::class, null, $this->metadataBuildingContext);
796
797
        $metadata->addEntityListener(Events::prePersist, CompanyContractListener::class, 'prePersistHandler');
798
        $metadata->addEntityListener(Events::postPersist, CompanyContractListener::class, 'postPersistHandler');
799
800
        $serialize   = serialize($metadata);
801
        $unserialize = unserialize($serialize);
802
803
        self::assertEquals($metadata->entityListeners, $unserialize->entityListeners);
804
    }
805
806
    /**
807
     * @group DDC-1068
808
     */
809
    public function testClassCaseSensitivity() : void
810
    {
811
        $cm = new ClassMetadata(strtoupper(CMS\CmsUser::class), null, $this->metadataBuildingContext);
812
        $cm->setTable(new Mapping\TableMetadata('cms_users'));
813
814
        self::assertEquals(CMS\CmsUser::class, $cm->getClassName());
815
    }
816
817
    /**
818
     * @group DDC-659
819
     */
820
    public function testLifecycleCallbackNotFound() : void
821
    {
822
        $cm = new ClassMetadata(CMS\CmsUser::class, null, $this->metadataBuildingContext);
823
        $cm->setTable(new Mapping\TableMetadata('cms_users'));
824
825
        $cm->addLifecycleCallback('notfound', 'postLoad');
826
827
        $this->expectException(MappingException::class);
828
        $this->expectExceptionMessage("Entity '" . CMS\CmsUser::class . "' has no method 'notfound' to be registered as lifecycle callback.");
829
830
        $cm->validateLifecycleCallbacks(new RuntimeReflectionService());
831
    }
832
833
    /**
834
     * @group ImproveErrorMessages
835
     */
836
    public function testTargetEntityNotFound() : void
837
    {
838
        $cm = new ClassMetadata(CMS\CmsUser::class, null, $this->metadataBuildingContext);
839
        $cm->setTable(new Mapping\TableMetadata('cms_users'));
840
841
        $association = new Mapping\ManyToOneAssociationMetadata('address');
842
843
        $association->setTargetEntity('UnknownClass');
844
845
        $cm->addProperty($association);
846
847
        $this->expectException(MappingException::class);
848
        $this->expectExceptionMessage("The target-entity 'UnknownClass' cannot be found in '" . CMS\CmsUser::class . "#address'.");
849
850
        $cm->validateAssociations();
851
    }
852
853
    /**
854
     * @group DDC-1746
855
     * @expectedException        \Doctrine\ORM\Mapping\MappingException
856
     * @expectedExceptionMessage You have specified invalid cascade options for Doctrine\Tests\Models\CMS\CmsUser::$address: 'invalid'; available options: 'remove', 'persist', and 'refresh'
857
     */
858
    public function testInvalidCascade() : void
859
    {
860
        $cm = new ClassMetadata(CMS\CmsUser::class, null, $this->metadataBuildingContext);
861
        $cm->setTable(new Mapping\TableMetadata('cms_users'));
862
863
        $association = new Mapping\ManyToOneAssociationMetadata('address');
864
865
        $association->setTargetEntity('UnknownClass');
866
        $association->setCascade(['invalid']);
867
868
        $cm->addProperty($association);
869
    }
870
871
    /**
872
     * @group DDC-964
873
     * @expectedException        \Doctrine\ORM\Mapping\MappingException
874
     * @expectedExceptionMessage Invalid field override named 'invalidPropertyName' for class 'Doctrine\Tests\Models\DDC964\DDC964Admin'
875
     */
876
    public function testInvalidPropertyAssociationOverrideNameException() : void
877
    {
878
        $cm = new ClassMetadata(DDC964Admin::class, null, $this->metadataBuildingContext);
879
        $cm->setTable(new Mapping\TableMetadata('ddc964_admin'));
880
881
        $association = new Mapping\ManyToOneAssociationMetadata('address');
882
883
        $association->setTargetEntity(DDC964Address::class);
884
885
        $cm->addProperty($association);
886
887
        $cm->setPropertyOverride(new Mapping\ManyToOneAssociationMetadata('invalidPropertyName'));
888
    }
889
890
    /**
891
     * @group DDC-964
892
     * @expectedException        \Doctrine\ORM\Mapping\MappingException
893
     * @expectedExceptionMessage Invalid field override named 'invalidPropertyName' for class 'Doctrine\Tests\Models\DDC964\DDC964Guest'.
894
     */
895
    public function testInvalidPropertyAttributeOverrideNameException() : void
896
    {
897
        $cm = new ClassMetadata(DDC964Guest::class, null, $this->metadataBuildingContext);
898
        $cm->setTable(new Mapping\TableMetadata('ddc964_guest'));
899
900
        $fieldMetadata = new Mapping\FieldMetadata('name');
901
        $fieldMetadata->setType(Type::getType('string'));
902
903
        $cm->addProperty($fieldMetadata);
904
905
        $fieldMetadata = new Mapping\FieldMetadata('invalidPropertyName');
906
        $fieldMetadata->setType(Type::getType('string'));
907
908
        $cm->setPropertyOverride($fieldMetadata);
909
    }
910
911
    /**
912
     * @group DDC-1955
913
     * @expectedException        \Doctrine\ORM\Mapping\MappingException
914
     * @expectedExceptionMessage Entity Listener "\InvalidClassName" declared on "Doctrine\Tests\Models\CMS\CmsUser" not found.
915
     */
916
    public function testInvalidEntityListenerClassException() : void
917
    {
918
        $cm = new ClassMetadata(CMS\CmsUser::class, null, $this->metadataBuildingContext);
919
        $cm->setTable(new Mapping\TableMetadata('cms_users'));
920
921
        $cm->addEntityListener(Events::postLoad, '\InvalidClassName', 'postLoadHandler');
922
    }
923
924
    /**
925
     * @group DDC-1955
926
     * @expectedException        \Doctrine\ORM\Mapping\MappingException
927
     * @expectedExceptionMessage Entity Listener "Doctrine\Tests\Models\Company\CompanyContractListener" declared on "Doctrine\Tests\Models\CMS\CmsUser" has no method "invalidMethod".
928
     */
929
    public function testInvalidEntityListenerMethodException() : void
930
    {
931
        $cm = new ClassMetadata(CMS\CmsUser::class, null, $this->metadataBuildingContext);
932
        $cm->setTable(new Mapping\TableMetadata('cms_users'));
933
934
        $cm->addEntityListener(Events::postLoad, 'Doctrine\Tests\Models\Company\CompanyContractListener', 'invalidMethod');
935
    }
936
937
    public function testManyToManySelfReferencingNamingStrategyDefaults() : void
938
    {
939
        $cm = new ClassMetadata(CustomTypeParent::class, null, $this->metadataBuildingContext);
940
        $cm->setTable(new Mapping\TableMetadata('custom_type_parent'));
941
942
        $association = new Mapping\ManyToManyAssociationMetadata('friendsWithMe');
943
944
        $association->setTargetEntity(CustomTypeParent::class);
945
946
        $cm->addProperty($association);
947
948
        $association = $cm->getProperty('friendsWithMe');
949
950
        $joinColumns = [];
951
952
        $joinColumn = new Mapping\JoinColumnMetadata();
953
954
        $joinColumn->setColumnName('customtypeparent_source');
955
        $joinColumn->setReferencedColumnName('id');
956
        $joinColumn->setOnDelete('CASCADE');
957
958
        $joinColumns[] = $joinColumn;
959
960
        $inverseJoinColumns = [];
961
962
        $joinColumn = new Mapping\JoinColumnMetadata();
963
964
        $joinColumn->setColumnName('customtypeparent_target');
965
        $joinColumn->setReferencedColumnName('id');
966
        $joinColumn->setOnDelete('CASCADE');
967
968
        $inverseJoinColumns[] = $joinColumn;
969
970
        $joinTable = $association->getJoinTable();
971
972
        self::assertEquals('customtypeparent_customtypeparent', $joinTable->getName());
973
        self::assertEquals($joinColumns, $joinTable->getJoinColumns());
974
        self::assertEquals($inverseJoinColumns, $joinTable->getInverseJoinColumns());
975
    }
976
977
    /**
978
     * @group DDC-2662
979
     * @group 6682
980
     */
981
    public function testQuotedSequenceName() : void
982
    {
983
        self::markTestIncomplete(
984
            '@guilhermeblanco, in #6683 we added allocationSize/initialValue as to the sequence definition but with the'
985
            . ' changes you have made I am not sure if the "initialValue" should still be verified here or if it should'
986
            . ' part of the metadata drivers'
987
        );
988
989
        $cm = new ClassMetadata(CMS\CmsUser::class, null, $this->metadataBuildingContext);
990
        $cm->setTable(new Mapping\TableMetadata('cms_users'));
991
992
        $id = new Mapping\FieldMetadata('id');
993
        $id->setValueGenerator(new Mapping\ValueGeneratorMetadata(
994
            Mapping\GeneratorType::SEQUENCE,
995
            [
996
                'sequenceName' => 'foo',
997
                'allocationSize' => 1,
998
            ]
999
        ));
1000
        $cm->addProperty($id);
1001
1002
        self::assertEquals(
1003
            ['sequenceName' => 'foo', 'allocationSize' => 1, 'initialValue' => '1'],
1004
            $cm->getProperty('id')->getValueGenerator()->getDefinition()
1005
        );
1006
    }
1007
1008
    /**
1009
     * @group DDC-2700
1010
     */
1011
    public function testIsIdentifierMappedSuperClass() : void
1012
    {
1013
        $class = new ClassMetadata(DDC2700MappedSuperClass::class, null, $this->metadataBuildingContext);
1014
1015
        self::assertFalse($class->isIdentifier('foo'));
1016
    }
1017
1018
    /**
1019
     * @group embedded
1020
     */
1021
    public function testWakeupReflectionWithEmbeddableAndStaticReflectionService() : void
1022
    {
1023
        $metadata = new ClassMetadata(TestEntity1::class, null, $this->metadataBuildingContext);
1024
        $cm->setTable(new Mapping\TableMetadata('test_entity1'));
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $cm seems to be never defined.
Loading history...
1025
1026
        $metadata->mapEmbedded(
1027
            [
1028
                'fieldName'    => 'test',
1029
                'class'        => TestEntity1::class,
1030
                'columnPrefix' => false,
1031
            ]
1032
        );
1033
1034
        $fieldMetadata = new Mapping\FieldMetadata('test.embeddedProperty');
1035
        $fieldMetadata->setType(Type::getType('string'));
1036
1037
        $metadata->addProperty($fieldMetadata);
1038
1039
        /*
1040
        $mapping = [
1041
            'originalClass' => TestEntity1::class,
1042
            'declaredField' => 'test',
1043
            'originalField' => 'embeddedProperty'
1044
        ];
1045
1046
        $metadata->addProperty('test.embeddedProperty', Type::getType('string'), $mapping);
1047
        */
1048
1049
        $metadata->wakeupReflection(new StaticReflectionService());
1050
1051
        self::assertEquals(
1052
            [
1053
                'test'                  => null,
1054
                'test.embeddedProperty' => null,
1055
            ],
1056
            $metadata->getReflectionProperties()
0 ignored issues
show
Bug introduced by
The method getReflectionProperties() does not exist on Doctrine\ORM\Mapping\ClassMetadata. Did you maybe mean getReflectionClass()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1056
            $metadata->/** @scrutinizer ignore-call */ 
1057
                       getReflectionProperties()

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1057
        );
1058
    }
1059
}
1060
1061
/**
1062
 * @ORM\MappedSuperclass
1063
 */
1064
class DDC2700MappedSuperClass
1065
{
1066
    /** @ORM\Column */
1067
    private $foo;
0 ignored issues
show
introduced by
The private property $foo is not used, and could be removed.
Loading history...
1068
}
1069
1070
class MyNamespacedNamingStrategy extends DefaultNamingStrategy
1071
{
1072
    /**
1073
     * {@inheritdoc}
1074
     */
1075
    public function classToTableName(string $className) : string
1076
    {
1077
        if (strpos($className, '\\') !== false) {
1078
            $className = str_replace('\\', '_', str_replace('Doctrine\Tests\Models\\', '', $className));
1079
        }
1080
1081
        return strtolower($className);
1082
    }
1083
}
1084
1085
class MyPrefixNamingStrategy extends DefaultNamingStrategy
1086
{
1087
    /**
1088
     * {@inheritdoc}
1089
     */
1090
    public function propertyToColumnName(string $propertyName, ?string $className = null) : string
1091
    {
1092
        return strtolower($this->classToTableName($className)) . '_' . $propertyName;
0 ignored issues
show
Bug introduced by
It seems like $className can also be of type null; however, parameter $className of Doctrine\ORM\Mapping\Fac...egy::classToTableName() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1092
        return strtolower($this->classToTableName(/** @scrutinizer ignore-type */ $className)) . '_' . $propertyName;
Loading history...
1093
    }
1094
}
1095