Passed
Pull Request — develop (#6935)
by Michael
503:01 queued 406:10
created

  A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 14
nc 1
nop 0
dl 0
loc 18
rs 9.4285
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\Common\EventManager;
8
use Doctrine\DBAL\Connection;
9
use Doctrine\DBAL\Types\Type;
10
use Doctrine\ORM\Configuration;
11
use Doctrine\ORM\EntityManagerInterface;
12
use Doctrine\ORM\Event\OnClassMetadataNotFoundEventArgs;
13
use Doctrine\ORM\Events;
14
use Doctrine\ORM\Sequencing\Generator;
15
use Doctrine\ORM\Mapping;
16
use Doctrine\ORM\Mapping\ClassMetadata;
17
use Doctrine\ORM\Mapping\ClassMetadataFactory;
18
use Doctrine\ORM\Mapping\Driver\MappingDriver;
19
use Doctrine\ORM\Mapping\MappingException;
20
use Doctrine\ORM\ORMException;
21
use Doctrine\ORM\Reflection\RuntimeReflectionService;
22
use Doctrine\Tests\Mocks\ConnectionMock;
23
use Doctrine\Tests\Mocks\DriverMock;
24
use Doctrine\Tests\Mocks\EntityManagerMock;
25
use Doctrine\Tests\Mocks\MetadataDriverMock;
26
use Doctrine\Tests\Models\CMS\CmsArticle;
27
use Doctrine\Tests\Models\CMS\CmsUser;
28
use Doctrine\Tests\Models\DDC4006\DDC4006User;
29
use Doctrine\Tests\Models\JoinedInheritanceType\AnotherChildClass;
30
use Doctrine\Tests\Models\JoinedInheritanceType\ChildClass;
31
use Doctrine\Tests\Models\JoinedInheritanceType\RootClass;
32
use Doctrine\Tests\Models\Quote;
33
use Doctrine\Tests\OrmTestCase;
34
use DoctrineGlobal_Article;
35
36
class ClassMetadataFactoryTest extends OrmTestCase
37
{
38
    public function testGetMetadataForSingleClass()
39
    {
40
        $mockDriver = new MetadataDriverMock();
41
        $entityManager = $this->createEntityManager($mockDriver);
42
43
        $conn = $entityManager->getConnection();
44
        $mockPlatform = $conn->getDatabasePlatform();
45
        $mockPlatform->setPrefersSequences(true);
0 ignored issues
show
Bug introduced by
The method setPrefersSequences() does not exist on Doctrine\DBAL\Platforms\AbstractPlatform. It seems like you code against a sub-type of Doctrine\DBAL\Platforms\AbstractPlatform such as Doctrine\Tests\Mocks\DatabasePlatformMock. ( Ignorable by Annotation )

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

45
        $mockPlatform->/** @scrutinizer ignore-call */ 
46
                       setPrefersSequences(true);
Loading history...
46
        $mockPlatform->setPrefersIdentityColumns(false);
0 ignored issues
show
Bug introduced by
The method setPrefersIdentityColumns() does not exist on Doctrine\DBAL\Platforms\AbstractPlatform. It seems like you code against a sub-type of Doctrine\DBAL\Platforms\AbstractPlatform such as Doctrine\Tests\Mocks\DatabasePlatformMock. ( Ignorable by Annotation )

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

46
        $mockPlatform->/** @scrutinizer ignore-call */ 
47
                       setPrefersIdentityColumns(false);
Loading history...
47
48
        $cm1 = $this->createValidClassMetadata();
49
50
        // SUT
51
        $cmf = new ClassMetadataFactory();
52
        $cmf->setEntityManager($entityManager);
53
        $cmf->setMetadataFor($cm1->getClassName(), $cm1);
54
55
        // Prechecks
56
        self::assertCount(0, $cm1->getAncestorsIterator());
57
        self::assertEquals(Mapping\InheritanceType::NONE, $cm1->inheritanceType);
58
        self::assertEquals(Mapping\GeneratorType::AUTO, $cm1->getProperty('id')->getValueGenerator()->getType());
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

58
        self::assertEquals(Mapping\GeneratorType::AUTO, $cm1->getProperty('id')->/** @scrutinizer ignore-call */ getValueGenerator()->getType());

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...
59
        self::assertTrue($cm1->hasField('name'));
60
        self::assertCount(4, $cm1->getDeclaredPropertiesIterator()); // 2 fields + 2 associations
61
        self::assertEquals('group', $cm1->table->getName());
62
63
        // Go
64
        $cmMap1 = $cmf->getMetadataFor($cm1->getClassName());
65
66
        self::assertSame($cm1, $cmMap1);
67
        self::assertEquals('group', $cmMap1->table->getName());
68
        self::assertCount(0, $cmMap1->getAncestorsIterator());
69
        self::assertTrue($cmMap1->hasField('name'));
70
    }
71
72
    public function testGetMetadataFor_ThrowsExceptionOnUnknownCustomGeneratorClass()
73
    {
74
        $cm1 = $this->createValidClassMetadata();
75
76
        $cm1->getProperty('id')->setValueGenerator(
0 ignored issues
show
Bug introduced by
The method setValueGenerator() does not exist on Doctrine\ORM\Mapping\Property. Did you maybe mean setValue()? ( Ignorable by Annotation )

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

76
        $cm1->getProperty('id')->/** @scrutinizer ignore-call */ setValueGenerator(

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...
77
            new Mapping\ValueGeneratorMetadata(
78
                Mapping\GeneratorType::CUSTOM,
79
                [
80
                    'class' => 'NotExistingGenerator',
81
                    'arguments' => [],
82
                ]
83
            )
84
        );
85
86
        $cmf = $this->createTestFactory();
87
88
        $cmf->setMetadataForClass($cm1->getClassName(), $cm1);
89
90
        $this->expectException(ORMException::class);
91
92
        $actual = $cmf->getMetadataFor($cm1->getClassName());
0 ignored issues
show
Unused Code introduced by
The assignment to $actual is dead and can be removed.
Loading history...
93
    }
94
95
    public function testGetMetadataFor_ThrowsExceptionOnMissingCustomGeneratorDefinition()
96
    {
97
        $cm1 = $this->createValidClassMetadata();
98
99
        $cm1->getProperty('id')->setValueGenerator(
100
            new Mapping\ValueGeneratorMetadata(Mapping\GeneratorType::CUSTOM)
101
        );
102
103
        $cmf = $this->createTestFactory();
104
105
        $cmf->setMetadataForClass($cm1->getClassName(), $cm1);
106
107
        $this->expectException(ORMException::class);
108
109
        $actual = $cmf->getMetadataFor($cm1->getClassName());
0 ignored issues
show
Unused Code introduced by
The assignment to $actual is dead and can be removed.
Loading history...
110
    }
111
112
    public function testHasGetMetadata_NamespaceSeparatorIsNotNormalized()
113
    {
114
        require_once __DIR__."/../../Models/Global/GlobalNamespaceModel.php";
115
116
        $metadataDriver = $this->createAnnotationDriver([__DIR__ . '/../../Models/Global/']);
117
118
        $entityManager = $this->createEntityManager($metadataDriver);
119
120
        $mf = $entityManager->getMetadataFactory();
121
122
        self::assertSame(
123
            $mf->getMetadataFor(DoctrineGlobal_Article::class),
124
            $mf->getMetadataFor('\\' . DoctrineGlobal_Article::class)
125
        );
126
        self::assertTrue($mf->hasMetadataFor(DoctrineGlobal_Article::class));
127
        self::assertTrue($mf->hasMetadataFor('\\' . DoctrineGlobal_Article::class));
128
    }
129
130
    /**
131
     * @group DDC-1512
132
     */
133
    public function testIsTransient()
134
    {
135
        $cmf = new ClassMetadataFactory();
0 ignored issues
show
Unused Code introduced by
The assignment to $cmf is dead and can be removed.
Loading history...
136
        $driver = $this->createMock(MappingDriver::class);
137
        $driver->expects($this->at(0))
138
               ->method('isTransient')
139
               ->with($this->equalTo(CmsUser::class))
0 ignored issues
show
Bug introduced by
$this->equalTo(Doctrine\...els\CMS\CmsUser::class) of type PHPUnit\Framework\Constraint\IsEqual is incompatible with the type array expected by parameter $arguments of PHPUnit\Framework\MockOb...nvocationMocker::with(). ( Ignorable by Annotation )

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

139
               ->with(/** @scrutinizer ignore-type */ $this->equalTo(CmsUser::class))
Loading history...
140
               ->will($this->returnValue(true));
141
        $driver->expects($this->at(1))
142
               ->method('isTransient')
143
               ->with($this->equalTo(CmsArticle::class))
144
               ->will($this->returnValue(false));
145
146
        $em = $this->createEntityManager($driver);
147
148
        self::assertTrue($em->getMetadataFactory()->isTransient(CmsUser::class));
149
        self::assertFalse($em->getMetadataFactory()->isTransient(CmsArticle::class));
150
    }
151
152
    public function testAddDefaultDiscriminatorMap()
153
    {
154
        $cmf = new ClassMetadataFactory();
155
        $driver = $this->createAnnotationDriver([__DIR__ . '/../../Models/JoinedInheritanceType/']);
156
        $em = $this->createEntityManager($driver);
157
        $cmf->setEntityManager($em);
158
159
        $rootMetadata = $cmf->getMetadataFor(RootClass::class);
160
        $childMetadata = $cmf->getMetadataFor(ChildClass::class);
161
        $anotherChildMetadata = $cmf->getMetadataFor(AnotherChildClass::class);
162
        $rootDiscriminatorMap = $rootMetadata->discriminatorMap;
163
        $childDiscriminatorMap = $childMetadata->discriminatorMap;
164
        $anotherChildDiscriminatorMap = $anotherChildMetadata->discriminatorMap;
165
166
        $rootClass = RootClass::class;
167
        $childClass = ChildClass::class;
168
        $anotherChildClass = AnotherChildClass::class;
169
170
        $rootClassKey = array_search($rootClass, $rootDiscriminatorMap);
171
        $childClassKey = array_search($childClass, $rootDiscriminatorMap);
172
        $anotherChildClassKey = array_search($anotherChildClass, $rootDiscriminatorMap);
173
174
        self::assertEquals('rootclass', $rootClassKey);
175
        self::assertEquals('childclass', $childClassKey);
176
        self::assertEquals('anotherchildclass', $anotherChildClassKey);
177
178
        self::assertEquals($childDiscriminatorMap, $rootDiscriminatorMap);
179
        self::assertEquals($anotherChildDiscriminatorMap, $rootDiscriminatorMap);
180
181
        // ClassMetadataFactory::addDefaultDiscriminatorMap shouldn't be called again, because the
182
        // discriminator map is already cached
183
        $cmf = $this->getMockBuilder(ClassMetadataFactory::class)->setMethods(['addDefaultDiscriminatorMap'])->getMock();
184
        $cmf->setEntityManager($em);
1 ignored issue
show
Bug introduced by
The method setEntityManager() does not exist on PHPUnit\Framework\MockObject\MockObject. ( Ignorable by Annotation )

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

184
        $cmf->/** @scrutinizer ignore-call */ 
185
              setEntityManager($em);

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...
185
        $cmf->expects($this->never())
186
            ->method('addDefaultDiscriminatorMap');
187
188
        $rootMetadata = $cmf->getMetadataFor(RootClass::class);
1 ignored issue
show
Bug introduced by
The method getMetadataFor() does not exist on PHPUnit\Framework\MockObject\MockObject. ( Ignorable by Annotation )

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

188
        /** @scrutinizer ignore-call */ 
189
        $rootMetadata = $cmf->getMetadataFor(RootClass::class);

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...
Unused Code introduced by
The assignment to $rootMetadata is dead and can be removed.
Loading history...
189
    }
190
191
    public function testGetAllMetadataWorksWithBadConnection()
192
    {
193
        // DDC-3551
194
        $conn = $this->createMock(Connection::class);
195
        $mockDriver    = new MetadataDriverMock();
196
        $conn->expects($this->any())
197
            ->method('getEventManager')
198
            ->willReturn(new EventManager());
199
        $em = $this->createEntityManager($mockDriver, $conn);
200
201
        $conn->expects($this->any())
202
            ->method('getDatabasePlatform')
203
            ->will($this->throwException(new \Exception('Exception thrown in test when calling getDatabasePlatform')));
204
205
        $cmf = new ClassMetadataFactory();
206
        $cmf->setEntityManager($em);
207
208
        // getting all the metadata should work, even if get DatabasePlatform blows up
209
        $metadata = $cmf->getAllMetadata();
210
        // this will just be an empty array - there was no error
211
        self::assertEquals([], $metadata);
212
    }
213
214
    protected function createEntityManager($metadataDriver, $conn = null)
215
    {
216
        $driverMock = new DriverMock();
217
        $config = new Configuration();
218
219
        $config->setProxyDir(__DIR__ . '/../../Proxies');
220
        $config->setProxyNamespace('Doctrine\Tests\Proxies');
221
222
        if (!$conn) {
223
            $conn = new ConnectionMock([], $driverMock, $config, new EventManager());
224
        }
225
        $eventManager = $conn->getEventManager();
226
227
        $config->setMetadataDriverImpl($metadataDriver);
228
229
        return EntityManagerMock::create($conn, $config, $eventManager);
230
    }
231
232
    /**
233
     * @return ClassMetadataFactoryTestSubject
234
     */
235
    protected function createTestFactory()
236
    {
237
        $mockDriver = new MetadataDriverMock();
238
        $entityManager = $this->createEntityManager($mockDriver);
239
        $cmf = new ClassMetadataFactoryTestSubject();
240
        $cmf->setEntityManager($entityManager);
241
        return $cmf;
242
    }
243
244
    /**
245
     * @param string $class
246
     * @return ClassMetadata
247
     */
248
    protected function createValidClassMetadata()
249
    {
250
        // Self-made metadata
251
        $metadataBuildingContext = new Mapping\ClassMetadataBuildingContext(
252
            $this->createMock(ClassMetadataFactory::class),
253
            new RuntimeReflectionService()
254
        );
255
256
        $cm1 = new ClassMetadata(TestEntity1::class, $metadataBuildingContext);
257
258
        $tableMetadata = new Mapping\TableMetadata();
259
        $tableMetadata->setName('group');
260
261
        $cm1->setTable($tableMetadata);
262
263
        // Add a mapped field
264
        $fieldMetadata = new Mapping\FieldMetadata('id');
265
266
        $fieldMetadata->setType(Type::getType('integer'));
267
        $fieldMetadata->setPrimaryKey(true);
268
        $fieldMetadata->setValueGenerator(new Mapping\ValueGeneratorMetadata(Mapping\GeneratorType::AUTO));
269
270
        $cm1->addProperty($fieldMetadata);
271
272
        // Add a mapped field
273
        $fieldMetadata = new Mapping\FieldMetadata('name');
274
275
        $fieldMetadata->setType(Type::getType('string'));
276
277
        $cm1->addProperty($fieldMetadata);
278
279
        // and a mapped association
280
        $association = new Mapping\OneToOneAssociationMetadata('other');
281
282
        $association->setTargetEntity(TestEntity1::class);
283
        $association->setMappedBy('this');
284
285
        $cm1->addProperty($association);
286
287
        // and an association on the owning side
288
        $joinColumns = [];
289
290
        $joinColumn = new Mapping\JoinColumnMetadata();
291
292
        $joinColumn->setColumnName("other_id");
293
        $joinColumn->setReferencedColumnName("id");
294
295
        $joinColumns[] = $joinColumn;
296
297
        $association = new Mapping\OneToOneAssociationMetadata('association');
298
299
        $association->setJoinColumns($joinColumns);
300
        $association->setTargetEntity(TestEntity1::class);
301
302
        $cm1->addProperty($association);
303
304
        return $cm1;
305
    }
306
307
    /**
308
     * @group DDC-1845
309
     */
310
    public function testQuoteMetadata()
311
    {
312
        $cmf    = new ClassMetadataFactory();
313
        $driver = $this->createAnnotationDriver([__DIR__ . '/../../Models/Quote/']);
314
        $em     = $this->createEntityManager($driver);
315
        $cmf->setEntityManager($em);
316
317
        $userMetadata       = $cmf->getMetadataFor(Quote\User::class);
318
        $phoneMetadata      = $cmf->getMetadataFor(Quote\Phone::class);
319
        $groupMetadata      = $cmf->getMetadataFor(Quote\Group::class);
320
        $addressMetadata    = $cmf->getMetadataFor(Quote\Address::class);
321
322
        // Phone Class Metadata
323
        self::assertNotNull($phoneMetadata->getProperty('number'));
324
        self::assertEquals('phone-number', $phoneMetadata->getProperty('number')->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

324
        self::assertEquals('phone-number', $phoneMetadata->getProperty('number')->/** @scrutinizer ignore-call */ getColumnName());
Loading history...
325
326
        $user                = $phoneMetadata->getProperty('user');
327
        $userJoinColumns     = $user->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

327
        /** @scrutinizer ignore-call */ 
328
        $userJoinColumns     = $user->getJoinColumns();
Loading history...
328
        $phoneUserJoinColumn = reset($userJoinColumns);
329
330
        self::assertEquals('user-id', $phoneUserJoinColumn->getColumnName());
331
        self::assertEquals('user-id', $phoneUserJoinColumn->getReferencedColumnName());
332
333
        // Address Class Metadata
334
        self::assertNotNull($addressMetadata->getProperty('id'));
335
        self::assertNotNull($addressMetadata->getProperty('zip'));
336
        self::assertEquals('address-id', $addressMetadata->getProperty('id')->getColumnName());
337
        self::assertEquals('address-zip', $addressMetadata->getProperty('zip')->getColumnName());
338
339
        // User Class Metadata
340
        self::assertNotNull($userMetadata->getProperty('id'));
341
        self::assertNotNull($userMetadata->getProperty('name'));
342
        self::assertEquals('user-id', $userMetadata->getProperty('id')->getColumnName());
343
        self::assertEquals('user-name', $userMetadata->getProperty('name')->getColumnName());
344
345
        $group               = $groupMetadata->getProperty('parent');
346
        $groupJoinColumns    = $group->getJoinColumns();
347
        $groupUserJoinColumn = reset($groupJoinColumns);
348
349
        self::assertEquals('parent-id', $groupUserJoinColumn->getColumnName());
350
        self::assertEquals('group-id', $groupUserJoinColumn->getReferencedColumnName());
351
352
        $user                  = $addressMetadata->getProperty('user');
353
        $userJoinColumns       = $user->getJoinColumns();
354
        $addressUserJoinColumn = reset($userJoinColumns);
355
356
        self::assertEquals('user-id', $addressUserJoinColumn->getColumnName());
357
        self::assertEquals('user-id', $addressUserJoinColumn->getReferencedColumnName());
358
359
        $address               = $userMetadata->getProperty('address');
360
        $addressJoinColumns    = $address->getJoinColumns();
361
        $userAddressJoinColumn = reset($addressJoinColumns);
362
363
        self::assertEquals('address-id', $userAddressJoinColumn->getColumnName());
364
        self::assertEquals('address-id', $userAddressJoinColumn->getReferencedColumnName());
365
366
        $groups                       = $userMetadata->getProperty('groups');
367
        $groupsJoinTable              = $groups->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

367
        /** @scrutinizer ignore-call */ 
368
        $groupsJoinTable              = $groups->getJoinTable();
Loading history...
368
        $userGroupsJoinColumns        = $groupsJoinTable->getJoinColumns();
369
        $userGroupsJoinColumn         = reset($userGroupsJoinColumns);
370
        $userGroupsInverseJoinColumns = $groupsJoinTable->getInverseJoinColumns();
371
        $userGroupsInverseJoinColumn  = reset($userGroupsInverseJoinColumns);
372
373
        self::assertEquals('quote-users-groups', $groupsJoinTable->getName());
374
        self::assertEquals('user-id', $userGroupsJoinColumn->getColumnName());
375
        self::assertEquals('user-id', $userGroupsJoinColumn->getReferencedColumnName());
376
        self::assertEquals('group-id', $userGroupsInverseJoinColumn->getColumnName());
377
        self::assertEquals('group-id', $userGroupsInverseJoinColumn->getReferencedColumnName());
378
    }
379
380
    /**
381
     * @group DDC-3385
382
     * @group 1181
383
     * @group 385
384
     */
385
    public function testFallbackLoadingCausesEventTriggeringThatCanModifyFetchedMetadata()
386
    {
387
        $test          = $this;
388
389
        /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadata */
390
        $metadata      = $this->createMock(ClassMetadata::class);
391
        $cmf           = new ClassMetadataFactory();
392
        $mockDriver    = new MetadataDriverMock();
393
        $em            = $this->createEntityManager($mockDriver);
394
        $listener      = $this->getMockBuilder(\stdClass::class)->setMethods(['onClassMetadataNotFound'])->getMock();
395
        $eventManager  = $em->getEventManager();
396
397
        $cmf->setEntityManager($em);
398
399
        $listener
400
            ->expects($this->any())
401
            ->method('onClassMetadataNotFound')
402
            ->will($this->returnCallback(function (OnClassMetadataNotFoundEventArgs $args) use ($metadata, $em, $test) {
403
                $test->assertNull($args->getFoundMetadata());
404
                $test->assertSame('Foo', $args->getClassName());
405
                $test->assertSame($em, $args->getObjectManager());
406
407
                $args->setFoundMetadata($metadata);
408
            }));
409
410
        $eventManager->addEventListener([Events::onClassMetadataNotFound], $listener);
411
412
        self::assertSame($metadata, $cmf->getMetadataFor('Foo'));
413
    }
414
415
    /**
416
     * @group DDC-3427
417
     */
418
    public function testAcceptsEntityManagerInterfaceInstances()
419
    {
420
        $classMetadataFactory = new ClassMetadataFactory();
421
422
        /* @var EntityManagerInterface EntityManager */
423
        $entityManager        = $this->createMock(EntityManagerInterface::class);
424
425
        $classMetadataFactory->setEntityManager($entityManager);
426
427
        // not really the cleanest way to check it, but we won't add a getter to the CMF just for the sake of testing.
428
        self::assertAttributeSame($entityManager, 'em', $classMetadataFactory);
429
    }
430
431
    /**
432
     * @group embedded
433
     * @group DDC-3305
434
     */
435
    public function testRejectsEmbeddableWithoutValidClassName()
436
    {
437
        $metadata = $this->createValidClassMetadata();
438
439
        $metadata->mapEmbedded(
440
            [
441
            'fieldName'    => 'embedded',
442
            'class'        => '',
443
            'columnPrefix' => false,
444
            ]
445
        );
446
447
        $cmf = $this->createTestFactory();
448
449
        $cmf->setMetadataForClass($metadata->getClassName(), $metadata);
450
451
        $this->expectException(MappingException::class);
452
        $this->expectExceptionMessage('The embed mapping \'embedded\' misses the \'class\' attribute.');
453
454
        $cmf->getMetadataFor($metadata->getClassName());
455
    }
456
457
    /**
458
     * @group embedded
459
     * @group DDC-4006
460
     */
461
    public function testInheritsIdGeneratorMappingFromEmbeddable()
462
    {
463
        $cmf = new ClassMetadataFactory();
464
        $driver = $this->createAnnotationDriver([__DIR__ . '/../../Models/DDC4006/']);
465
        $em = $this->createEntityManager($driver);
466
        $cmf->setEntityManager($em);
467
468
        $userMetadata = $cmf->getMetadataFor(DDC4006User::class);
469
470
        self::assertTrue($userMetadata->isIdGeneratorIdentity());
0 ignored issues
show
Bug introduced by
The method isIdGeneratorIdentity() 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

470
        self::assertTrue($userMetadata->/** @scrutinizer ignore-call */ isIdGeneratorIdentity());

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...
471
    }
472
}
473
474
/* Test subject class with overridden factory method for mocking purposes */
475
class ClassMetadataFactoryTestSubject extends ClassMetadataFactory
476
{
477
    private $mockMetadata = [];
478
    private $requestedClasses = [];
479
480
    protected function newClassMetadataInstance(
481
        string $className,
482
        ?Mapping\ClassMetadata $parent,
0 ignored issues
show
Unused Code introduced by
The parameter $parent is not used and could be removed. ( Ignorable by Annotation )

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

482
        /** @scrutinizer ignore-unused */ ?Mapping\ClassMetadata $parent,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
483
        Mapping\ClassMetadataBuildingContext $metadataBuildingContext
0 ignored issues
show
Unused Code introduced by
The parameter $metadataBuildingContext is not used and could be removed. ( Ignorable by Annotation )

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

483
        /** @scrutinizer ignore-unused */ Mapping\ClassMetadataBuildingContext $metadataBuildingContext

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
484
    ) : ClassMetadata
485
    {
486
        $this->requestedClasses[] = $className;
487
488
        if ( ! isset($this->mockMetadata[$className])) {
489
            throw new \InvalidArgumentException("No mock metadata found for class $className.");
490
        }
491
492
        return $this->mockMetadata[$className];
493
    }
494
495
    public function setMetadataForClass($className, $metadata)
496
    {
497
        $this->mockMetadata[$className] = $metadata;
498
    }
499
500
    public function getRequestedClasses()
501
    {
502
        return $this->requestedClasses;
503
    }
504
}
505
506
class TestEntity1
507
{
508
    private $id;
0 ignored issues
show
introduced by
The private property $id is not used, and could be removed.
Loading history...
509
    private $name;
0 ignored issues
show
introduced by
The private property $name is not used, and could be removed.
Loading history...
510
    private $other;
0 ignored issues
show
introduced by
The private property $other is not used, and could be removed.
Loading history...
511
    private $association;
0 ignored issues
show
introduced by
The private property $association is not used, and could be removed.
Loading history...
512
    private $embedded;
0 ignored issues
show
introduced by
The private property $embedded is not used, and could be removed.
Loading history...
513
}
514
515
class CustomIdGenerator implements Generator
516
{
517
    /**
518
     * {@inheritdoc}
519
     */
520
    public function generate(EntityManagerInterface $em, $entity): \Generator
521
    {
522
    }
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return Generator. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
523
524
    /**
525
     * {@inheritdoc}
526
     */
527
    public function isPostInsertGenerator()
528
    {
529
        return false;
530
    }
531
}
532