Test Setup Failed
Push — develop ( 082d66...6f26e1 )
by Guilherme
63:04
created

testExistanceOfSqlResultSetMapping()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 9

Duplication

Lines 19
Ratio 100 %

Importance

Changes 0
Metric Value
dl 19
loc 19
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 9
nc 1
nop 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 35 and the first side effect is on line 33.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Tests\ORM\Mapping;
6
7
use Doctrine\DBAL\Types\Type;
8
use Doctrine\ORM\EntityRepository;
9
use Doctrine\ORM\Events;
10
use Doctrine\ORM\Mapping;
11
use Doctrine\ORM\Mapping\ClassMetadata;
12
use Doctrine\ORM\Mapping\DiscriminatorColumnMetadata;
13
use Doctrine\ORM\Mapping\Factory\DefaultNamingStrategy;
14
use Doctrine\ORM\Mapping\Factory\UnderscoreNamingStrategy;
15
use Doctrine\ORM\Mapping\JoinColumnMetadata;
16
use Doctrine\ORM\Mapping\MappingException;
17
use Doctrine\ORM\Reflection\RuntimeReflectionService;
18
use Doctrine\ORM\Reflection\StaticReflectionService;
19
use Doctrine\Tests\Models\CMS;
20
use Doctrine\Tests\Models\Company\CompanyContract;
21
use Doctrine\Tests\Models\Company\CompanyContractListener;
22
use Doctrine\Tests\Models\CustomType\CustomTypeParent;
23
use Doctrine\Tests\Models\DDC117\DDC117Article;
24
use Doctrine\Tests\Models\DDC117\DDC117ArticleDetails;
25
use Doctrine\Tests\Models\DDC6412\DDC6412File;
26
use Doctrine\Tests\Models\DDC964\DDC964Address;
27
use Doctrine\Tests\Models\DDC964\DDC964Admin;
28
use Doctrine\Tests\Models\DDC964\DDC964Guest;
29
use Doctrine\Tests\Models\Routing\RoutingLeg;
30
use Doctrine\Tests\OrmTestCase;
31
use DoctrineGlobal_Article;
32
33
require_once __DIR__ . '/../../Models/Global/GlobalNamespaceModel.php';
34
35
class ClassMetadataTest extends OrmTestCase
36
{
37
    /**
38
     * @var Mapping\ClassMetadataBuildingContext|\PHPUnit_Framework_MockObject_MockObject
39
     */
40
    private $metadataBuildingContext;
41
42
    public function setUp()
43
    {
44
        parent::setUp();
45
46
        $this->metadataBuildingContext = new Mapping\ClassMetadataBuildingContext(
47
            $this->createMock(Mapping\ClassMetadataFactory::class)
48
        );
49
    }
50
51
    public function testClassMetadataInstanceSimpleState()
52
    {
53
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
54
55
        $cm->initializeReflection(new RuntimeReflectionService());
56
57
        self::assertInstanceOf(\ReflectionClass::class, $cm->getReflectionClass());
58
        self::assertEquals(CMS\CmsUser::class, $cm->getClassName());
59
        self::assertEquals(CMS\CmsUser::class, $cm->getRootClassName());
60
        self::assertEquals([], $cm->getSubClasses());
61
        self::assertCount(0, $cm->getAncestorsIterator());
62
        self::assertEquals(Mapping\InheritanceType::NONE, $cm->inheritanceType);
63
    }
64
65
    public function testClassMetadataInstanceSerialization()
66
    {
67
        $parent = new ClassMetadata(CMS\CmsEmployee::class, $this->metadataBuildingContext);
68
        $cm     = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
69
70
        $cm->setParent($parent);
71
        $cm->initializeReflection(new RuntimeReflectionService());
72
73
        $discrColumn = new DiscriminatorColumnMetadata();
74
75
        $discrColumn->setColumnName('disc');
76
        $discrColumn->setType(Type::getType('integer'));
77
78
        $cm->setInheritanceType(Mapping\InheritanceType::SINGLE_TABLE);
79
        $cm->setSubclasses([
80
            'Doctrine\Tests\Models\CMS\One',
81
            'Doctrine\Tests\Models\CMS\Two',
82
            'Doctrine\Tests\Models\CMS\Three'
83
        ]);
84
        $cm->setCustomRepositoryClassName('Doctrine\Tests\Models\CMS\UserRepository');
85
        $cm->setDiscriminatorColumn($discrColumn);
86
        $cm->asReadOnly();
87
        $cm->addNamedQuery('dql', 'foo');
88
89
        $association = new Mapping\OneToOneAssociationMetadata('phonenumbers');
90
91
        $association->setTargetEntity(CMS\CmsAddress::class);
92
        $association->setMappedBy('foo');
93
94
        $cm->addProperty($association);
95
96
        self::assertCount(1, $cm->getDeclaredPropertiesIterator());
97
98
        $serialized = serialize($cm);
99
        $cm = unserialize($serialized);
100
        $cm->wakeupReflection(new RuntimeReflectionService());
101
102
        // Check state
103
        self::assertInstanceOf(\ReflectionClass::class, $cm->getReflectionClass());
104
        self::assertEquals(CMS\CmsUser::class, $cm->getClassName());
105
        self::assertEquals(CMS\CmsEmployee::class, $cm->getRootClassName());
106
        self::assertEquals('Doctrine\Tests\Models\CMS\UserRepository', $cm->getCustomRepositoryClassName());
107
        self::assertEquals(
108
            [
109
                'Doctrine\Tests\Models\CMS\One',
110
                'Doctrine\Tests\Models\CMS\Two',
111
                'Doctrine\Tests\Models\CMS\Three'
112
            ],
113
            $cm->getSubClasses()
114
        );
115
        self::assertCount(1, $cm->getAncestorsIterator());
116
        self::assertEquals(CMS\CmsEmployee::class, $cm->getAncestorsIterator()->current()->getClassName());
117
        self::assertEquals($discrColumn, $cm->discriminatorColumn);
118
        self::assertTrue($cm->isReadOnly());
119
        self::assertEquals(['dql' => 'foo'], $cm->getNamedQueries());
120
        self::assertCount(1, $cm->getDeclaredPropertiesIterator());
121
        self::assertInstanceOf(Mapping\OneToOneAssociationMetadata::class, $cm->getProperty('phonenumbers'));
122
123
        $oneOneMapping = $cm->getProperty('phonenumbers');
124
125
        self::assertEquals(Mapping\FetchMode::LAZY, $oneOneMapping->getFetchMode());
126
        self::assertEquals(CMS\CmsAddress::class, $oneOneMapping->getTargetEntity());
127
    }
128
129
    public function testFieldIsNullable()
130
    {
131
        $metadata = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
132
        $metadata->initializeReflection(new RuntimeReflectionService());
133
134
        // Explicit Nullable
135
        $fieldMetadata = new Mapping\FieldMetadata('status');
136
137
        $fieldMetadata->setType(Type::getType('string'));
138
        $fieldMetadata->setLength(50);
139
        $fieldMetadata->setNullable(true);
140
141
        $metadata->addProperty($fieldMetadata);
142
143
        $property = $metadata->getProperty('status');
144
145
        self::assertTrue($property->isNullable());
146
147
        // Explicit Not Nullable
148
        $fieldMetadata = new Mapping\FieldMetadata('username');
149
150
        $fieldMetadata->setType(Type::getType('string'));
151
        $fieldMetadata->setLength(50);
152
        $fieldMetadata->setNullable(false);
153
154
        $metadata->addProperty($fieldMetadata);
155
156
        $property = $metadata->getProperty('username');
157
158
        self::assertFalse($property->isNullable());
159
160
        // Implicit Not Nullable
161
        $fieldMetadata = new Mapping\FieldMetadata('name');
162
163
        $fieldMetadata->setType(Type::getType('string'));
164
        $fieldMetadata->setLength(50);
165
166
        $metadata->addProperty($fieldMetadata);
167
168
        $property = $metadata->getProperty('name');
169
170
        self::assertFalse($property->isNullable(), "By default a field should not be nullable.");
171
    }
172
173
    /**
174
     * @group DDC-115
175
     */
176
    public function testMapAssociationInGlobalNamespace()
177
    {
178
        require_once __DIR__."/../../Models/Global/GlobalNamespaceModel.php";
179
180
        $cm = new ClassMetadata(DoctrineGlobal_Article::class, $this->metadataBuildingContext);
181
182
        $cm->initializeReflection(new RuntimeReflectionService());
183
184
        $joinTable = new Mapping\JoinTableMetadata();
185
        $joinTable->setName('bar');
186
187
        $joinColumn = new Mapping\JoinColumnMetadata();
188
        $joinColumn->setColumnName("bar_id");
189
        $joinColumn->setReferencedColumnName("id");
190
191
        $joinTable->addJoinColumn($joinColumn);
192
193
        $joinColumn = new Mapping\JoinColumnMetadata();
194
        $joinColumn->setColumnName("baz_id");
195
        $joinColumn->setReferencedColumnName("id");
196
197
        $joinTable->addInverseJoinColumn($joinColumn);
198
199
        $association = new Mapping\ManyToManyAssociationMetadata('author');
200
201
        $association->setJoinTable($joinTable);
202
        $association->setTargetEntity('DoctrineGlobal_User');
203
204
        $cm->addProperty($association);
205
206
        self::assertEquals("DoctrineGlobal_User", $cm->getProperty('author')->getTargetEntity());
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Doctrine\ORM\Mapping\Property as the method getTargetEntity() does only exist in the following implementations of said interface: Doctrine\ORM\Mapping\AssociationMetadata, Doctrine\ORM\Mapping\ManyToManyAssociationMetadata, Doctrine\ORM\Mapping\ManyToOneAssociationMetadata, Doctrine\ORM\Mapping\OneToManyAssociationMetadata, Doctrine\ORM\Mapping\OneToOneAssociationMetadata, Doctrine\ORM\Mapping\ToManyAssociationMetadata, Doctrine\ORM\Mapping\ToOneAssociationMetadata.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
207
    }
208
209 View Code Duplication
    public function testMapManyToManyJoinTableDefaults()
210
    {
211
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
212
        $cm->initializeReflection(new RuntimeReflectionService());
213
214
        $association = new Mapping\ManyToManyAssociationMetadata('groups');
215
216
        $association->setTargetEntity(CMS\CmsGroup::class);
217
218
        $cm->addProperty($association);
219
220
        $association = $cm->getProperty('groups');
221
222
        $joinColumns = [];
223
224
        $joinColumn = new Mapping\JoinColumnMetadata();
225
226
        $joinColumn->setColumnName("cmsuser_id");
227
        $joinColumn->setReferencedColumnName("id");
228
        $joinColumn->setOnDelete("CASCADE");
229
230
        $joinColumns[] = $joinColumn;
231
232
        $inverseJoinColumns = [];
233
234
        $joinColumn = new Mapping\JoinColumnMetadata();
235
236
        $joinColumn->setColumnName("cmsgroup_id");
237
        $joinColumn->setReferencedColumnName("id");
238
        $joinColumn->setOnDelete("CASCADE");
239
240
        $inverseJoinColumns[] = $joinColumn;
241
242
        $joinTable = $association->getJoinTable();
243
244
        self::assertEquals('cmsuser_cmsgroup', $joinTable->getName());
245
        self::assertEquals($joinColumns, $joinTable->getJoinColumns());
246
        self::assertEquals($inverseJoinColumns, $joinTable->getInverseJoinColumns());
247
    }
248
249
    public function testSerializeManyToManyJoinTableCascade()
250
    {
251
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
252
        $cm->initializeReflection(new RuntimeReflectionService());
253
254
        $association = new Mapping\ManyToManyAssociationMetadata('groups');
255
256
        $association->setTargetEntity(CMS\CmsGroup::class);
257
258
        $cm->addProperty($association);
259
260
        $association = $cm->getProperty('groups');
261
        $association = unserialize(serialize($association));
262
263
        $joinTable = $association->getJoinTable();
264
265
        foreach ($joinTable->getJoinColumns() as $joinColumn) {
266
            self::assertEquals('CASCADE', $joinColumn->getOnDelete());
267
        }
268
    }
269
270
    /**
271
     * @group DDC-115
272
     */
273
    public function testSetDiscriminatorMapInGlobalNamespace()
274
    {
275
        require_once __DIR__."/../../Models/Global/GlobalNamespaceModel.php";
276
277
        $cm = new ClassMetadata('DoctrineGlobal_User', $this->metadataBuildingContext);
278
        $cm->initializeReflection(new RuntimeReflectionService());
279
        $cm->setDiscriminatorMap(['descr' => 'DoctrineGlobal_Article', 'foo' => 'DoctrineGlobal_User']);
280
281
        self::assertEquals("DoctrineGlobal_Article", $cm->discriminatorMap['descr']);
282
        self::assertEquals("DoctrineGlobal_User", $cm->discriminatorMap['foo']);
283
    }
284
285
    /**
286
     * @group DDC-115
287
     */
288
    public function testSetSubClassesInGlobalNamespace()
289
    {
290
        require_once __DIR__."/../../Models/Global/GlobalNamespaceModel.php";
291
292
        $cm = new ClassMetadata('DoctrineGlobal_User', $this->metadataBuildingContext);
293
        $cm->initializeReflection(new RuntimeReflectionService());
294
        $cm->setSubclasses(['DoctrineGlobal_Article']);
295
296
        self::assertEquals("DoctrineGlobal_Article", $cm->getSubClasses()[0]);
297
    }
298
299
    /**
300
     * @group DDC-268
301
     */
302
    public function testSetInvalidVersionMapping_ThrowsException()
303
    {
304
        $metadata = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
305
        $property = new Mapping\VersionFieldMetadata('foo'); //new FieldMetadata('foo', 'foo', Type::getType('string'));
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
306
307
        $property->setDeclaringClass($metadata);
308
        $property->setColumnName('foo');
309
        $property->setType(Type::getType('string'));
310
311
        $metadata->initializeReflection(new RuntimeReflectionService());
312
313
        $this->expectException(MappingException::class);
314
315
        $metadata->addProperty($property);
316
    }
317
318 View Code Duplication
    public function testGetSingleIdentifierFieldName_MultipleIdentifierEntity_ThrowsException()
319
    {
320
        $metadata = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
321
        $metadata->initializeReflection(new RuntimeReflectionService());
322
323
        $fieldMetadata = new Mapping\FieldMetadata('name');
324
        $fieldMetadata->setType(Type::getType('string'));
325
326
        $metadata->addProperty($fieldMetadata);
327
328
        $fieldMetadata = new Mapping\FieldMetadata('username');
329
        $fieldMetadata->setType(Type::getType('string'));
330
331
        $metadata->addProperty($fieldMetadata);
332
333
        $metadata->setIdentifier(['name', 'username']);
334
335
        $this->expectException(MappingException::class);
336
337
        $metadata->getSingleIdentifierFieldName();
338
    }
339
340
    public function testGetSingleIdentifierFieldName_NoIdEntity_ThrowsException()
341
    {
342
        $cm = new ClassMetadata(DDC6412File::class, $this->metadataBuildingContext);
343
        $cm->initializeReflection(new RuntimeReflectionService());
344
345
        $this->expectException(\Doctrine\ORM\Mapping\MappingException::class);
346
347
        $cm->getSingleIdentifierFieldName();
348
    }
349
350
    public function testDuplicateAssociationMappingException()
351
    {
352
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
353
        $cm->initializeReflection(new RuntimeReflectionService());
354
355
        $association = new Mapping\OneToOneAssociationMetadata('foo');
356
357
        $association->setDeclaringClass($cm);
358
        $association->setSourceEntity(\stdClass::class);
359
        $association->setTargetEntity(\stdClass::class);
360
        $association->setMappedBy('foo');
361
362
        $cm->addInheritedProperty($association);
363
364
        $this->expectException(MappingException::class);
365
366
        $association = new Mapping\OneToOneAssociationMetadata('foo');
367
368
        $association->setDeclaringClass($cm);
369
        $association->setSourceEntity(\stdClass::class);
370
        $association->setTargetEntity(\stdClass::class);
371
        $association->setMappedBy('foo');
372
373
        $cm->addInheritedProperty($association);
374
    }
375
376 View Code Duplication
    public function testDuplicateColumnName_ThrowsMappingException()
377
    {
378
        $metadata = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
379
        $metadata->initializeReflection(new RuntimeReflectionService());
380
381
        $fieldMetadata = new Mapping\FieldMetadata('name');
382
383
        $fieldMetadata->setType(Type::getType('string'));
384
385
        $metadata->addProperty($fieldMetadata);
386
387
        $this->expectException(MappingException::class);
388
389
        $fieldMetadata = new Mapping\FieldMetadata('username');
390
391
        $fieldMetadata->setType(Type::getType('string'));
392
        $fieldMetadata->setColumnName('name');
393
394
        $metadata->addProperty($fieldMetadata);
395
    }
396
397 View Code Duplication
    public function testDuplicateColumnName_DiscriminatorColumn_ThrowsMappingException()
398
    {
399
        $metadata = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
400
        $metadata->initializeReflection(new RuntimeReflectionService());
401
402
        $fieldMetadata = new Mapping\FieldMetadata('name');
403
404
        $fieldMetadata->setType(Type::getType('string'));
405
406
        $metadata->addProperty($fieldMetadata);
407
408
        $discrColumn = new DiscriminatorColumnMetadata();
409
410
        $discrColumn->setColumnName('name');
411
        $discrColumn->setType(Type::getType('string'));
412
        $discrColumn->setLength(255);
413
414
        $this->expectException(\Doctrine\ORM\Mapping\MappingException::class);
415
416
        $metadata->setDiscriminatorColumn($discrColumn);
417
    }
418
419 View Code Duplication
    public function testDuplicateColumnName_DiscriminatorColumn2_ThrowsMappingException()
420
    {
421
        $metadata = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
422
        $metadata->initializeReflection(new RuntimeReflectionService());
423
424
        $discrColumn = new DiscriminatorColumnMetadata();
425
426
        $discrColumn->setColumnName('name');
427
        $discrColumn->setType(Type::getType('string'));
428
        $discrColumn->setLength(255);
429
430
        $metadata->setDiscriminatorColumn($discrColumn);
431
432
        $this->expectException(\Doctrine\ORM\Mapping\MappingException::class);
433
434
        $fieldMetadata = new Mapping\FieldMetadata('name');
435
436
        $fieldMetadata->setType(Type::getType('string'));
437
438
        $metadata->addProperty($fieldMetadata);
439
    }
440
441
    public function testDuplicateFieldAndAssociationMapping1_ThrowsException()
442
    {
443
        $metadata = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
444
        $metadata->initializeReflection(new RuntimeReflectionService());
445
446
        $fieldMetadata = new Mapping\FieldMetadata('name');
447
448
        $fieldMetadata->setType(Type::getType('string'));
449
450
        $metadata->addProperty($fieldMetadata);
451
452
        $this->expectException(\Doctrine\ORM\Mapping\MappingException::class);
453
454
        $association = new Mapping\OneToOneAssociationMetadata('name');
455
456
        $association->setTargetEntity(CMS\CmsUser::class);
457
458
        $metadata->addProperty($association);
459
    }
460
461
    public function testDuplicateFieldAndAssociationMapping2_ThrowsException()
462
    {
463
        $metadata = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
464
        $metadata->initializeReflection(new RuntimeReflectionService());
465
466
        $association = new Mapping\OneToOneAssociationMetadata('name');
467
468
        $association->setTargetEntity(CMS\CmsUser::class);
469
470
        $metadata->addProperty($association);
471
472
        $this->expectException(\Doctrine\ORM\Mapping\MappingException::class);
473
474
        $fieldMetadata = new Mapping\FieldMetadata('name');
475
476
        $fieldMetadata->setType(Type::getType('string'));
477
478
        $metadata->addProperty($fieldMetadata);
479
    }
480
481
    /**
482
     * @group DDC-1224
483
     */
484
    public function testGetTemporaryTableNameSchema()
485
    {
486
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
487
        $cm->initializeReflection(new RuntimeReflectionService());
488
489
        $tableMetadata = new Mapping\TableMetadata();
490
491
        $tableMetadata->setSchema('foo');
492
        $tableMetadata->setName('bar');
493
494
        $cm->setTable($tableMetadata);
495
496
        self::assertEquals('foo_bar_id_tmp', $cm->getTemporaryIdTableName());
497
    }
498
499
    public function testDefaultTableName()
500
    {
501
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
502
        $cm->initializeReflection(new RuntimeReflectionService());
503
504
        // When table's name is not given
505
        self::assertEquals('CmsUser', $cm->getTableName());
506
        self::assertEquals('CmsUser', $cm->table->getName());
507
508
        $cm = new ClassMetadata(CMS\CmsAddress::class, $this->metadataBuildingContext);
509
        $cm->initializeReflection(new RuntimeReflectionService());
510
511
        // When joinTable's name is not given
512
        $joinTable = new Mapping\JoinTableMetadata();
513
514
        $joinColumn = new Mapping\JoinColumnMetadata();
515
        $joinColumn->setReferencedColumnName("id");
516
517
        $joinTable->addJoinColumn($joinColumn);
518
519
        $joinColumn = new Mapping\JoinColumnMetadata();
520
        $joinColumn->setReferencedColumnName("id");
521
522
        $joinTable->addInverseJoinColumn($joinColumn);
523
524
        $association = new Mapping\ManyToManyAssociationMetadata('user');
525
526
        $association->setJoinTable($joinTable);
527
        $association->setTargetEntity(CMS\CmsUser::class);
528
        $association->setInversedBy('users');
529
530
        $cm->addProperty($association);
531
532
        $association = $cm->getProperty('user');
533
534
        self::assertEquals('cmsaddress_cmsuser', $association->getJoinTable()->getName());
535
    }
536
537
    public function testDefaultJoinColumnName()
538
    {
539
        $cm = new ClassMetadata(CMS\CmsAddress::class, $this->metadataBuildingContext);
540
        $cm->initializeReflection(new RuntimeReflectionService());
541
542
        // this is really dirty, but it's the simplest way to test whether
543
        // joinColumn's name will be automatically set to user_id
544
        $joinColumns = [];
545
546
        $joinColumn = new JoinColumnMetadata();
547
548
        $joinColumn->setReferencedColumnName('id');
549
550
        $joinColumns[] = $joinColumn;
551
552
        $association = new Mapping\OneToOneAssociationMetadata('user');
553
554
        $association->setJoinColumns($joinColumns);
555
        $association->setTargetEntity(CMS\CmsUser::class);
556
557
        $cm->addProperty($association);
558
559
        $association = $cm->getProperty('user');
560
        $joinColumns = $association->getJoinColumns();
561
        $joinColumn  = reset($joinColumns);
562
563
        self::assertEquals('user_id', $joinColumn->getColumnName());
564
565
        $cm = new ClassMetadata(CMS\CmsAddress::class, $this->metadataBuildingContext);
566
        $cm->initializeReflection(new RuntimeReflectionService());
567
568
        $joinTable = new Mapping\JoinTableMetadata();
569
        $joinTable->setName('user_CmsUser');
570
571
        $joinColumn = new JoinColumnMetadata();
572
        $joinColumn->setReferencedColumnName('id');
573
574
        $joinTable->addJoinColumn($joinColumn);
575
576
        $joinColumn = new JoinColumnMetadata();
577
        $joinColumn->setReferencedColumnName('id');
578
579
        $joinTable->addInverseJoinColumn($joinColumn);
580
581
        $association = new Mapping\ManyToManyAssociationMetadata('user');
582
583
        $association->setJoinTable($joinTable);
584
        $association->setTargetEntity(CMS\CmsUser::class);
585
        $association->setInversedBy('users');
586
587
        $cm->addProperty($association);
588
589
        $association        = $cm->getProperty('user');
590
        $joinTable          = $association->getJoinTable();
591
        $joinColumns        = $joinTable->getJoinColumns();
592
        $joinColumn         = reset($joinColumns);
593
        $inverseJoinColumns = $joinTable->getInverseJoinColumns();
594
        $inverseJoinColumn  = reset($inverseJoinColumns);
595
596
        self::assertEquals('cmsaddress_id', $joinColumn->getColumnName());
597
        self::assertEquals('cmsuser_id', $inverseJoinColumn->getColumnName());
598
    }
599
600
    /**
601
     * @group DDC-559
602
     */
603
    public function testOneToOneUnderscoreNamingStrategyDefaults()
604
    {
605
        $namingStrategy = new UnderscoreNamingStrategy(CASE_UPPER);
606
607
        $this->metadataBuildingContext = new Mapping\ClassMetadataBuildingContext(
608
            $this->createMock(Mapping\ClassMetadataFactory::class),
609
            $namingStrategy
610
        );
611
612
        $metadata    = new ClassMetadata(CMS\CmsAddress::class, $this->metadataBuildingContext);
613
614
        $association = new Mapping\OneToOneAssociationMetadata('user');
615
616
        $association->setTargetEntity(CMS\CmsUser::class);
617
618
        $metadata->addProperty($association);
619
620
        $association = $metadata->getProperty('user');
621
        $joinColumns = $association->getJoinColumns();
622
        $joinColumn  = reset($joinColumns);
623
624
        self::assertEquals('USER_ID', $joinColumn->getColumnName());
625
        self::assertEquals('ID', $joinColumn->getReferencedColumnName());
626
    }
627
628
    /**
629
     * @group DDC-559
630
     */
631
    public function testManyToManyUnderscoreNamingStrategyDefaults()
632
    {
633
        $namingStrategy = new UnderscoreNamingStrategy(CASE_UPPER);
634
635
        $this->metadataBuildingContext = new Mapping\ClassMetadataBuildingContext(
636
            $this->createMock(Mapping\ClassMetadataFactory::class),
637
            $namingStrategy
638
        );
639
640
        $metadata       = new ClassMetadata(CMS\CmsAddress::class, $this->metadataBuildingContext);
641
642
        $association = new Mapping\ManyToManyAssociationMetadata('user');
643
644
        $association->setTargetEntity(CMS\CmsUser::class);
645
646
        $metadata->addProperty($association);
647
648
        $association        = $metadata->getProperty('user');
649
        $joinTable          = $association->getJoinTable();
650
        $joinColumns        = $joinTable->getJoinColumns();
651
        $joinColumn         = reset($joinColumns);
652
        $inverseJoinColumns = $joinTable->getInverseJoinColumns();
653
        $inverseJoinColumn  = reset($inverseJoinColumns);
654
655
        self::assertEquals('CMS_ADDRESS_CMS_USER', $joinTable->getName());
656
657
        self::assertEquals('CMS_ADDRESS_ID', $joinColumn->getColumnName());
658
        self::assertEquals('ID', $joinColumn->getReferencedColumnName());
659
660
        self::assertEquals('CMS_USER_ID', $inverseJoinColumn->getColumnName());
661
        self::assertEquals('ID', $inverseJoinColumn->getReferencedColumnName());
662
663
        $cm = new ClassMetadata('DoctrineGlobal_Article', $this->metadataBuildingContext);
664
665
        $association = new Mapping\ManyToManyAssociationMetadata('author');
666
667
        $association->setTargetEntity(CMS\CmsUser::class);
668
669
        $cm->addProperty($association);
670
671
        $association = $cm->getProperty('author');
672
673
        self::assertEquals('DOCTRINE_GLOBAL_ARTICLE_CMS_USER', $association->getJoinTable()->getName());
674
    }
675
676
    /**
677
     * @group DDC-886
678
     */
679 View Code Duplication
    public function testSetMultipleIdentifierSetsComposite()
680
    {
681
        $metadata = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
682
        $metadata->initializeReflection(new RuntimeReflectionService());
683
684
        $fieldMetadata = new Mapping\FieldMetadata('name');
685
        $fieldMetadata->setType(Type::getType('string'));
686
687
        $metadata->addProperty($fieldMetadata);
688
689
        $fieldMetadata = new Mapping\FieldMetadata('username');
690
        $fieldMetadata->setType(Type::getType('string'));
691
692
        $metadata->addProperty($fieldMetadata);
693
694
        $metadata->setIdentifier(['name', 'username']);
695
        self::assertTrue($metadata->isIdentifierComposite());
696
    }
697
698
    /**
699
     * @group DDC-961
700
     */
701
    public function testJoinTableMappingDefaults()
702
    {
703
        $metadata = new ClassMetadata('DoctrineGlobal_Article', $this->metadataBuildingContext);
704
        $metadata->initializeReflection(new RuntimeReflectionService());
705
706
        $association = new Mapping\ManyToManyAssociationMetadata('author');
707
708
        $association->setTargetEntity(CMS\CmsUser::class);
709
710
        $metadata->addProperty($association);
711
712
        $association = $metadata->getProperty('author');
713
714
        self::assertEquals('doctrineglobal_article_cmsuser', $association->getJoinTable()->getName());
715
    }
716
717
    /**
718
     * @group DDC-117
719
     */
720
    public function testMapIdentifierAssociation()
721
    {
722
        $cm = new ClassMetadata(DDC117ArticleDetails::class, $this->metadataBuildingContext);
723
        $cm->initializeReflection(new RuntimeReflectionService());
724
725
        $association = new Mapping\OneToOneAssociationMetadata('article');
726
727
        $association->setTargetEntity(DDC117Article::class);
728
        $association->setPrimaryKey(true);
729
730
        $cm->addProperty($association);
731
732
        self::assertEquals(["article"], $cm->identifier);
733
    }
734
735
    /**
736
     * @group DDC-117
737
     */
738 View Code Duplication
    public function testOrphanRemovalIdentifierAssociation()
739
    {
740
        $cm = new ClassMetadata(DDC117ArticleDetails::class, $this->metadataBuildingContext);
741
        $cm->initializeReflection(new RuntimeReflectionService());
742
743
        $this->expectException(MappingException::class);
744
        $this->expectExceptionMessage('The orphan removal option is not allowed on an association that');
745
746
        $association = new Mapping\OneToOneAssociationMetadata('article');
747
748
        $association->setTargetEntity(DDC117Article::class);
749
        $association->setPrimaryKey(true);
750
        $association->setOrphanRemoval(true);
751
752
        $cm->addProperty($association);
753
    }
754
755
    /**
756
     * @group DDC-117
757
     */
758 View Code Duplication
    public function testInverseIdentifierAssociation()
759
    {
760
        $cm = new ClassMetadata(DDC117ArticleDetails::class, $this->metadataBuildingContext);
761
        $cm->initializeReflection(new RuntimeReflectionService());
762
763
        $this->expectException(MappingException::class);
764
        $this->expectExceptionMessage('An inverse association is not allowed to be identifier in');
765
766
        $association = new Mapping\OneToOneAssociationMetadata('article');
767
768
        $association->setTargetEntity(DDC117Article::class);
769
        $association->setPrimaryKey(true);
770
        $association->setMappedBy('details');
771
772
        $cm->addProperty($association);
773
    }
774
775
    /**
776
     * @group DDC-117
777
     */
778 View Code Duplication
    public function testIdentifierAssociationManyToMany()
779
    {
780
        $cm = new ClassMetadata(DDC117ArticleDetails::class, $this->metadataBuildingContext);
781
        $cm->initializeReflection(new RuntimeReflectionService());
782
783
        $this->expectException(MappingException::class);
784
        $this->expectExceptionMessage('Many-to-many or one-to-many associations are not allowed to be identifier in');
785
786
        $association = new Mapping\ManyToManyAssociationMetadata('article');
787
788
        $association->setTargetEntity(DDC117Article::class);
789
        $association->setPrimaryKey(true);
790
791
        $cm->addProperty($association);
792
    }
793
794
    /**
795
     * @group DDC-996
796
     */
797 View Code Duplication
    public function testEmptyFieldNameThrowsException()
798
    {
799
        $this->expectException(MappingException::class);
800
        $this->expectExceptionMessage("The field or association mapping misses the 'fieldName' attribute in entity '" . CMS\CmsUser::class . "'.");
801
802
        $metadata = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
803
        $metadata->initializeReflection(new RuntimeReflectionService());
804
805
        $fieldMetadata = new Mapping\FieldMetadata('');
806
807
        $fieldMetadata->setType(Type::getType('string'));
808
809
        $metadata->addProperty($fieldMetadata);
810
    }
811
812
    public function testRetrievalOfNamedQueries()
813
    {
814
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
815
        $cm->initializeReflection(new RuntimeReflectionService());
816
817
        self::assertEquals(0, count($cm->getNamedQueries()));
818
819
        $cm->addNamedQuery('userById', 'SELECT u FROM __CLASS__ u WHERE u.id = ?1');
820
821
        self::assertEquals(1, count($cm->getNamedQueries()));
822
    }
823
824
    /**
825
     * @group DDC-1663
826
     */
827 View Code Duplication
    public function testRetrievalOfResultSetMappings()
828
    {
829
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
830
        $cm->initializeReflection(new RuntimeReflectionService());
831
832
833
        self::assertEquals(0, count($cm->getSqlResultSetMappings()));
834
835
        $cm->addSqlResultSetMapping(
836
            [
837
            'name'      => 'find-all',
838
            'entities'  => [
839
                [
840
                    'entityClass'   => CMS\CmsUser::class,
841
                ],
842
            ],
843
            ]
844
        );
845
846
        self::assertEquals(1, count($cm->getSqlResultSetMappings()));
847
    }
848
849
    public function testExistanceOfNamedQuery()
850
    {
851
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
852
        $cm->initializeReflection(new RuntimeReflectionService());
853
854
855
        $cm->addNamedQuery('all', 'SELECT u FROM __CLASS__ u');
856
857
        self::assertTrue($cm->hasNamedQuery('all'));
858
        self::assertFalse($cm->hasNamedQuery('userById'));
859
    }
860
861
    /**
862
     * @group DDC-1663
863
     */
864
    public function testRetrieveOfNamedNativeQuery()
865
    {
866
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
867
        $cm->initializeReflection(new RuntimeReflectionService());
868
869
        $cm->addNamedNativeQuery(
870
            'find-all',
871
            'SELECT * FROM cms_users',
872
            [
873
                'resultSetMapping' => 'result-mapping-name',
874
                'resultClass'      => CMS\CmsUser::class,
875
            ]
876
        );
877
878
        $cm->addNamedNativeQuery(
879
            'find-by-id',
880
            'SELECT * FROM cms_users WHERE id = ?',
881
            [
882
                'resultClass'      => '__CLASS__',
883
                'resultSetMapping' => 'result-mapping-name',
884
            ]
885
        );
886
887
        $mapping = $cm->getNamedNativeQuery('find-all');
888
889
        self::assertEquals('SELECT * FROM cms_users', $mapping['query']);
890
        self::assertEquals('result-mapping-name', $mapping['resultSetMapping']);
891
        self::assertEquals(CMS\CmsUser::class, $mapping['resultClass']);
892
893
        $mapping = $cm->getNamedNativeQuery('find-by-id');
894
895
        self::assertEquals('SELECT * FROM cms_users WHERE id = ?', $mapping['query']);
896
        self::assertEquals('result-mapping-name', $mapping['resultSetMapping']);
897
        self::assertEquals('__CLASS__', $mapping['resultClass']);
898
    }
899
900
    /**
901
     * @group DDC-1663
902
     */
903
    public function testRetrieveOfSqlResultSetMapping()
904
    {
905
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
906
        $cm->initializeReflection(new RuntimeReflectionService());
907
908
        $cm->addSqlResultSetMapping(
909
            [
910
                'name'      => 'find-all',
911
                'entities'  => [
912
                    [
913
                        'entityClass'   => '__CLASS__',
914
                        'fields'        => [
915
                            [
916
                                'name'  => 'id',
917
                                'column'=> 'id'
918
                            ],
919
                            [
920
                                'name'  => 'name',
921
                                'column'=> 'name'
922
                            ]
923
                        ]
924
                    ],
925
                    [
926
                        'entityClass'   => CMS\CmsEmail::class,
927
                        'fields'        => [
928
                            [
929
                                'name'  => 'id',
930
                                'column'=> 'id'
931
                            ],
932
                            [
933
                                'name'  => 'email',
934
                                'column'=> 'email'
935
                            ]
936
                        ]
937
                    ]
938
                ],
939
                'columns'   => [['name' => 'scalarColumn']]
940
            ]
941
        );
942
943
        $mapping = $cm->getSqlResultSetMapping('find-all');
944
945
        self::assertEquals('__CLASS__', $mapping['entities'][0]['entityClass']);
946
        self::assertEquals(['name'=>'id','column'=>'id'], $mapping['entities'][0]['fields'][0]);
947
        self::assertEquals(['name'=>'name','column'=>'name'], $mapping['entities'][0]['fields'][1]);
948
949
        self::assertEquals(CMS\CmsEmail::class, $mapping['entities'][1]['entityClass']);
950
        self::assertEquals(['name'=>'id','column'=>'id'], $mapping['entities'][1]['fields'][0]);
951
        self::assertEquals(['name'=>'email','column'=>'email'], $mapping['entities'][1]['fields'][1]);
952
953
        self::assertEquals('scalarColumn', $mapping['columns'][0]['name']);
954
    }
955
956
    /**
957
     * @group DDC-1663
958
     */
959 View Code Duplication
    public function testExistanceOfSqlResultSetMapping()
960
    {
961
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
962
        $cm->initializeReflection(new RuntimeReflectionService());
963
964
        $cm->addSqlResultSetMapping(
965
            [
966
                'name'      => 'find-all',
967
                'entities'  => [
968
                    [
969
                        'entityClass'   => CMS\CmsUser::class,
970
                    ],
971
                ],
972
            ]
973
        );
974
975
        self::assertTrue($cm->hasSqlResultSetMapping('find-all'));
976
        self::assertFalse($cm->hasSqlResultSetMapping('find-by-id'));
977
    }
978
979
    /**
980
     * @group DDC-1663
981
     */
982 View Code Duplication
    public function testExistanceOfNamedNativeQuery()
983
    {
984
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
985
        $cm->initializeReflection(new RuntimeReflectionService());
986
987
        $cm->addNamedNativeQuery(
988
            'find-all',
989
            'SELECT * FROM cms_users',
990
            [
991
                'resultClass' => CMS\CmsUser::class,
992
            ]
993
        );
994
995
        self::assertTrue($cm->hasNamedNativeQuery('find-all'));
996
        self::assertFalse($cm->hasNamedNativeQuery('find-by-id'));
997
    }
998
999
    public function testRetrieveOfNamedQuery()
1000
    {
1001
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
1002
        $cm->initializeReflection(new RuntimeReflectionService());
1003
1004
        $cm->addNamedQuery('userById', 'SELECT u FROM __CLASS__ u WHERE u.id = ?1');
1005
1006
        self::assertEquals('SELECT u FROM __CLASS__ u WHERE u.id = ?1', $cm->getNamedQuery('userById'));
1007
1008
        // Named queries are only resolved when created
1009
        $repo = new EntityRepository($this->getTestEntityManager(), $cm);
1010
1011
        self::assertEquals('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = ?1', $repo->createNamedQuery('userById')->getDQL());
1012
    }
1013
1014
    /**
1015
     * @group DDC-1663
1016
     */
1017 View Code Duplication
    public function testRetrievalOfNamedNativeQueries()
1018
    {
1019
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
1020
        $cm->initializeReflection(new RuntimeReflectionService());
1021
1022
        self::assertEquals(0, count($cm->getNamedNativeQueries()));
1023
1024
        $cm->addNamedNativeQuery(
1025
            'find-all',
1026
            'SELECT * FROM cms_users',
1027
            [
1028
                'resultClass' => CMS\CmsUser::class,
1029
            ]
1030
        );
1031
1032
        self::assertEquals(1, count($cm->getNamedNativeQueries()));
1033
    }
1034
1035
    /**
1036
     * @group DDC-2451
1037
     */
1038
    public function testSerializeEntityListeners()
1039
    {
1040
        $metadata = new ClassMetadata(CompanyContract::class, $this->metadataBuildingContext);
1041
1042
        $metadata->initializeReflection(new RuntimeReflectionService());
1043
        $metadata->addEntityListener(Events::prePersist, CompanyContractListener::class, 'prePersistHandler');
1044
        $metadata->addEntityListener(Events::postPersist, CompanyContractListener::class, 'postPersistHandler');
1045
1046
        $serialize   = serialize($metadata);
1047
        $unserialize = unserialize($serialize);
1048
1049
        self::assertEquals($metadata->entityListeners, $unserialize->entityListeners);
1050
    }
1051
1052
    /**
1053
     * @expectedException \Doctrine\ORM\Mapping\MappingException
1054
     * @expectedExceptionMessage Query named "userById" in "Doctrine\Tests\Models\CMS\CmsUser" was already declared, but it must be declared only once
1055
     */
1056
    public function testNamingCollisionNamedQueryShouldThrowException()
1057
    {
1058
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
1059
        $cm->initializeReflection(new RuntimeReflectionService());
1060
1061
        $cm->addNamedQuery('userById', 'SELECT u FROM __CLASS__ u WHERE u.id = ?1');
1062
        $cm->addNamedQuery('userById', 'SELECT u FROM __CLASS__ u WHERE u.id = ?1');
1063
    }
1064
1065
    /**
1066
     * @group DDC-1663
1067
     *
1068
     * @expectedException \Doctrine\ORM\Mapping\MappingException
1069
     * @expectedExceptionMessage Query named "find-all" in "Doctrine\Tests\Models\CMS\CmsUser" was already declared, but it must be declared only once
1070
     */
1071
    public function testNamingCollisionNamedNativeQueryShouldThrowException()
1072
    {
1073
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
1074
        $cm->initializeReflection(new RuntimeReflectionService());
1075
1076
        $cm->addNamedNativeQuery(
1077
            'find-all',
1078
            'SELECT * FROM cms_users',
1079
            [
1080
                'resultClass' => CMS\CmsUser::class,
1081
            ]
1082
        );
1083
1084
        $cm->addNamedNativeQuery(
1085
            'find-all',
1086
            'SELECT * FROM cms_users',
1087
            [
1088
                'resultClass' => CMS\CmsUser::class,
1089
            ]
1090
        );
1091
    }
1092
1093
    /**
1094
     * @group DDC-1663
1095
     *
1096
     * @expectedException \Doctrine\ORM\Mapping\MappingException
1097
     * @expectedExceptionMessage Result set mapping named "find-all" in "Doctrine\Tests\Models\CMS\CmsUser" was already declared, but it must be declared only once
1098
     */
1099
    public function testNamingCollisionSqlResultSetMappingShouldThrowException()
1100
    {
1101
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
1102
        $cm->initializeReflection(new RuntimeReflectionService());
1103
1104
        $cm->addSqlResultSetMapping(
1105
            [
1106
            'name'      => 'find-all',
1107
            'entities'  => [
1108
                [
1109
                    'entityClass'   => CMS\CmsUser::class,
1110
                ],
1111
            ],
1112
            ]
1113
        );
1114
1115
        $cm->addSqlResultSetMapping(
1116
            [
1117
            'name'      => 'find-all',
1118
            'entities'  => [
1119
                [
1120
                    'entityClass'   => CMS\CmsUser::class,
1121
                ],
1122
            ],
1123
            ]
1124
        );
1125
    }
1126
1127
    /**
1128
     * @group DDC-1068
1129
     */
1130
    public function testClassCaseSensitivity()
1131
    {
1132
        $user = new CMS\CmsUser();
0 ignored issues
show
Unused Code introduced by
$user is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1133
        $cm = new ClassMetadata(strtoupper(CMS\CmsUser::class), $this->metadataBuildingContext);
1134
        $cm->initializeReflection(new RuntimeReflectionService());
1135
1136
        self::assertEquals(CMS\CmsUser::class, $cm->getClassName());
1137
    }
1138
1139
    /**
1140
     * @group DDC-659
1141
     */
1142 View Code Duplication
    public function testLifecycleCallbackNotFound()
1143
    {
1144
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
1145
        $cm->initializeReflection(new RuntimeReflectionService());
1146
        $cm->addLifecycleCallback('notfound', 'postLoad');
1147
1148
        $this->expectException(MappingException::class);
1149
        $this->expectExceptionMessage("Entity '" . CMS\CmsUser::class . "' has no method 'notfound' to be registered as lifecycle callback.");
1150
1151
        $cm->validateLifecycleCallbacks(new RuntimeReflectionService());
1152
    }
1153
1154
    /**
1155
     * @group ImproveErrorMessages
1156
     */
1157 View Code Duplication
    public function testTargetEntityNotFound()
1158
    {
1159
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
1160
        $cm->initializeReflection(new RuntimeReflectionService());
1161
1162
        $association = new Mapping\ManyToOneAssociationMetadata('address');
1163
1164
        $association->setTargetEntity('UnknownClass');
1165
1166
        $cm->addProperty($association);
1167
1168
        $this->expectException(MappingException::class);
1169
        $this->expectExceptionMessage("The target-entity 'UnknownClass' cannot be found in '" . CMS\CmsUser::class . "#address'.");
1170
1171
        $cm->validateAssociations();
1172
    }
1173
1174
    /**
1175
     * @group DDC-1663
1176
     *
1177
     * @expectedException \Doctrine\ORM\Mapping\MappingException
1178
     * @expectedExceptionMessage Result set mapping named "find-all" in "Doctrine\Tests\Models\CMS\CmsUser requires a entity class name.
1179
     */
1180
    public function testNameIsMandatoryForEntityNameSqlResultSetMappingException()
1181
    {
1182
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
1183
        $cm->initializeReflection(new RuntimeReflectionService());
1184
1185
        $cm->addSqlResultSetMapping(
1186
            [
1187
            'name'      => 'find-all',
1188
            'entities'  => [
1189
                [
1190
                    'fields' => []
1191
                ]
1192
            ],
1193
            ]
1194
        );
1195
    }
1196
1197
    /**
1198
     * @group DDC-984
1199
     * @group DDC-559
1200
     * @group DDC-1575
1201
     */
1202
    public function testFullyQualifiedClassNameShouldBeGivenToNamingStrategy()
1203
    {
1204
        $namingStrategy = new MyNamespacedNamingStrategy();
1205
1206
        $this->metadataBuildingContext = new Mapping\ClassMetadataBuildingContext(
1207
            $this->createMock(Mapping\ClassMetadataFactory::class),
1208
            $namingStrategy
1209
        );
1210
1211
        $addressMetadata    = new ClassMetadata(CMS\CmsAddress::class, $this->metadataBuildingContext);
1212
        $articleMetadata    = new ClassMetadata(DoctrineGlobal_Article::class, $this->metadataBuildingContext);
1213
        $routingMetadata    = new ClassMetadata(RoutingLeg::class, $this->metadataBuildingContext);
1214
1215
        $addressMetadata->initializeReflection(new RuntimeReflectionService());
1216
        $articleMetadata->initializeReflection(new RuntimeReflectionService());
1217
        $routingMetadata->initializeReflection(new RuntimeReflectionService());
1218
1219
        $association = new Mapping\ManyToManyAssociationMetadata('user');
1220
1221
        $association->setTargetEntity(CMS\CmsUser::class);
1222
1223
        $addressMetadata->addProperty($association);
1224
1225
        $association = new Mapping\ManyToManyAssociationMetadata('author');
1226
1227
        $association->setTargetEntity(CMS\CmsUser::class);
1228
1229
        $articleMetadata->addProperty($association);
1230
1231
        self::assertEquals('routing_routingleg', $routingMetadata->table->getName());
1232
        self::assertEquals('cms_cmsaddress_cms_cmsuser', $addressMetadata->getProperty('user')->getJoinTable()->getName());
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Doctrine\ORM\Mapping\Property as the method getJoinTable() does only exist in the following implementations of said interface: Doctrine\ORM\Mapping\ManyToManyAssociationMetadata.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1233
        self::assertEquals('doctrineglobal_article_cms_cmsuser', $articleMetadata->getProperty('author')->getJoinTable()->getName());
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Doctrine\ORM\Mapping\Property as the method getJoinTable() does only exist in the following implementations of said interface: Doctrine\ORM\Mapping\ManyToManyAssociationMetadata.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1234
    }
1235
1236
    /**
1237
     * @group DDC-984
1238
     * @group DDC-559
1239
     */
1240
    public function testFullyQualifiedClassNameShouldBeGivenToNamingStrategyPropertyToColumnName()
1241
    {
1242
        $namingStrategy = new MyPrefixNamingStrategy();
1243
1244
        $this->metadataBuildingContext = new Mapping\ClassMetadataBuildingContext(
1245
            $this->createMock(Mapping\ClassMetadataFactory::class),
1246
            $namingStrategy
1247
        );
1248
1249
        $metadata = new ClassMetadata(CMS\CmsAddress::class, $this->metadataBuildingContext);
1250
1251
        $metadata->initializeReflection(new RuntimeReflectionService());
1252
1253
        $fieldMetadata = new Mapping\FieldMetadata('country');
1254
1255
        $fieldMetadata->setType(Type::getType('string'));
1256
1257
        $metadata->addProperty($fieldMetadata);
1258
1259
        $fieldMetadata = new Mapping\FieldMetadata('city');
1260
1261
        $fieldMetadata->setType(Type::getType('string'));
1262
1263
        $metadata->addProperty($fieldMetadata);
1264
1265
        self::assertEquals(
1266
            $metadata->fieldNames,
1267
            [
1268
                'cmsaddress_country' => 'country',
1269
                'cmsaddress_city'    => 'city'
1270
            ]
1271
        );
1272
    }
1273
1274
    /**
1275
     * @group DDC-1746
1276
     * @expectedException        \Doctrine\ORM\Mapping\MappingException
1277
     * @expectedExceptionMessage You have specified invalid cascade options for Doctrine\Tests\Models\CMS\CmsUser::$address: 'invalid'; available options: 'remove', 'persist', 'refresh', 'merge', and 'detach'
1278
     */
1279 View Code Duplication
    public function testInvalidCascade()
1280
    {
1281
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
1282
        $cm->initializeReflection(new RuntimeReflectionService());
1283
1284
        $association = new Mapping\ManyToOneAssociationMetadata('address');
1285
1286
        $association->setTargetEntity('UnknownClass');
1287
        $association->setCascade(['invalid']);
1288
1289
        $cm->addProperty($association);
1290
     }
1291
1292
    /**
1293
     * @group DDC-964
1294
     * @expectedException        \Doctrine\ORM\Mapping\MappingException
1295
     * @expectedExceptionMessage Invalid field override named 'invalidPropertyName' for class 'Doctrine\Tests\Models\DDC964\DDC964Admin'
1296
     */
1297 View Code Duplication
    public function testInvalidPropertyAssociationOverrideNameException()
1298
    {
1299
        $cm = new ClassMetadata(DDC964Admin::class, $this->metadataBuildingContext);
1300
        $cm->initializeReflection(new RuntimeReflectionService());
1301
1302
        $association = new Mapping\ManyToOneAssociationMetadata('address');
1303
1304
        $association->setTargetEntity(DDC964Address::class);
1305
1306
        $cm->addProperty($association);
1307
1308
        $cm->setPropertyOverride(new Mapping\ManyToOneAssociationMetadata('invalidPropertyName'));
1309
    }
1310
1311
    /**
1312
     * @group DDC-964
1313
     * @expectedException        \Doctrine\ORM\Mapping\MappingException
1314
     * @expectedExceptionMessage Invalid field override named 'invalidPropertyName' for class 'Doctrine\Tests\Models\DDC964\DDC964Guest'.
1315
     */
1316
    public function testInvalidPropertyAttributeOverrideNameException()
1317
    {
1318
        $metadata = new ClassMetadata(DDC964Guest::class, $this->metadataBuildingContext);
1319
        $metadata->initializeReflection(new RuntimeReflectionService());
1320
1321
        $fieldMetadata = new Mapping\FieldMetadata('name');
1322
        $fieldMetadata->setType(Type::getType('string'));
1323
1324
        $metadata->addProperty($fieldMetadata);
1325
1326
        $fieldMetadata = new Mapping\FieldMetadata('invalidPropertyName');
1327
        $fieldMetadata->setType(Type::getType('string'));
1328
1329
        $metadata->setPropertyOverride($fieldMetadata);
1330
    }
1331
1332
    /**
1333
     * @group DDC-1955
1334
     *
1335
     * @expectedException        \Doctrine\ORM\Mapping\MappingException
1336
     * @expectedExceptionMessage Entity Listener "\InvalidClassName" declared on "Doctrine\Tests\Models\CMS\CmsUser" not found.
1337
     */
1338 View Code Duplication
    public function testInvalidEntityListenerClassException()
1339
    {
1340
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
1341
        $cm->initializeReflection(new RuntimeReflectionService());
1342
1343
        $cm->addEntityListener(Events::postLoad, '\InvalidClassName', 'postLoadHandler');
1344
    }
1345
1346
    /**
1347
     * @group DDC-1955
1348
     *
1349
     * @expectedException        \Doctrine\ORM\Mapping\MappingException
1350
     * @expectedExceptionMessage Entity Listener "Doctrine\Tests\Models\Company\CompanyContractListener" declared on "Doctrine\Tests\Models\CMS\CmsUser" has no method "invalidMethod".
1351
     */
1352 View Code Duplication
    public function testInvalidEntityListenerMethodException()
1353
    {
1354
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
1355
        $cm->initializeReflection(new RuntimeReflectionService());
1356
1357
        $cm->addEntityListener(Events::postLoad, 'Doctrine\Tests\Models\Company\CompanyContractListener', 'invalidMethod');
1358
    }
1359
1360 View Code Duplication
    public function testManyToManySelfReferencingNamingStrategyDefaults()
1361
    {
1362
        $cm = new ClassMetadata(CustomTypeParent::class, $this->metadataBuildingContext);
1363
        $cm->initializeReflection(new RuntimeReflectionService());
1364
1365
        $association = new Mapping\ManyToManyAssociationMetadata('friendsWithMe');
1366
1367
        $association->setTargetEntity(CustomTypeParent::class);
1368
1369
        $cm->addProperty($association);
1370
1371
        $association = $cm->getProperty('friendsWithMe');
1372
1373
        $joinColumns = [];
1374
1375
        $joinColumn = new Mapping\JoinColumnMetadata();
1376
1377
        $joinColumn->setColumnName("customtypeparent_source");
1378
        $joinColumn->setReferencedColumnName("id");
1379
        $joinColumn->setOnDelete("CASCADE");
1380
1381
        $joinColumns[] = $joinColumn;
1382
1383
        $inverseJoinColumns = [];
1384
1385
        $joinColumn = new Mapping\JoinColumnMetadata();
1386
1387
        $joinColumn->setColumnName("customtypeparent_target");
1388
        $joinColumn->setReferencedColumnName("id");
1389
        $joinColumn->setOnDelete("CASCADE");
1390
1391
        $inverseJoinColumns[] = $joinColumn;
1392
1393
        $joinTable = $association->getJoinTable();
1394
1395
        self::assertEquals('customtypeparent_customtypeparent', $joinTable->getName());
1396
        self::assertEquals($joinColumns, $joinTable->getJoinColumns());
1397
        self::assertEquals($inverseJoinColumns, $joinTable->getInverseJoinColumns());
1398
    }
1399
1400
    /**
1401
     * @group DDC-2662
1402
     */
1403
    public function testQuotedSequenceName()
1404
    {
1405
        $cm = new ClassMetadata(CMS\CmsUser::class, $this->metadataBuildingContext);
1406
        $cm->initializeReflection(new RuntimeReflectionService());
1407
1408
        $id = new Mapping\FieldMetadata('id');
1409
        $id->setValueGenerator(new Mapping\ValueGeneratorMetadata(
1410
            Mapping\GeneratorType::SEQUENCE,
1411
            [
1412
                'sequenceName' => 'foo',
1413
                'allocationSize' => 1,
1414
            ]
1415
        ));
1416
        $cm->addProperty($id);
1417
1418
        self::assertEquals(
1419
            ['sequenceName' => 'foo', 'allocationSize' => 1],
1420
            $cm->getProperty('id')->getValueGenerator()->getDefinition()
0 ignored issues
show
Bug introduced by
The method getValueGenerator() does not exist on Doctrine\ORM\Mapping\Property. Did you maybe mean getValue()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
1421
        );
1422
    }
1423
1424
    /**
1425
     * @group DDC-2700
1426
     */
1427
    public function testIsIdentifierMappedSuperClass()
1428
    {
1429
        $class = new ClassMetadata(DDC2700MappedSuperClass::class, $this->metadataBuildingContext);
1430
1431
        self::assertFalse($class->isIdentifier('foo'));
1432
    }
1433
1434
    /**
1435
     * @group embedded
1436
     */
1437
    public function testWakeupReflectionWithEmbeddableAndStaticReflectionService()
1438
    {
1439
        $metadata = new ClassMetadata(TestEntity1::class, $this->metadataBuildingContext);
1440
1441
        $metadata->mapEmbedded(
1442
            [
1443
                'fieldName'    => 'test',
1444
                'class'        => TestEntity1::class,
1445
                'columnPrefix' => false,
1446
            ]
1447
        );
1448
1449
        $fieldMetadata = new Mapping\FieldMetadata('test.embeddedProperty');
1450
        $fieldMetadata->setType(Type::getType('string'));
1451
1452
        $metadata->addProperty($fieldMetadata);
1453
1454
        /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1455
        $mapping = [
1456
            'originalClass' => TestEntity1::class,
1457
            'declaredField' => 'test',
1458
            'originalField' => 'embeddedProperty'
1459
        ];
1460
1461
        $metadata->addProperty('test.embeddedProperty', Type::getType('string'), $mapping);
1462
        */
1463
1464
        $metadata->wakeupReflection(new StaticReflectionService());
1465
1466
        self::assertEquals(
1467
            [
1468
                'test'                  => null,
1469
                'test.embeddedProperty' => null
1470
            ],
1471
            $metadata->getReflectionProperties()
0 ignored issues
show
Bug introduced by
The method getReflectionProperties() does not seem to exist on object<Doctrine\ORM\Mapping\ClassMetadata>.

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...
1472
        );
1473
    }
1474
}
1475
1476
/**
1477
 * @ORM\MappedSuperclass
1478
 */
1479
class DDC2700MappedSuperClass
1480
{
1481
    /** @ORM\Column */
1482
    private $foo;
0 ignored issues
show
Unused Code introduced by
The property $foo is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
1483
}
1484
1485
class MyNamespacedNamingStrategy extends DefaultNamingStrategy
1486
{
1487
    /**
1488
     * {@inheritdoc}
1489
     */
1490
    public function classToTableName($className)
1491
    {
1492
        if (strpos($className, '\\') !== false) {
1493
            $className = str_replace('\\', '_', str_replace('Doctrine\Tests\Models\\', '', $className));
1494
        }
1495
1496
        return strtolower($className);
1497
    }
1498
}
1499
1500
class MyPrefixNamingStrategy extends DefaultNamingStrategy
1501
{
1502
    /**
1503
     * {@inheritdoc}
1504
     */
1505
    public function propertyToColumnName($propertyName, $className = null)
1506
    {
1507
        return strtolower($this->classToTableName($className)) . '_' . $propertyName;
1508
    }
1509
}
1510