Completed
Pull Request — master (#8122)
by Gildas
64:47
created

testStringFieldMappings()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 7
nc 1
nop 1
dl 0
loc 12
rs 10
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\Platforms\AbstractPlatform;
8
use Doctrine\DBAL\Types\Type;
9
use Doctrine\ORM\Annotation as ORM;
10
use Doctrine\ORM\EntityManagerInterface;
11
use Doctrine\ORM\Events;
12
use Doctrine\ORM\Mapping;
13
use Doctrine\ORM\Mapping\ClassMetadata;
14
use Doctrine\ORM\Mapping\ClassMetadataFactory;
15
use Doctrine\ORM\Mapping\Factory\DefaultNamingStrategy;
16
use Doctrine\ORM\Mapping\Factory\UnderscoreNamingStrategy;
17
use Doctrine\ORM\Mapping\MappingException;
18
use Doctrine\ORM\Reflection\ReflectionService;
19
use Doctrine\ORM\Sequencing\Generator\Generator;
20
use Doctrine\ORM\Sequencing\Generator\SequenceGenerator;
21
use Doctrine\Tests\Models\Cache\City;
22
use Doctrine\Tests\Models\Company\CompanyContract;
23
use Doctrine\Tests\Models\Company\CompanyContractListener;
24
use Doctrine\Tests\Models\Company\CompanyFixContract;
25
use Doctrine\Tests\Models\Company\CompanyFlexContract;
26
use Doctrine\Tests\Models\Company\CompanyFlexUltraContract;
27
use Doctrine\Tests\Models\Company\CompanyFlexUltraContractListener;
28
use Doctrine\Tests\Models\DDC1476\DDC1476EntityWithDefaultFieldType;
29
use Doctrine\Tests\Models\DDC2825\ExplicitSchemaAndTable;
30
use Doctrine\Tests\Models\DDC2825\SchemaAndTableInTableName;
31
use Doctrine\Tests\Models\DDC3579\DDC3579Admin;
32
use Doctrine\Tests\Models\DDC5934\DDC5934Contract;
33
use Doctrine\Tests\Models\DDC869\DDC869ChequePayment;
34
use Doctrine\Tests\Models\DDC869\DDC869CreditCardPayment;
35
use Doctrine\Tests\Models\DDC869\DDC869PaymentRepository;
36
use Doctrine\Tests\Models\DDC889\DDC889Class;
37
use Doctrine\Tests\Models\DDC889\DDC889Entity;
38
use Doctrine\Tests\Models\DDC964\DDC964Admin;
39
use Doctrine\Tests\Models\DDC964\DDC964Guest;
40
use Doctrine\Tests\Models\Quote;
41
use Doctrine\Tests\OrmTestCase;
42
use const CASE_UPPER;
43
use function get_class;
44
use function iterator_to_array;
45
use function reset;
46
use function strpos;
47
48
abstract class AbstractMappingDriverTest extends OrmTestCase
49
{
50
    /** @var AbstractPlatform */
51
    protected $targetPlatform;
52
53
    /** @var Mapping\ClassMetadataBuildingContext */
54
    protected $metadataBuildingContext;
55
56
    protected function setUp() : void
57
    {
58
        parent::setUp();
59
60
        $this->targetPlatform = $this->createMock(AbstractPlatform::class);
61
62
        $this->targetPlatform
63
            ->expects($this->any())
64
            ->method('prefersSequences')
65
            ->will($this->returnValue(true));
66
67
        $this->targetPlatform
68
            ->expects($this->any())
69
            ->method('usesSequenceEmulatedIdentityColumns')
70
            ->will($this->returnValue(true));
71
72
        $this->targetPlatform
73
            ->expects($this->any())
74
            ->method('fixSchemaElementName')
75
            ->will($this->returnArgument(0));
76
77
        $this->metadataBuildingContext = new Mapping\ClassMetadataBuildingContext(
78
            $this->createMock(ClassMetadataFactory::class),
79
            $this->createMock(ReflectionService::class),
80
            $this->targetPlatform
81
        );
82
    }
83
84
    abstract protected function loadDriver();
85
86
    public function createClassMetadata($entityClassName)
87
    {
88
        $mappingDriver = $this->loadDriver();
89
90
        return $mappingDriver->loadMetadataForClass($entityClassName, null, $this->metadataBuildingContext);
91
    }
92
93
    protected function createClassMetadataFactory(?EntityManagerInterface $em = null) : ClassMetadataFactory
94
    {
95
        $driver  = $this->loadDriver();
96
        $em      = $em ?: $this->getTestEntityManager();
97
        $factory = new ClassMetadataFactory();
98
99
        $em->getConfiguration()->setMetadataDriverImpl($driver);
100
        $factory->setEntityManager($em);
101
102
        return $factory;
103
    }
104
105
    public function testEntityTableNameAndInheritance() : ClassMetadata
106
    {
107
        $class = $this->createClassMetadata(User::class);
108
109
        self::assertEquals('cms_users', $class->getTableName());
110
        self::assertEquals(Mapping\InheritanceType::NONE, $class->inheritanceType);
111
112
        return $class;
113
    }
114
115
    public function testEntityIndexes() : ClassMetadata
116
    {
117
        $class = $this->createClassMetadata('Doctrine\Tests\ORM\Mapping\User');
118
119
        self::assertCount(2, $class->table->getIndexes());
120
        self::assertEquals(
121
            [
122
                'name_idx' => [
123
                    'name'    => 'name_idx',
124
                    'columns' => ['name'],
125
                    'unique'  => false,
126
                    'options' => [],
127
                    'flags'   => [],
128
                ],
129
                0 => [
130
                    'name'    => null,
131
                    'columns' => ['user_email'],
132
                    'unique'  => false,
133
                    'options' => [],
134
                    'flags'   => [],
135
                ],
136
            ],
137
            $class->table->getIndexes()
138
        );
139
140
        return $class;
141
    }
142
143
    public function testEntityIndexFlagsAndPartialIndexes() : void
144
    {
145
        $class = $this->createClassMetadata(Comment::class);
146
147
        self::assertEquals(
148
            [
149
                0 => [
150
                    'name'    => null,
151
                    'columns' => ['content'],
152
                    'unique'  => false,
153
                    'flags'   => ['fulltext'],
154
                    'options' => ['where' => 'content IS NOT NULL'],
155
                ],
156
            ],
157
            $class->table->getIndexes()
158
        );
159
    }
160
161
    /**
162
     * @param ClassMetadata $class
163
     *
164
     * @depends testEntityTableNameAndInheritance
165
     */
166
    public function testEntityUniqueConstraints($class) : ClassMetadata
167
    {
168
        self::assertCount(1, $class->table->getUniqueConstraints());
169
        self::assertEquals(
170
            [
171
                'search_idx' => [
172
                    'name'    => 'search_idx',
173
                    'columns' => ['name', 'user_email'],
174
                    'options' => [],
175
                    'flags'   => [],
176
                ],
177
            ],
178
            $class->table->getUniqueConstraints()
179
        );
180
181
        return $class;
182
    }
183
184
    /**
185
     * @param ClassMetadata $class
186
     *
187
     * @depends testEntityTableNameAndInheritance
188
     */
189
    public function testEntityOptions($class) : ClassMetadata
190
    {
191
        self::assertCount(2, $class->table->getOptions());
192
        self::assertEquals(
193
            [
194
                'foo' => 'bar',
195
                'baz' => ['key' => 'val'],
196
            ],
197
            $class->table->getOptions()
198
        );
199
200
        return $class;
201
    }
202
203
    /**
204
     * @param ClassMetadata $class
205
     *
206
     * @depends testEntityOptions
207
     */
208
    public function testEntitySequence($class) : void
209
    {
210
        $valueGenerator = $class->getProperty('id')->getValueGenerator();
0 ignored issues
show
Bug introduced by
The method getValueGenerator() does not exist on Doctrine\ORM\Mapping\Property. Did you maybe mean getValue()? ( Ignorable by Annotation )

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

210
        $valueGenerator = $class->getProperty('id')->/** @scrutinizer ignore-call */ getValueGenerator();

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...
211
212
        self::assertEquals(Mapping\GeneratorType::SEQUENCE, $valueGenerator->getType(), 'Generator Type');
213
        self::assertInstanceOf(SequenceGenerator::class, $valueGenerator->getGenerator(), 'No Sequence Definition set on this driver.');
214
215
        /** @var SequenceGenerator $generator */
216
        $generator = $valueGenerator->getGenerator();
217
218
        self::assertEquals('tablename_seq', $generator->getSequenceName());
219
        self::assertEquals(100, $generator->getAllocationSize());
220
    }
221
222
    public function testEntityCustomGenerator() : void
223
    {
224
        $class          = $this->createClassMetadata(Animal::class);
225
        $valueGenerator = $class->getProperty('id')->getValueGenerator();
226
227
        self::assertEquals(Mapping\GeneratorType::CUSTOM, $valueGenerator->getType(), 'Generator Type');
228
        self::assertInstanceOf(CustomGenerator::class, $valueGenerator->getGenerator(), 'Generator Definition');
229
    }
230
231
    /**
232
     * @param ClassMetadata $class
233
     *
234
     * @depends testEntityTableNameAndInheritance
235
     */
236
    public function testProperties($class) : ClassMetadata
237
    {
238
        self::assertCount(7, $class->getPropertiesIterator());
239
240
        self::assertNotNull($class->getProperty('id'));
241
        self::assertNotNull($class->getProperty('name'));
242
        self::assertNotNull($class->getProperty('email'));
243
        self::assertNotNull($class->getProperty('version'));
244
        self::assertNotNull($class->getProperty('version'));
245
246
        return $class;
247
    }
248
249
    /**
250
     * @param ClassMetadata $class
251
     *
252
     * @depends testProperties
253
     */
254
    public function testVersionProperty($class) : void
255
    {
256
        self::assertTrue($class->isVersioned());
257
        self::assertNotNull($class->versionProperty);
258
259
        $versionPropertyName = $class->versionProperty->getName();
0 ignored issues
show
Bug introduced by
The method getName() does not exist on null. ( Ignorable by Annotation )

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

259
        /** @scrutinizer ignore-call */ 
260
        $versionPropertyName = $class->versionProperty->getName();

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...
260
261
        self::assertEquals('version', $versionPropertyName);
262
        self::assertNotNull($class->getProperty($versionPropertyName));
263
    }
264
265
    /**
266
     * @param ClassMetadata $class
267
     *
268
     * @depends testEntityTableNameAndInheritance
269
     */
270
    public function testFieldMappingsColumnNames($class) : ClassMetadata
271
    {
272
        self::assertNotNull($class->getProperty('id'));
273
        self::assertNotNull($class->getProperty('name'));
274
        self::assertNotNull($class->getProperty('email'));
275
276
        self::assertEquals('id', $class->getProperty('id')->getColumnName());
0 ignored issues
show
Bug introduced by
The method getColumnName() 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

276
        self::assertEquals('id', $class->getProperty('id')->/** @scrutinizer ignore-call */ getColumnName());
Loading history...
277
        self::assertEquals('name', $class->getProperty('name')->getColumnName());
278
        self::assertEquals('user_email', $class->getProperty('email')->getColumnName());
279
280
        return $class;
281
    }
282
283
    /**
284
     * @param ClassMetadata $class
285
     *
286
     * @depends testEntityTableNameAndInheritance
287
     */
288
    public function testStringFieldMappings($class) : ClassMetadata
289
    {
290
        self::assertNotNull($class->getProperty('name'));
291
292
        $property = $class->getProperty('name');
293
294
        self::assertEquals('string', $property->getTypeName());
0 ignored issues
show
Bug introduced by
The method getTypeName() 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

294
        self::assertEquals('string', $property->/** @scrutinizer ignore-call */ getTypeName());
Loading history...
295
        self::assertEquals(50, $property->getLength());
0 ignored issues
show
Bug introduced by
The method getLength() 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

295
        self::assertEquals(50, $property->/** @scrutinizer ignore-call */ getLength());
Loading history...
296
        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

296
        self::assertTrue($property->/** @scrutinizer ignore-call */ isNullable());
Loading history...
297
        self::assertTrue($property->isUnique());
0 ignored issues
show
Bug introduced by
The method isUnique() 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

297
        self::assertTrue($property->/** @scrutinizer ignore-call */ isUnique());
Loading history...
298
299
        return $class;
300
    }
301
302
    /**
303
     * @depends testEntityTableNameAndInheritance
304
     */
305
    public function testFieldOptions(ClassMetadata $class) : ClassMetadata
306
    {
307
        self::assertNotNull($class->getProperty('name'));
308
309
        $property = $class->getProperty('name');
310
        $expected = ['foo' => 'bar', 'baz' => ['key' => 'val'], 'fixed' => false];
311
312
        self::assertEquals($expected, $property->getOptions());
0 ignored issues
show
Bug introduced by
The method getOptions() 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

312
        self::assertEquals($expected, $property->/** @scrutinizer ignore-call */ getOptions());
Loading history...
313
314
        return $class;
315
    }
316
317
    /**
318
     * @param ClassMetadata $class
319
     *
320
     * @depends testEntityTableNameAndInheritance
321
     */
322
    public function testIdFieldOptions($class) : ClassMetadata
323
    {
324
        self::assertNotNull($class->getProperty('id'));
325
326
        $property = $class->getProperty('id');
327
        $expected = ['foo' => 'bar', 'unsigned' => false];
328
329
        self::assertEquals($expected, $property->getOptions());
330
331
        return $class;
332
    }
333
334
    /**
335
     * @param ClassMetadata $class
336
     *
337
     * @depends testProperties
338
     */
339
    public function testIdentifier($class) : ClassMetadata
340
    {
341
        self::assertNotNull($class->getProperty('id'));
342
343
        $property = $class->getProperty('id');
344
345
        self::assertEquals('integer', $property->getTypeName());
346
        self::assertEquals(['id'], $class->identifier);
347
        self::assertEquals(
348
            Mapping\GeneratorType::SEQUENCE,
349
            $property->getValueGenerator()->getType(),
350
            'ID-Generator is not GeneratorType::AUTO'
351
        );
352
353
        return $class;
354
    }
355
356
    /**
357
     * @group #6129
358
     */
359
    public function testBooleanValuesForOptionIsSetCorrectly() : ClassMetadata
360
    {
361
        $class = $this->createClassMetadata(User::class);
362
363
        $idOptions   = $class->getProperty('id')->getOptions();
364
        $nameOptions = $class->getProperty('name')->getOptions();
365
366
        self::assertInternalType('bool', $idOptions['unsigned']);
0 ignored issues
show
Deprecated Code introduced by
The function PHPUnit\Framework\Assert::assertInternalType() has been deprecated: https://github.com/sebastianbergmann/phpunit/issues/3369 ( Ignorable by Annotation )

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

366
        /** @scrutinizer ignore-deprecated */ self::assertInternalType('bool', $idOptions['unsigned']);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
367
        self::assertFalse($idOptions['unsigned']);
368
        self::assertInternalType('bool', $nameOptions['fixed']);
0 ignored issues
show
Deprecated Code introduced by
The function PHPUnit\Framework\Assert::assertInternalType() has been deprecated: https://github.com/sebastianbergmann/phpunit/issues/3369 ( Ignorable by Annotation )

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

368
        /** @scrutinizer ignore-deprecated */ self::assertInternalType('bool', $nameOptions['fixed']);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
369
        self::assertFalse($nameOptions['fixed']);
370
371
        return $class;
372
    }
373
374
    public function testOneToOneUnidirectional() : void
375
    {
376
        // One to One owning
377
        $fullAddressClass = $this->createClassMetadata(Quote\FullAddress::class);
378
        $cityAssociation  = $fullAddressClass->getProperty('city');
379
380
        self::assertInstanceOf(Mapping\OneToOneAssociationMetadata::class, $cityAssociation);
381
        self::assertTrue($cityAssociation->isOwningSide());
382
    }
383
384
    public function testOneToOneBidirectional() : void
385
    {
386
        // One to One owning / One To One inverse
387
        $addressClass    = $this->createClassMetadata(Quote\Address::class);
388
        $userAssociation = $addressClass->getProperty('user');
389
390
        self::assertInstanceOf(Mapping\OneToOneAssociationMetadata::class, $userAssociation);
391
        self::assertTrue($userAssociation->isOwningSide());
392
393
        $userClass          = $this->createClassMetadata(Quote\User::class);
394
        $addressAssociation = $userClass->getProperty('address');
395
396
        self::assertInstanceOf(Mapping\OneToOneAssociationMetadata::class, $addressAssociation);
397
        self::assertFalse($addressAssociation->isOwningSide());
398
    }
399
400
    public function testManyToOneUnidirectional() : void
401
    {
402
        // Many to One owning
403
        $groupClass       = $this->createClassMetadata(Quote\Group::class);
404
        $groupAssociation = $groupClass->getProperty('parent');
405
406
        self::assertInstanceOf(Mapping\ManyToOneAssociationMetadata::class, $groupAssociation);
407
        self::assertTrue($groupAssociation->isOwningSide());
408
    }
409
410
    public function testManyToOneBidirectional() : void
411
    {
412
        // Many To One owning / One To Many inverse
413
        $phoneClass      = $this->createClassMetadata(Quote\Phone::class);
414
        $userAssociation = $phoneClass->getProperty('user');
415
416
        self::assertInstanceOf(Mapping\ManyToOneAssociationMetadata::class, $userAssociation);
417
        self::assertTrue($userAssociation->isOwningSide());
418
419
        $userClass        = $this->createClassMetadata(Quote\User::class);
420
        $phoneAssociation = $userClass->getProperty('phones');
421
422
        self::assertInstanceOf(Mapping\OneToManyAssociationMetadata::class, $phoneAssociation);
423
        self::assertFalse($phoneAssociation->isOwningSide());
424
    }
425
426
    public function testManyToManyBidirectional() : void
427
    {
428
        // Many to Many owning / Many to Many inverse
429
        $userClass        = $this->createClassMetadata(Quote\User::class);
430
        $groupAssociation = $userClass->getProperty('groups');
431
432
        self::assertInstanceOf(Mapping\ManyToManyAssociationMetadata::class, $groupAssociation);
433
        self::assertTrue($groupAssociation->isOwningSide());
434
435
        $groupClass      = $this->createClassMetadata(Quote\Group::class);
436
        $userAssociation = $groupClass->getProperty('users');
437
438
        self::assertInstanceOf(Mapping\ManyToManyAssociationMetadata::class, $userAssociation);
439
        self::assertFalse($userAssociation->isOwningSide());
440
    }
441
442
    /**
443
     * @param ClassMetadata $class
444
     *
445
     * @depends testProperties
446
     */
447
    public function testOwningOneToOneAssociation($class) : ClassMetadata
448
    {
449
        self::assertArrayHasKey('address', iterator_to_array($class->getPropertiesIterator()));
450
451
        $association = $class->getProperty('address');
452
453
        self::assertTrue($association->isOwningSide());
0 ignored issues
show
Bug introduced by
The method isOwningSide() 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

453
        self::assertTrue($association->/** @scrutinizer ignore-call */ isOwningSide());
Loading history...
454
        self::assertEquals('user', $association->getInversedBy());
0 ignored issues
show
Bug introduced by
The method getInversedBy() 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

454
        self::assertEquals('user', $association->/** @scrutinizer ignore-call */ getInversedBy());
Loading history...
455
        // Check cascading
456
        self::assertEquals(['remove'], $association->getCascade());
0 ignored issues
show
Bug introduced by
The method getCascade() 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

456
        self::assertEquals(['remove'], $association->/** @scrutinizer ignore-call */ getCascade());
Loading history...
457
458
        return $class;
459
    }
460
461
    /**
462
     * @param ClassMetadata $class
463
     *
464
     * @depends testOwningOneToOneAssociation
465
     */
466
    public function testInverseOneToManyAssociation($class) : ClassMetadata
467
    {
468
        self::assertArrayHasKey('phonenumbers', iterator_to_array($class->getPropertiesIterator()));
469
470
        $association = $class->getProperty('phonenumbers');
471
472
        self::assertFalse($association->isOwningSide());
473
        self::assertTrue($association->isOrphanRemoval());
0 ignored issues
show
Bug introduced by
The method isOrphanRemoval() 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

473
        self::assertTrue($association->/** @scrutinizer ignore-call */ isOrphanRemoval());
Loading history...
474
475
        // Check cascading
476
        self::assertEquals(['persist', 'remove'], $association->getCascade());
477
478
        // Test Order By
479
        self::assertEquals(['number' => 'ASC'], $association->getOrderBy());
0 ignored issues
show
Bug introduced by
The method getOrderBy() 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\ToManyAssociationMetadata. ( Ignorable by Annotation )

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

479
        self::assertEquals(['number' => 'ASC'], $association->/** @scrutinizer ignore-call */ getOrderBy());
Loading history...
480
481
        return $class;
482
    }
483
484
    /**
485
     * @param ClassMetadata $class
486
     *
487
     * @depends testInverseOneToManyAssociation
488
     */
489
    public function testManyToManyAssociationWithCascadeAll($class) : ClassMetadata
490
    {
491
        self::assertArrayHasKey('groups', iterator_to_array($class->getPropertiesIterator()));
492
493
        $association = $class->getProperty('groups');
494
495
        self::assertTrue($association->isOwningSide());
496
497
        // Make sure that cascade-all works as expected
498
        self::assertEquals(['remove', 'persist', 'refresh'], $association->getCascade());
499
500
        // Test Order By
501
        self::assertEquals([], $association->getOrderBy());
502
503
        return $class;
504
    }
505
506
    /**
507
     * @param ClassMetadata $class
508
     *
509
     * @depends testManyToManyAssociationWithCascadeAll
510
     */
511
    public function testLifecycleCallbacks($class) : ClassMetadata
512
    {
513
        self::assertCount(2, $class->lifecycleCallbacks);
514
        self::assertEquals($class->lifecycleCallbacks['prePersist'][0], 'doStuffOnPrePersist');
515
        self::assertEquals($class->lifecycleCallbacks['postPersist'][0], 'doStuffOnPostPersist');
516
517
        return $class;
518
    }
519
520
    /**
521
     * @param ClassMetadata $class
522
     *
523
     * @depends testManyToManyAssociationWithCascadeAll
524
     */
525
    public function testLifecycleCallbacksSupportMultipleMethodNames($class) : ClassMetadata
526
    {
527
        self::assertCount(2, $class->lifecycleCallbacks['prePersist']);
528
        self::assertEquals($class->lifecycleCallbacks['prePersist'][1], 'doOtherStuffOnPrePersistToo');
529
530
        return $class;
531
    }
532
533
    /**
534
     * @param ClassMetadata $class
535
     *
536
     * @depends testLifecycleCallbacksSupportMultipleMethodNames
537
     */
538
    public function testJoinColumnUniqueAndNullable($class) : ClassMetadata
539
    {
540
        // Non-Nullability of Join Column
541
        $association = $class->getProperty('groups');
542
        $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

542
        /** @scrutinizer ignore-call */ 
543
        $joinTable   = $association->getJoinTable();
Loading history...
543
        $joinColumns = $joinTable->getJoinColumns();
544
        $joinColumn  = reset($joinColumns);
545
546
        self::assertFalse($joinColumn->isNullable());
547
        self::assertFalse($joinColumn->isUnique());
548
549
        return $class;
550
    }
551
552
    /**
553
     * @param ClassMetadata $class
554
     *
555
     * @depends testJoinColumnUniqueAndNullable
556
     */
557
    public function testColumnDefinition($class) : ClassMetadata
558
    {
559
        self::assertNotNull($class->getProperty('email'));
560
561
        $property           = $class->getProperty('email');
562
        $association        = $class->getProperty('groups');
563
        $joinTable          = $association->getJoinTable();
564
        $inverseJoinColumns = $joinTable->getInverseJoinColumns();
565
        $inverseJoinColumn  = reset($inverseJoinColumns);
566
567
        self::assertEquals('CHAR(32) NOT NULL', $property->getColumnDefinition());
0 ignored issues
show
Bug introduced by
The method getColumnDefinition() 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

567
        self::assertEquals('CHAR(32) NOT NULL', $property->/** @scrutinizer ignore-call */ getColumnDefinition());
Loading history...
568
        self::assertEquals('INT NULL', $inverseJoinColumn->getColumnDefinition());
569
570
        return $class;
571
    }
572
573
    /**
574
     * @param ClassMetadata $class
575
     *
576
     * @depends testColumnDefinition
577
     */
578
    public function testJoinColumnOnDelete($class) : ClassMetadata
579
    {
580
        $association = $class->getProperty('address');
581
        $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

581
        /** @scrutinizer ignore-call */ 
582
        $joinColumns = $association->getJoinColumns();
Loading history...
582
        $joinColumn  = reset($joinColumns);
583
584
        self::assertEquals('CASCADE', $joinColumn->getOnDelete());
585
586
        return $class;
587
    }
588
589
    /**
590
     * @group DDC-514
591
     */
592
    public function testDiscriminatorColumnDefaults() : void
593
    {
594
        if (strpos(static::class, 'PHPMappingDriver') !== false) {
595
            $this->markTestSkipped('PHP Mapping Drivers have no defaults.');
596
        }
597
598
        $class = $this->createClassMetadata(Animal::class);
599
600
        self::assertNotNull($class->discriminatorColumn);
601
602
        $discrColumn = $class->discriminatorColumn;
603
604
        self::assertEquals('Animal', $discrColumn->getTableName());
605
        self::assertEquals('discr', $discrColumn->getColumnName());
606
        self::assertEquals('string', $discrColumn->getTypeName());
607
        self::assertEquals(32, $discrColumn->getLength());
608
        self::assertNull($discrColumn->getColumnDefinition());
609
    }
610
611
    /**
612
     * @group DDC-869
613
     */
614
    public function testMappedSuperclassWithRepository() : void
615
    {
616
        $em      = $this->getTestEntityManager();
617
        $factory = $this->createClassMetadataFactory($em);
618
        $class   = $factory->getMetadataFor(DDC869CreditCardPayment::class);
619
620
        self::assertNotNull($class->getProperty('id'));
621
        self::assertNotNull($class->getProperty('value'));
622
        self::assertNotNull($class->getProperty('creditCardNumber'));
623
        self::assertEquals($class->getCustomRepositoryClassName(), DDC869PaymentRepository::class);
624
        self::assertInstanceOf(DDC869PaymentRepository::class, $em->getRepository(DDC869CreditCardPayment::class));
625
        self::assertTrue($em->getRepository(DDC869ChequePayment::class)->isTrue());
626
627
        $class = $factory->getMetadataFor(DDC869ChequePayment::class);
628
629
        self::assertNotNull($class->getProperty('id'));
630
        self::assertNotNull($class->getProperty('value'));
631
        self::assertNotNull($class->getProperty('serialNumber'));
632
        self::assertEquals($class->getCustomRepositoryClassName(), DDC869PaymentRepository::class);
633
        self::assertInstanceOf(DDC869PaymentRepository::class, $em->getRepository(DDC869ChequePayment::class));
634
        self::assertTrue($em->getRepository(DDC869ChequePayment::class)->isTrue());
635
    }
636
637
    /**
638
     * @group DDC-1476
639
     */
640
    public function testDefaultFieldType() : void
641
    {
642
        $factory = $this->createClassMetadataFactory();
643
        $class   = $factory->getMetadataFor(DDC1476EntityWithDefaultFieldType::class);
644
645
        self::assertNotNull($class->getProperty('id'));
646
        self::assertNotNull($class->getProperty('name'));
647
648
        $idProperty   = $class->getProperty('id');
649
        $nameProperty = $class->getProperty('name');
650
651
        self::assertInstanceOf(Mapping\FieldMetadata::class, $idProperty);
652
        self::assertInstanceOf(Mapping\FieldMetadata::class, $nameProperty);
653
654
        self::assertEquals('string', $idProperty->getTypeName());
655
        self::assertEquals('string', $nameProperty->getTypeName());
656
657
        self::assertEquals('id', $idProperty->getName());
658
        self::assertEquals('name', $nameProperty->getName());
659
660
        self::assertEquals('id', $idProperty->getColumnName());
661
        self::assertEquals('name', $nameProperty->getColumnName());
662
663
        self::assertFalse($idProperty->hasValueGenerator());
0 ignored issues
show
Bug introduced by
The method hasValueGenerator() 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

663
        self::assertFalse($idProperty->/** @scrutinizer ignore-call */ hasValueGenerator());
Loading history...
664
    }
665
666
    /**
667
     * @group DDC-1170
668
     */
669
    public function testIdentifierColumnDefinition() : void
670
    {
671
        $class = $this->createClassMetadata(DDC1170Entity::class);
672
673
        self::assertNotNull($class->getProperty('id'));
674
        self::assertNotNull($class->getProperty('value'));
675
676
        self::assertEquals('INT unsigned NOT NULL', $class->getProperty('id')->getColumnDefinition());
677
        self::assertEquals('VARCHAR(255) NOT NULL', $class->getProperty('value')->getColumnDefinition());
678
    }
679
680
    /**
681
     * @group DDC-559
682
     */
683
    public function testNamingStrategy() : void
684
    {
685
        $em      = $this->getTestEntityManager();
686
        $factory = $this->createClassMetadataFactory($em);
687
688
        self::assertInstanceOf(DefaultNamingStrategy::class, $em->getConfiguration()->getNamingStrategy());
689
        $em->getConfiguration()->setNamingStrategy(new UnderscoreNamingStrategy(CASE_UPPER));
690
        self::assertInstanceOf(UnderscoreNamingStrategy::class, $em->getConfiguration()->getNamingStrategy());
691
692
        $class        = $factory->getMetadataFor(DDC1476EntityWithDefaultFieldType::class);
693
        $idProperty   = $class->getProperty('id');
694
        $nameProperty = $class->getProperty('name');
695
696
        self::assertEquals('ID', $idProperty->getColumnName());
697
        self::assertEquals('NAME', $nameProperty->getColumnName());
698
        self::assertEquals('DDC1476ENTITY_WITH_DEFAULT_FIELD_TYPE', $class->table->getName());
699
    }
700
701
    /**
702
     * @group DDC-807
703
     * @group DDC-553
704
     */
705
    public function testDiscriminatorColumnDefinition() : void
706
    {
707
        $class = $this->createClassMetadata(DDC807Entity::class);
708
709
        self::assertNotNull($class->discriminatorColumn);
710
711
        $discrColumn = $class->discriminatorColumn;
712
713
        self::assertEquals('dtype', $discrColumn->getColumnName());
714
        self::assertEquals("ENUM('ONE','TWO')", $discrColumn->getColumnDefinition());
715
    }
716
717
    /**
718
     * @group DDC-889
719
     */
720
    public function testInvalidEntityOrMappedSuperClassShouldMentionParentClasses() : void
721
    {
722
        $this->expectException(MappingException::class);
723
        $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.');
724
725
        $this->createClassMetadata(DDC889Class::class);
726
    }
727
728
    /**
729
     * @group DDC-889
730
     */
731
    public function testIdentifierRequiredShouldMentionParentClasses() : void
732
    {
733
        $factory = $this->createClassMetadataFactory();
734
735
        $this->expectException(MappingException::class);
736
        $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.');
737
738
        $factory->getMetadataFor(DDC889Entity::class);
739
    }
740
741
    /**
742
     * @group DDC-964
743
     */
744
    public function testAssociationOverridesMapping() : void
745
    {
746
        $factory       = $this->createClassMetadataFactory();
747
        $adminMetadata = $factory->getMetadataFor(DDC964Admin::class);
748
        $guestMetadata = $factory->getMetadataFor(DDC964Guest::class);
749
750
        // assert groups association mappings
751
        self::assertArrayHasKey('groups', iterator_to_array($guestMetadata->getPropertiesIterator()));
752
        self::assertArrayHasKey('groups', iterator_to_array($adminMetadata->getPropertiesIterator()));
753
754
        $guestGroups = $guestMetadata->getProperty('groups');
755
        $adminGroups = $adminMetadata->getProperty('groups');
756
757
        // assert not override attributes
758
        self::assertEquals($guestGroups->getName(), $adminGroups->getName());
759
        self::assertEquals(get_class($guestGroups), get_class($adminGroups));
760
        self::assertEquals($guestGroups->getMappedBy(), $adminGroups->getMappedBy());
0 ignored issues
show
Bug introduced by
The method getMappedBy() 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

760
        self::assertEquals($guestGroups->/** @scrutinizer ignore-call */ getMappedBy(), $adminGroups->getMappedBy());
Loading history...
761
        self::assertEquals($guestGroups->getInversedBy(), $adminGroups->getInversedBy());
762
        self::assertEquals($guestGroups->isOwningSide(), $adminGroups->isOwningSide());
763
        self::assertEquals($guestGroups->getFetchMode(), $adminGroups->getFetchMode());
0 ignored issues
show
Bug introduced by
The method getFetchMode() 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

763
        self::assertEquals($guestGroups->/** @scrutinizer ignore-call */ getFetchMode(), $adminGroups->getFetchMode());
Loading history...
764
        self::assertEquals($guestGroups->getCascade(), $adminGroups->getCascade());
765
766
        // assert not override attributes
767
        $guestGroupsJoinTable          = $guestGroups->getJoinTable();
768
        $guestGroupsJoinColumns        = $guestGroupsJoinTable->getJoinColumns();
769
        $guestGroupsJoinColumn         = reset($guestGroupsJoinColumns);
770
        $guestGroupsInverseJoinColumns = $guestGroupsJoinTable->getInverseJoinColumns();
771
        $guestGroupsInverseJoinColumn  = reset($guestGroupsInverseJoinColumns);
772
773
        self::assertEquals('ddc964_users_groups', $guestGroupsJoinTable->getName());
774
        self::assertEquals('user_id', $guestGroupsJoinColumn->getColumnName());
775
        self::assertEquals('group_id', $guestGroupsInverseJoinColumn->getColumnName());
776
777
        $adminGroupsJoinTable          = $adminGroups->getJoinTable();
778
        $adminGroupsJoinColumns        = $adminGroupsJoinTable->getJoinColumns();
779
        $adminGroupsJoinColumn         = reset($adminGroupsJoinColumns);
780
        $adminGroupsInverseJoinColumns = $adminGroupsJoinTable->getInverseJoinColumns();
781
        $adminGroupsInverseJoinColumn  = reset($adminGroupsInverseJoinColumns);
782
783
        self::assertEquals('ddc964_users_admingroups', $adminGroupsJoinTable->getName());
784
        self::assertEquals('adminuser_id', $adminGroupsJoinColumn->getColumnName());
785
        self::assertEquals('admingroup_id', $adminGroupsInverseJoinColumn->getColumnName());
786
787
        // assert address association mappings
788
        self::assertArrayHasKey('address', iterator_to_array($guestMetadata->getPropertiesIterator()));
789
        self::assertArrayHasKey('address', iterator_to_array($adminMetadata->getPropertiesIterator()));
790
791
        $guestAddress = $guestMetadata->getProperty('address');
792
        $adminAddress = $adminMetadata->getProperty('address');
793
794
        // assert not override attributes
795
        self::assertEquals($guestAddress->getName(), $adminAddress->getName());
796
        self::assertEquals(get_class($guestAddress), get_class($adminAddress));
797
        self::assertEquals($guestAddress->getMappedBy(), $adminAddress->getMappedBy());
798
        self::assertEquals($guestAddress->getInversedBy(), $adminAddress->getInversedBy());
799
        self::assertEquals($guestAddress->isOwningSide(), $adminAddress->isOwningSide());
800
        self::assertEquals($guestAddress->getFetchMode(), $adminAddress->getFetchMode());
801
        self::assertEquals($guestAddress->getCascade(), $adminAddress->getCascade());
802
803
        // assert override
804
        $guestAddressJoinColumns = $guestAddress->getJoinColumns();
805
        $guestAddressJoinColumn  = reset($guestAddressJoinColumns);
806
807
        self::assertEquals('address_id', $guestAddressJoinColumn->getColumnName());
808
809
        $adminAddressJoinColumns = $adminAddress->getJoinColumns();
810
        $adminAddressJoinColumn  = reset($adminAddressJoinColumns);
811
812
        self::assertEquals('adminaddress_id', $adminAddressJoinColumn->getColumnName());
813
    }
814
815
    /**
816
     * @group DDC-3579
817
     */
818
    public function testInversedByOverrideMapping() : void
819
    {
820
        $factory       = $this->createClassMetadataFactory();
821
        $adminMetadata = $factory->getMetadataFor(DDC3579Admin::class);
822
823
        // assert groups association mappings
824
        self::assertArrayHasKey('groups', iterator_to_array($adminMetadata->getPropertiesIterator()));
825
826
        $adminGroups = $adminMetadata->getProperty('groups');
827
828
        // assert override
829
        self::assertEquals('admins', $adminGroups->getInversedBy());
830
    }
831
832
    /**
833
     * @group DDC-5934
834
     */
835
    public function testFetchOverrideMapping() : void
836
    {
837
        // check override metadata
838
        $contractMetadata = $this->createClassMetadataFactory()->getMetadataFor(DDC5934Contract::class);
839
840
        self::assertArrayHasKey('members', iterator_to_array($contractMetadata->getPropertiesIterator()));
841
842
        $contractMembers = $contractMetadata->getProperty('members');
843
844
        self::assertSame(Mapping\FetchMode::EXTRA_LAZY, $contractMembers->getFetchMode());
845
    }
846
847
    /**
848
     * @group DDC-964
849
     */
850
    public function testAttributeOverridesMapping() : void
851
    {
852
        $factory       = $this->createClassMetadataFactory();
853
        $adminMetadata = $factory->getMetadataFor(DDC964Admin::class);
854
855
        self::assertEquals(
856
            [
857
                'user_id' => 'id',
858
                'user_name' => 'name',
859
                'adminaddress_id' => 'address',
860
            ],
861
            $adminMetadata->fieldNames
862
        );
863
864
        self::assertNotNull($adminMetadata->getProperty('id'));
865
866
        $idProperty = $adminMetadata->getProperty('id');
867
868
        self::assertTrue($idProperty->isPrimaryKey());
869
        self::assertEquals('id', $idProperty->getName());
870
        self::assertEquals('user_id', $idProperty->getColumnName());
871
872
        self::assertNotNull($adminMetadata->getProperty('name'));
873
874
        $nameProperty = $adminMetadata->getProperty('name');
875
876
        self::assertEquals('name', $nameProperty->getName());
877
        self::assertEquals('user_name', $nameProperty->getColumnName());
878
        self::assertEquals(250, $nameProperty->getLength());
879
        self::assertTrue($nameProperty->isNullable());
880
        self::assertFalse($nameProperty->isUnique());
881
882
        $guestMetadata = $factory->getMetadataFor(DDC964Guest::class);
883
884
        self::assertEquals(
885
            [
886
                'guest_id' => 'id',
887
                'guest_name' => 'name',
888
                'address_id' => 'address',
889
            ],
890
            $guestMetadata->fieldNames
891
        );
892
893
        self::assertNotNull($guestMetadata->getProperty('id'));
894
895
        $idProperty = $guestMetadata->getProperty('id');
896
897
        self::assertTrue($idProperty->isPrimaryKey());
898
        self::assertEquals('id', $idProperty->getName());
899
        self::assertEquals('guest_id', $idProperty->getColumnName());
900
901
        self::assertNotNull($guestMetadata->getProperty('name'));
902
903
        $nameProperty = $guestMetadata->getProperty('name');
904
905
        self::assertEquals('name', $nameProperty->getName());
906
        self::assertEquals('guest_name', $nameProperty->getColumnName());
907
        self::assertEquals(240, $nameProperty->getLength());
908
        self::assertFalse($nameProperty->isNullable());
909
        self::assertTrue($nameProperty->isUnique());
910
    }
911
912
    /**
913
     * @group DDC-1955
914
     */
915
    public function testEntityListeners() : void
916
    {
917
        $factory    = $this->createClassMetadataFactory();
918
        $superClass = $factory->getMetadataFor(CompanyContract::class);
919
        $flexClass  = $factory->getMetadataFor(CompanyFixContract::class);
920
        $fixClass   = $factory->getMetadataFor(CompanyFlexContract::class);
921
922
        self::assertArrayHasKey(Events::prePersist, $superClass->entityListeners);
923
        self::assertArrayHasKey(Events::postPersist, $superClass->entityListeners);
924
925
        self::assertCount(1, $superClass->entityListeners[Events::prePersist]);
926
        self::assertCount(1, $superClass->entityListeners[Events::postPersist]);
927
928
        $postPersist = $superClass->entityListeners[Events::postPersist][0];
929
        $prePersist  = $superClass->entityListeners[Events::prePersist][0];
930
931
        self::assertEquals(CompanyContractListener::class, $postPersist['class']);
932
        self::assertEquals(CompanyContractListener::class, $prePersist['class']);
933
        self::assertEquals('postPersistHandler', $postPersist['method']);
934
        self::assertEquals('prePersistHandler', $prePersist['method']);
935
936
        //Inherited listeners
937
        self::assertEquals($fixClass->entityListeners, $superClass->entityListeners);
938
        self::assertEquals($flexClass->entityListeners, $superClass->entityListeners);
939
    }
940
941
    /**
942
     * @group DDC-1955
943
     */
944
    public function testEntityListenersOverride() : void
945
    {
946
        $factory    = $this->createClassMetadataFactory();
947
        $ultraClass = $factory->getMetadataFor(CompanyFlexUltraContract::class);
948
949
        //overridden listeners
950
        self::assertArrayHasKey(Events::postPersist, $ultraClass->entityListeners);
951
        self::assertArrayHasKey(Events::prePersist, $ultraClass->entityListeners);
952
953
        self::assertCount(1, $ultraClass->entityListeners[Events::postPersist]);
954
        self::assertCount(3, $ultraClass->entityListeners[Events::prePersist]);
955
956
        $postPersist = $ultraClass->entityListeners[Events::postPersist][0];
957
        $prePersist  = $ultraClass->entityListeners[Events::prePersist][0];
958
959
        self::assertEquals(CompanyContractListener::class, $postPersist['class']);
960
        self::assertEquals(CompanyContractListener::class, $prePersist['class']);
961
        self::assertEquals('postPersistHandler', $postPersist['method']);
962
        self::assertEquals('prePersistHandler', $prePersist['method']);
963
964
        $prePersist = $ultraClass->entityListeners[Events::prePersist][1];
965
        self::assertEquals(CompanyFlexUltraContractListener::class, $prePersist['class']);
966
        self::assertEquals('prePersistHandler1', $prePersist['method']);
967
968
        $prePersist = $ultraClass->entityListeners[Events::prePersist][2];
969
        self::assertEquals(CompanyFlexUltraContractListener::class, $prePersist['class']);
970
        self::assertEquals('prePersistHandler2', $prePersist['method']);
971
    }
972
973
    /**
974
     * @group DDC-2183
975
     */
976
    public function testSecondLevelCacheMapping() : void
977
    {
978
        $factory = $this->createClassMetadataFactory();
979
        $class   = $factory->getMetadataFor(City::class);
980
981
        self::assertNotNull($class->getCache());
982
        self::assertEquals(Mapping\CacheUsage::READ_ONLY, $class->getCache()->getUsage());
983
        self::assertEquals('doctrine_tests_models_cache_city', $class->getCache()->getRegion());
984
985
        self::assertArrayHasKey('state', iterator_to_array($class->getPropertiesIterator()));
986
987
        $stateAssociation = $class->getProperty('state');
988
989
        self::assertNotNull($stateAssociation->getCache());
0 ignored issues
show
Bug introduced by
The method getCache() 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 or Doctrine\ORM\Mapping\EmbeddedClassMetadata. ( Ignorable by Annotation )

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

989
        self::assertNotNull($stateAssociation->/** @scrutinizer ignore-call */ getCache());
Loading history...
990
        self::assertEquals(Mapping\CacheUsage::READ_ONLY, $stateAssociation->getCache()->getUsage());
991
        self::assertEquals('doctrine_tests_models_cache_city__state', $stateAssociation->getCache()->getRegion());
992
993
        self::assertArrayHasKey('attractions', iterator_to_array($class->getPropertiesIterator()));
994
995
        $attractionsAssociation = $class->getProperty('attractions');
996
997
        self::assertNotNull($attractionsAssociation->getCache());
998
        self::assertEquals(Mapping\CacheUsage::READ_ONLY, $attractionsAssociation->getCache()->getUsage());
999
        self::assertEquals('doctrine_tests_models_cache_city__attractions', $attractionsAssociation->getCache()->getRegion());
1000
    }
1001
1002
    /**
1003
     * @group DDC-2825
1004
     * @group 881
1005
     */
1006
    public function testSchemaDefinitionViaExplicitTableSchemaAnnotationProperty() : void
1007
    {
1008
        $factory  = $this->createClassMetadataFactory();
1009
        $metadata = $factory->getMetadataFor(ExplicitSchemaAndTable::class);
1010
1011
        self::assertSame('explicit_schema', $metadata->getSchemaName());
1012
        self::assertSame('explicit_table', $metadata->getTableName());
1013
    }
1014
1015
    /**
1016
     * @group DDC-2825
1017
     * @group 881
1018
     */
1019
    public function testSchemaDefinitionViaSchemaDefinedInTableNameInTableAnnotationProperty() : void
1020
    {
1021
        $factory  = $this->createClassMetadataFactory();
1022
        $metadata = $factory->getMetadataFor(SchemaAndTableInTableName::class);
1023
1024
        self::assertSame('implicit_schema', $metadata->getSchemaName());
1025
        self::assertSame('implicit_table', $metadata->getTableName());
1026
    }
1027
1028
    /**
1029
     * @group DDC-514
1030
     * @group DDC-1015
1031
     */
1032
    public function testDiscriminatorColumnDefaultLength() : void
1033
    {
1034
        if (strpos(static::class, 'PHPMappingDriver') !== false) {
1035
            $this->markTestSkipped('PHP Mapping Drivers have no defaults.');
1036
        }
1037
1038
        $class = $this->createClassMetadata(SingleTableEntityNoDiscriminatorColumnMapping::class);
1039
1040
        self::assertEquals(255, $class->discriminatorColumn->getLength());
1041
1042
        $class = $this->createClassMetadata(SingleTableEntityIncompleteDiscriminatorColumnMapping::class);
1043
1044
        self::assertEquals(255, $class->discriminatorColumn->getLength());
1045
    }
1046
1047
    /**
1048
     * @group DDC-514
1049
     * @group DDC-1015
1050
     */
1051
    public function testDiscriminatorColumnDefaultType() : void
1052
    {
1053
        if (strpos(static::class, 'PHPMappingDriver') !== false) {
1054
            $this->markTestSkipped('PHP Mapping Drivers have no defaults.');
1055
        }
1056
1057
        $class = $this->createClassMetadata(SingleTableEntityNoDiscriminatorColumnMapping::class);
1058
1059
        self::assertEquals('string', $class->discriminatorColumn->getTypeName());
1060
1061
        $class = $this->createClassMetadata(SingleTableEntityIncompleteDiscriminatorColumnMapping::class);
1062
1063
        self::assertEquals('string', $class->discriminatorColumn->getTypeName());
1064
    }
1065
1066
    /**
1067
     * @group DDC-514
1068
     * @group DDC-1015
1069
     */
1070
    public function testDiscriminatorColumnDefaultName() : void
1071
    {
1072
        if (strpos(static::class, 'PHPMappingDriver') !== false) {
1073
            $this->markTestSkipped('PHP Mapping Drivers have no defaults.');
1074
        }
1075
1076
        $class = $this->createClassMetadata(SingleTableEntityNoDiscriminatorColumnMapping::class);
1077
1078
        self::assertEquals('dtype', $class->discriminatorColumn->getColumnName());
1079
1080
        $class = $this->createClassMetadata(SingleTableEntityIncompleteDiscriminatorColumnMapping::class);
1081
1082
        self::assertEquals('dtype', $class->discriminatorColumn->getColumnName());
1083
    }
1084
1085
    /**
1086
     * @expectedException \Doctrine\ORM\Mapping\MappingException
1087
     * @expectedExceptionMessage Entity class 'Doctrine\Tests\ORM\Mapping\cube' used in the discriminator map of class 'Doctrine\Tests\ORM\Mapping\Shape' does not exist.
1088
     */
1089
    public function testInvalidSubClassCase()
1090
    {
1091
        $this->createClassMetadata(Shape::class);
1092
    }
1093
}
1094
1095
/**
1096
 * @ORM\Entity
1097
 * @ORM\HasLifecycleCallbacks
1098
 * @ORM\Table(
1099
 *  name="cms_users",
1100
 *  uniqueConstraints={@ORM\UniqueConstraint(name="search_idx", columns={"name", "user_email"})},
1101
 *  indexes={@ORM\Index(name="name_idx", columns={"name"}), @ORM\Index(columns={"user_email"})},
1102
 *  options={"foo": "bar", "baz": {"key": "val"}}
1103
 * )
1104
 */
1105
class User
1106
{
1107
    /**
1108
     * @ORM\Id
1109
     * @ORM\Column(type="integer", options={"foo": "bar", "unsigned": false})
1110
     * @ORM\GeneratedValue(strategy="AUTO")
1111
     * @ORM\SequenceGenerator(sequenceName="tablename_seq", allocationSize=100)
1112
     */
1113
    public $id;
1114
1115
    /** @ORM\Column(length=50, nullable=true, unique=true, options={"foo": "bar", "baz": {"key": "val"}, "fixed": false}) */
1116
    public $name;
1117
1118
    /** @ORM\Column(name="user_email", columnDefinition="CHAR(32) NOT NULL") */
1119
    public $email;
1120
1121
    /**
1122
     * @ORM\OneToOne(targetEntity=Address::class, cascade={"remove"}, inversedBy="user")
1123
     * @ORM\JoinColumn(onDelete="CASCADE")
1124
     */
1125
    public $address;
1126
1127
    /**
1128
     * @ORM\OneToMany(targetEntity=Phonenumber::class, mappedBy="user", cascade={"persist"}, orphanRemoval=true)
1129
     * @ORM\OrderBy({"number"="ASC"})
1130
     */
1131
    public $phonenumbers;
1132
1133
    /**
1134
     * @ORM\ManyToMany(targetEntity=Group::class, cascade={"all"})
1135
     * @ORM\JoinTable(name="cms_user_groups",
1136
     *    joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false, unique=false)},
1137
     *    inverseJoinColumns={@ORM\JoinColumn(name="group_id", referencedColumnName="id", columnDefinition="INT NULL")}
1138
     * )
1139
     */
1140
    public $groups;
1141
1142
    /**
1143
     * @ORM\Column(type="integer")
1144
     * @ORM\Version
1145
     */
1146
    public $version;
1147
1148
    /**
1149
     * @ORM\PrePersist
1150
     */
1151
    public function doStuffOnPrePersist()
1152
    {
1153
    }
1154
1155
    /**
1156
     * @ORM\PrePersist
1157
     */
1158
    public function doOtherStuffOnPrePersistToo()
1159
    {
1160
    }
1161
1162
    /**
1163
     * @ORM\PostPersist
1164
     */
1165
    public function doStuffOnPostPersist()
1166
    {
1167
    }
1168
1169
    public static function loadMetadata(ClassMetadata $metadata)
1170
    {
1171
        $tableMetadata = new Mapping\TableMetadata();
1172
1173
        $tableMetadata->setName('cms_users');
1174
        $tableMetadata->addIndex(
1175
            [
1176
                'name'    => 'name_idx',
1177
                'columns' => ['name'],
1178
                'unique'  => false,
1179
                'options' => [],
1180
                'flags'   => [],
1181
            ]
1182
        );
1183
1184
        $tableMetadata->addIndex(
1185
            [
1186
                'name'    => null,
1187
                'columns' => ['user_email'],
1188
                'unique'  => false,
1189
                'options' => [],
1190
                'flags'   => [],
1191
            ]
1192
        );
1193
1194
        $tableMetadata->addUniqueConstraint(
1195
            [
1196
                'name'    => 'search_idx',
1197
                'columns' => ['name', 'user_email'],
1198
                'options' => [],
1199
                'flags'   => [],
1200
            ]
1201
        );
1202
        $tableMetadata->addOption('foo', 'bar');
1203
        $tableMetadata->addOption('baz', ['key' => 'val']);
1204
1205
        $metadata->setTable($tableMetadata);
1206
        $metadata->setInheritanceType(Mapping\InheritanceType::NONE);
0 ignored issues
show
Bug introduced by
Doctrine\ORM\Mapping\InheritanceType::NONE 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

1206
        $metadata->setInheritanceType(/** @scrutinizer ignore-type */ Mapping\InheritanceType::NONE);
Loading history...
1207
        $metadata->setChangeTrackingPolicy(Mapping\ChangeTrackingPolicy::DEFERRED_IMPLICIT);
1208
1209
        $metadata->addLifecycleCallback('prePersist', 'doStuffOnPrePersist');
1210
        $metadata->addLifecycleCallback('prePersist', 'doOtherStuffOnPrePersistToo');
1211
        $metadata->addLifecycleCallback('postPersist', 'doStuffOnPostPersist');
1212
1213
        $metadata->setGeneratorDefinition(
0 ignored issues
show
Bug introduced by
The method setGeneratorDefinition() does not exist on Doctrine\ORM\Mapping\ClassMetadata. ( Ignorable by Annotation )

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

1213
        $metadata->/** @scrutinizer ignore-call */ 
1214
                   setGeneratorDefinition(

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...
1214
            [
1215
                'sequenceName'   => 'tablename_seq',
1216
                'allocationSize' => 100,
1217
            ]
1218
        );
1219
1220
        $fieldMetadata = new Mapping\FieldMetadata('id');
1221
        $fieldMetadata->setType(Type::getType('integer'));
1222
        $fieldMetadata->setPrimaryKey(true);
1223
        $fieldMetadata->setOptions(['foo' => 'bar', 'unsigned' => false]);
1224
1225
        $metadata->addProperty($fieldMetadata);
1226
1227
        $fieldMetadata = new Mapping\FieldMetadata('name');
1228
        $fieldMetadata->setType(Type::getType('string'));
1229
        $fieldMetadata->setLength(50);
1230
        $fieldMetadata->setNullable(true);
1231
        $fieldMetadata->setUnique(true);
1232
        $fieldMetadata->setOptions(
1233
            [
1234
                'foo' => 'bar',
1235
                'baz' => ['key' => 'val'],
1236
                'fixed' => false,
1237
            ]
1238
        );
1239
1240
        $metadata->addProperty($fieldMetadata);
1241
1242
        $fieldMetadata = new Mapping\FieldMetadata('email');
1243
1244
        $fieldMetadata->setType(Type::getType('string'));
1245
        $fieldMetadata->setColumnName('user_email');
1246
        $fieldMetadata->setColumnDefinition('CHAR(32) NOT NULL');
1247
1248
        $metadata->addProperty($fieldMetadata);
1249
1250
        $fieldMetadata = new Mapping\FieldMetadata('version');
1251
1252
        $fieldMetadata->setType(Type::getType('integer'));
1253
        $fieldMetadata->setVersioned(true);
1254
1255
        $metadata->addProperty($fieldMetadata);
1256
        $metadata->setIdGeneratorType(Mapping\GeneratorType::AUTO);
0 ignored issues
show
Bug introduced by
The method setIdGeneratorType() does not exist on Doctrine\ORM\Mapping\ClassMetadata. ( Ignorable by Annotation )

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

1256
        $metadata->/** @scrutinizer ignore-call */ 
1257
                   setIdGeneratorType(Mapping\GeneratorType::AUTO);

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...
1257
1258
        $joinColumns = [];
1259
1260
        $joinColumn = new Mapping\JoinColumnMetadata();
1261
1262
        $joinColumn->setColumnName('address_id');
1263
        $joinColumn->setReferencedColumnName('id');
1264
        $joinColumn->setOnDelete('CASCADE');
1265
1266
        $joinColumns[] = $joinColumn;
1267
1268
        $association = new Mapping\OneToOneAssociationMetadata('address');
1269
1270
        $association->setJoinColumns($joinColumns);
1271
        $association->setTargetEntity(Address::class);
1272
        $association->setInversedBy('user');
1273
        $association->setCascade(['remove']);
1274
        $association->setOrphanRemoval(false);
1275
1276
        $metadata->addProperty($association);
1277
1278
        $association = new Mapping\OneToManyAssociationMetadata('phonenumbers');
1279
1280
        $association->setTargetEntity(Phonenumber::class);
1281
        $association->setMappedBy('user');
1282
        $association->setCascade(['persist']);
1283
        $association->setOrderBy(['number' => 'ASC']);
1284
        $association->setOrphanRemoval(true);
1285
1286
        $metadata->addProperty($association);
1287
1288
        $joinTable = new Mapping\JoinTableMetadata();
1289
        $joinTable->setName('cms_users_groups');
1290
1291
        $joinColumn = new Mapping\JoinColumnMetadata();
1292
1293
        $joinColumn->setColumnName('user_id');
1294
        $joinColumn->setReferencedColumnName('id');
1295
        $joinColumn->setNullable(false);
1296
        $joinColumn->setUnique(false);
1297
1298
        $joinTable->addJoinColumn($joinColumn);
1299
1300
        $joinColumn = new Mapping\JoinColumnMetadata();
1301
1302
        $joinColumn->setColumnName('group_id');
1303
        $joinColumn->setReferencedColumnName('id');
1304
        $joinColumn->setColumnDefinition('INT NULL');
1305
1306
        $joinTable->addInverseJoinColumn($joinColumn);
1307
1308
        $association = new Mapping\ManyToManyAssociationMetadata('groups');
1309
1310
        $association->setJoinTable($joinTable);
1311
        $association->setTargetEntity(Group::class);
1312
        $association->setCascade(['remove', 'persist', 'refresh']);
1313
1314
        $metadata->addProperty($association);
1315
    }
1316
}
1317
1318
class CustomGenerator implements Generator
1319
{
1320
    public function generate(EntityManagerInterface $em, ?object $entity)
1321
    {
1322
        // TODO: Implement generate() method.
1323
    }
1324
1325
    public function isPostInsertGenerator() : bool
1326
    {
1327
        return false;
1328
    }
1329
}
1330
1331
/**
1332
 * @ORM\Entity
1333
 * @ORM\InheritanceType("SINGLE_TABLE")
1334
 * @ORM\DiscriminatorMap({"cat" = Cat::class, "dog" = Dog::class})
1335
 * @ORM\DiscriminatorColumn(name="discr", length=32, type="string")
1336
 */
1337
abstract class Animal
1338
{
1339
    /**
1340
     * @ORM\Id @ORM\Column(type="string") @ORM\GeneratedValue(strategy="CUSTOM")
1341
     * @ORM\CustomIdGenerator(class=CustomGenerator::class)
1342
     */
1343
    public $id;
1344
}
1345
1346
/** @ORM\Entity */
1347
class Cat extends Animal
1348
{
1349
}
1350
1351
/** @ORM\Entity */
1352
class Dog extends Animal
1353
{
1354
}
1355
1356
/**
1357
 * @ORM\Entity
1358
 * @ORM\InheritanceType("SINGLE_TABLE")
1359
 * @ORM\DiscriminatorMap({"cube" = cube::class})
1360
 * @ORM\DiscriminatorColumn(name="discr", length=32, type="string")
1361
 */
1362
abstract class Shape
1363
{
1364
    /** @ORM\Id @ORM\Column(type="string") @ORM\GeneratedValue(strategy="AUTO") */
1365
    public $id;
1366
}
1367
1368
/** @ORM\Entity */
1369
class Cube extends Shape
1370
{
1371
}
1372
1373
/**
1374
 * @ORM\Entity
1375
 */
1376
class DDC1170Entity
1377
{
1378
    /**
1379
     * @param string $value
1380
     */
1381
    public function __construct($value = null)
1382
    {
1383
        $this->value = $value;
1384
    }
1385
1386
    /**
1387
     * @ORM\Id
1388
     * @ORM\GeneratedValue(strategy="NONE")
1389
     * @ORM\Column(type="integer", columnDefinition = "INT unsigned NOT NULL")
1390
     */
1391
    private $id;
1392
1393
    /** @ORM\Column(columnDefinition = "VARCHAR(255) NOT NULL") */
1394
    private $value;
1395
1396
    /**
1397
     * @return int
1398
     */
1399
    public function getId()
1400
    {
1401
        return $this->id;
1402
    }
1403
1404
    /**
1405
     * @return string
1406
     */
1407
    public function getValue()
1408
    {
1409
        return $this->value;
1410
    }
1411
}
1412
1413
/**
1414
 * @ORM\Entity
1415
 * @ORM\InheritanceType("SINGLE_TABLE")
1416
 * @ORM\DiscriminatorMap({"ONE" = DDC807SubClasse1::class, "TWO" = DDC807SubClasse2::class})
1417
 * @ORM\DiscriminatorColumn(name = "dtype", columnDefinition="ENUM('ONE','TWO')")
1418
 */
1419
class DDC807Entity
1420
{
1421
    /**
1422
     * @ORM\Id
1423
     * @ORM\Column(type="integer")
1424
     * @ORM\GeneratedValue(strategy="NONE")
1425
     */
1426
    public $id;
1427
}
1428
1429
class DDC807SubClasse1
1430
{
1431
}
1432
class DDC807SubClasse2
1433
{
1434
}
1435
1436
class Address
1437
{
1438
}
1439
class Phonenumber
1440
{
1441
}
1442
class Group
1443
{
1444
}
1445
1446
/**
1447
 * @ORM\Entity
1448
 * @ORM\Table(indexes={@ORM\Index(columns={"content"}, flags={"fulltext"}, options={"where": "content IS NOT NULL"})})
1449
 */
1450
class Comment
1451
{
1452
    /** @ORM\Column(type="text") */
1453
    private $content;
0 ignored issues
show
introduced by
The private property $content is not used, and could be removed.
Loading history...
1454
}
1455
1456
/**
1457
 * @ORM\Entity
1458
 * @ORM\InheritanceType("SINGLE_TABLE")
1459
 * @ORM\DiscriminatorMap({
1460
 *     "ONE" = Doctrine\Tests\ORM\Mapping\SingleTableEntityNoDiscriminatorColumnMappingSub1::class,
1461
 *     "TWO" = Doctrine\Tests\ORM\Mapping\SingleTableEntityNoDiscriminatorColumnMappingSub2::class
1462
 * })
1463
 */
1464
class SingleTableEntityNoDiscriminatorColumnMapping
1465
{
1466
    /**
1467
     * @ORM\Id
1468
     * @ORM\Column(type="integer")
1469
     * @ORM\GeneratedValue(strategy="NONE")
1470
     */
1471
    public $id;
1472
}
1473
1474
/**
1475
 * @ORM\Entity
1476
 */
1477
class SingleTableEntityNoDiscriminatorColumnMappingSub1 extends SingleTableEntityNoDiscriminatorColumnMapping
1478
{
1479
}
1480
1481
/**
1482
 * @ORM\Entity
1483
 */
1484
class SingleTableEntityNoDiscriminatorColumnMappingSub2 extends SingleTableEntityNoDiscriminatorColumnMapping
1485
{
1486
}
1487
1488
/**
1489
 * @ORM\Entity
1490
 * @ORM\InheritanceType("SINGLE_TABLE")
1491
 * @ORM\DiscriminatorMap({
1492
 *     "ONE" = Doctrine\Tests\ORM\Mapping\SingleTableEntityIncompleteDiscriminatorColumnMappingSub1::class,
1493
 *     "TWO" = Doctrine\Tests\ORM\Mapping\SingleTableEntityIncompleteDiscriminatorColumnMappingSub2::class
1494
 * })
1495
 * @ORM\DiscriminatorColumn(name="dtype")
1496
 */
1497
class SingleTableEntityIncompleteDiscriminatorColumnMapping
1498
{
1499
    /**
1500
     * @ORM\Id
1501
     * @ORM\Column(type="integer")
1502
     * @ORM\GeneratedValue(strategy="NONE")
1503
     */
1504
    public $id;
1505
}
1506
1507
class SingleTableEntityIncompleteDiscriminatorColumnMappingSub1 extends SingleTableEntityIncompleteDiscriminatorColumnMapping
1508
{
1509
}
1510
1511
class SingleTableEntityIncompleteDiscriminatorColumnMappingSub2 extends SingleTableEntityIncompleteDiscriminatorColumnMapping
1512
{
1513
}
1514