Failed Conditions
Push — master ( 6744b4...2b8acb )
by Marco
60:45 queued 60:36
created

ClassMetadataFactoryTest   B

Complexity

Total Complexity 18

Size/Duplication

Total Lines 422
Duplicated Lines 8.29 %

Coupling/Cohesion

Components 1
Dependencies 17

Importance

Changes 0
Metric Value
wmc 18
lcom 1
cbo 17
dl 35
loc 422
rs 7.8571
c 0
b 0
f 0

17 Methods

Rating   Name   Duplication   Size   Complexity  
B testGetMetadataForSingleClass() 0 34 1
A testGetMetadataFor_ReturnsLoadedCustomIdGenerator() 0 13 1
A testHasGetMetadata_NamespaceSeparatorIsNotNormalized() 0 18 1
A testIsTransient() 0 18 1
A testIsTransientEntityNamespace() 0 19 1
B testAddDefaultDiscriminatorMap() 0 38 1
A testGetAllMetadataWorksWithBadConnection() 0 19 1
A _createTestFactory() 0 8 1
A _createValidClassMetadata() 0 23 1
B testQuoteMetadata() 0 76 1
B testFallbackLoadingCausesEventTriggeringThatCanModifyFetchedMetadata() 0 28 1
A testAcceptsEntityManagerInterfaceInstances() 0 12 1
A testRejectsEmbeddableWithoutValidClassName() 0 21 1
A testInheritsIdGeneratorMappingFromEmbeddable() 0 11 1
A testGetMetadataFor_ThrowsExceptionOnUnknownCustomGeneratorClass() 11 11 1
A testGetMetadataFor_ThrowsExceptionOnMissingCustomGeneratorDefinition() 10 10 1
A _createEntityManager() 14 14 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace Doctrine\Tests\ORM\Mapping;
4
5
use Doctrine\Common\EventManager;
6
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver;
7
use Doctrine\Common\Persistence\Mapping\RuntimeReflectionService;
8
use Doctrine\DBAL\Connection;
9
use Doctrine\ORM\Configuration;
10
use Doctrine\ORM\EntityManager;
11
use Doctrine\ORM\EntityManagerInterface;
12
use Doctrine\ORM\Event\OnClassMetadataNotFoundEventArgs;
13
use Doctrine\ORM\Events;
14
use Doctrine\ORM\Id\AbstractIdGenerator;
15
use Doctrine\ORM\Mapping\ClassMetadata;
16
use Doctrine\ORM\Mapping\ClassMetadataFactory;
17
use Doctrine\ORM\Mapping\MappingException;
18
use Doctrine\ORM\ORMException;
19
use Doctrine\Tests\Mocks\ConnectionMock;
20
use Doctrine\Tests\Mocks\DriverMock;
21
use Doctrine\Tests\Mocks\EntityManagerMock;
22
use Doctrine\Tests\Mocks\MetadataDriverMock;
23
use Doctrine\Tests\Models\CMS\CmsArticle;
24
use Doctrine\Tests\Models\CMS\CmsUser;
25
use Doctrine\Tests\Models\DDC4006\DDC4006User;
26
use Doctrine\Tests\Models\JoinedInheritanceType\AnotherChildClass;
27
use Doctrine\Tests\Models\JoinedInheritanceType\ChildClass;
28
use Doctrine\Tests\Models\JoinedInheritanceType\RootClass;
29
use Doctrine\Tests\Models\Quote;
30
use Doctrine\Tests\OrmTestCase;
31
use DoctrineGlobal_Article;
32
33
class ClassMetadataFactoryTest extends OrmTestCase
34
{
35
    public function testGetMetadataForSingleClass()
36
    {
37
        $mockDriver = new MetadataDriverMock();
38
        $entityManager = $this->_createEntityManager($mockDriver);
39
40
        $conn = $entityManager->getConnection();
41
        $mockPlatform = $conn->getDatabasePlatform();
42
        $mockPlatform->setPrefersSequences(true);
0 ignored issues
show
Bug introduced by
The method setPrefersSequences() does not exist on Doctrine\DBAL\Platforms\AbstractPlatform. Did you maybe mean prefersSequences()?

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...
43
        $mockPlatform->setPrefersIdentityColumns(false);
0 ignored issues
show
Bug introduced by
The method setPrefersIdentityColumns() does not exist on Doctrine\DBAL\Platforms\AbstractPlatform. Did you maybe mean prefersIdentityColumns()?

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...
44
45
        $cm1 = $this->_createValidClassMetadata();
46
47
        // SUT
48
        $cmf = new ClassMetadataFactory();
49
        $cmf->setEntityManager($entityManager);
50
        $cmf->setMetadataFor($cm1->name, $cm1);
51
52
        // Prechecks
53
        $this->assertEquals([], $cm1->parentClasses);
54
        $this->assertEquals(ClassMetadata::INHERITANCE_TYPE_NONE, $cm1->inheritanceType);
55
        $this->assertTrue($cm1->hasField('name'));
56
        $this->assertEquals(2, count($cm1->associationMappings));
57
        $this->assertEquals(ClassMetadata::GENERATOR_TYPE_AUTO, $cm1->generatorType);
58
        $this->assertEquals('group', $cm1->table['name']);
59
60
        // Go
61
        $cmMap1 = $cmf->getMetadataFor($cm1->name);
62
63
        $this->assertSame($cm1, $cmMap1);
64
        $this->assertEquals('group', $cmMap1->table['name']);
0 ignored issues
show
Bug introduced by
Accessing table on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
65
        $this->assertTrue($cmMap1->table['quoted']);
0 ignored issues
show
Bug introduced by
Accessing table on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
66
        $this->assertEquals([], $cmMap1->parentClasses);
0 ignored issues
show
Bug introduced by
Accessing parentClasses on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
67
        $this->assertTrue($cmMap1->hasField('name'));
68
    }
69
70
    public function testGetMetadataFor_ReturnsLoadedCustomIdGenerator()
71
    {
72
        $cm1 = $this->_createValidClassMetadata();
73
        $cm1->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_CUSTOM);
74
        $cm1->customGeneratorDefinition = ['class' => CustomIdGenerator::class];
75
        $cmf = $this->_createTestFactory();
76
        $cmf->setMetadataForClass($cm1->name, $cm1);
77
78
        $actual = $cmf->getMetadataFor($cm1->name);
79
80
        $this->assertEquals(ClassMetadata::GENERATOR_TYPE_CUSTOM, $actual->generatorType);
0 ignored issues
show
Bug introduced by
Accessing generatorType on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
81
        $this->assertInstanceOf(CustomIdGenerator::class, $actual->idGenerator);
0 ignored issues
show
Bug introduced by
Accessing idGenerator on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
82
    }
83
84 View Code Duplication
    public function testGetMetadataFor_ThrowsExceptionOnUnknownCustomGeneratorClass()
85
    {
86
        $cm1 = $this->_createValidClassMetadata();
87
        $cm1->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_CUSTOM);
88
        $cm1->customGeneratorDefinition = ["class" => "NotExistingGenerator"];
89
        $cmf = $this->_createTestFactory();
90
        $cmf->setMetadataForClass($cm1->name, $cm1);
91
        $this->expectException(ORMException::class);
92
93
        $actual = $cmf->getMetadataFor($cm1->name);
0 ignored issues
show
Unused Code introduced by
$actual 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...
94
    }
95
96 View Code Duplication
    public function testGetMetadataFor_ThrowsExceptionOnMissingCustomGeneratorDefinition()
97
    {
98
        $cm1 = $this->_createValidClassMetadata();
99
        $cm1->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_CUSTOM);
100
        $cmf = $this->_createTestFactory();
101
        $cmf->setMetadataForClass($cm1->name, $cm1);
102
        $this->expectException(ORMException::class);
103
104
        $actual = $cmf->getMetadataFor($cm1->name);
0 ignored issues
show
Unused Code introduced by
$actual 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...
105
    }
106
107
    public function testHasGetMetadata_NamespaceSeparatorIsNotNormalized()
108
    {
109
        require_once __DIR__."/../../Models/Global/GlobalNamespaceModel.php";
110
111
        $metadataDriver = $this->createAnnotationDriver([__DIR__ . '/../../Models/Global/']);
112
113
        $entityManager = $this->_createEntityManager($metadataDriver);
114
115
        $mf = $entityManager->getMetadataFactory();
116
        $m1 = $mf->getMetadataFor(DoctrineGlobal_Article::class);
117
        $h1 = $mf->hasMetadataFor(DoctrineGlobal_Article::class);
118
        $h2 = $mf->hasMetadataFor('\\' . DoctrineGlobal_Article::class);
119
        $m2 = $mf->getMetadataFor('\\' . DoctrineGlobal_Article::class);
120
121
        $this->assertNotSame($m1, $m2);
122
        $this->assertFalse($h2);
123
        $this->assertTrue($h1);
124
    }
125
126
    /**
127
     * @group DDC-1512
128
     */
129
    public function testIsTransient()
130
    {
131
        $cmf = new ClassMetadataFactory();
0 ignored issues
show
Unused Code introduced by
$cmf 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...
132
        $driver = $this->createMock(MappingDriver::class);
133
        $driver->expects($this->at(0))
134
               ->method('isTransient')
135
               ->with($this->equalTo(CmsUser::class))
136
               ->will($this->returnValue(true));
137
        $driver->expects($this->at(1))
138
               ->method('isTransient')
139
               ->with($this->equalTo(CmsArticle::class))
140
               ->will($this->returnValue(false));
141
142
        $em = $this->_createEntityManager($driver);
143
144
        $this->assertTrue($em->getMetadataFactory()->isTransient(CmsUser::class));
145
        $this->assertFalse($em->getMetadataFactory()->isTransient(CmsArticle::class));
146
    }
147
148
    /**
149
     * @group DDC-1512
150
     */
151
    public function testIsTransientEntityNamespace()
152
    {
153
        $cmf = new ClassMetadataFactory();
0 ignored issues
show
Unused Code introduced by
$cmf 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...
154
        $driver = $this->createMock(MappingDriver::class);
155
        $driver->expects($this->at(0))
156
               ->method('isTransient')
157
               ->with($this->equalTo(CmsUser::class))
158
               ->will($this->returnValue(true));
159
        $driver->expects($this->at(1))
160
               ->method('isTransient')
161
               ->with($this->equalTo(CmsArticle::class))
162
               ->will($this->returnValue(false));
163
164
        $em = $this->_createEntityManager($driver);
165
        $em->getConfiguration()->addEntityNamespace('CMS', 'Doctrine\Tests\Models\CMS');
166
167
        $this->assertTrue($em->getMetadataFactory()->isTransient('CMS:CmsUser'));
168
        $this->assertFalse($em->getMetadataFactory()->isTransient('CMS:CmsArticle'));
169
    }
170
171
    public function testAddDefaultDiscriminatorMap()
172
    {
173
        $cmf = new ClassMetadataFactory();
174
        $driver = $this->createAnnotationDriver([__DIR__ . '/../../Models/JoinedInheritanceType/']);
175
        $em = $this->_createEntityManager($driver);
176
        $cmf->setEntityManager($em);
177
178
        $rootMetadata = $cmf->getMetadataFor(RootClass::class);
179
        $childMetadata = $cmf->getMetadataFor(ChildClass::class);
180
        $anotherChildMetadata = $cmf->getMetadataFor(AnotherChildClass::class);
181
        $rootDiscriminatorMap = $rootMetadata->discriminatorMap;
0 ignored issues
show
Bug introduced by
Accessing discriminatorMap on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
182
        $childDiscriminatorMap = $childMetadata->discriminatorMap;
0 ignored issues
show
Bug introduced by
Accessing discriminatorMap on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
183
        $anotherChildDiscriminatorMap = $anotherChildMetadata->discriminatorMap;
0 ignored issues
show
Bug introduced by
Accessing discriminatorMap on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
184
185
        $rootClass = RootClass::class;
186
        $childClass = ChildClass::class;
187
        $anotherChildClass = AnotherChildClass::class;
188
189
        $rootClassKey = array_search($rootClass, $rootDiscriminatorMap);
190
        $childClassKey = array_search($childClass, $rootDiscriminatorMap);
191
        $anotherChildClassKey = array_search($anotherChildClass, $rootDiscriminatorMap);
192
193
        $this->assertEquals('rootclass', $rootClassKey);
194
        $this->assertEquals('childclass', $childClassKey);
195
        $this->assertEquals('anotherchildclass', $anotherChildClassKey);
196
197
        $this->assertEquals($childDiscriminatorMap, $rootDiscriminatorMap);
198
        $this->assertEquals($anotherChildDiscriminatorMap, $rootDiscriminatorMap);
199
200
        // ClassMetadataFactory::addDefaultDiscriminatorMap shouldn't be called again, because the
201
        // discriminator map is already cached
202
        $cmf = $this->getMockBuilder(ClassMetadataFactory::class)->setMethods(['addDefaultDiscriminatorMap'])->getMock();
203
        $cmf->setEntityManager($em);
204
        $cmf->expects($this->never())
205
            ->method('addDefaultDiscriminatorMap');
206
207
        $rootMetadata = $cmf->getMetadataFor(RootClass::class);
0 ignored issues
show
Unused Code introduced by
$rootMetadata 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...
208
    }
209
210
    public function testGetAllMetadataWorksWithBadConnection()
211
    {
212
        // DDC-3551
213
        $conn = $this->createMock(Connection::class);
214
        $mockDriver    = new MetadataDriverMock();
215
        $em = $this->_createEntityManager($mockDriver, $conn);
216
217
        $conn->expects($this->any())
218
            ->method('getDatabasePlatform')
219
            ->will($this->throwException(new \Exception('Exception thrown in test when calling getDatabasePlatform')));
220
221
        $cmf = new ClassMetadataFactory();
222
        $cmf->setEntityManager($em);
223
224
        // getting all the metadata should work, even if get DatabasePlatform blows up
225
        $metadata = $cmf->getAllMetadata();
226
        // this will just be an empty array - there was no error
227
        $this->assertEquals([], $metadata);
228
    }
229
230 View Code Duplication
    protected function _createEntityManager($metadataDriver, $conn = null)
231
    {
232
        $driverMock = new DriverMock();
233
        $config = new Configuration();
234
        $config->setProxyDir(__DIR__ . '/../../Proxies');
235
        $config->setProxyNamespace('Doctrine\Tests\Proxies');
236
        $eventManager = new EventManager();
237
        if (!$conn) {
238
            $conn = new ConnectionMock([], $driverMock, $config, $eventManager);
239
        }
240
        $config->setMetadataDriverImpl($metadataDriver);
241
242
        return EntityManagerMock::create($conn, $config, $eventManager);
243
    }
244
245
    /**
246
     * @return ClassMetadataFactoryTestSubject
247
     */
248
    protected function _createTestFactory()
249
    {
250
        $mockDriver = new MetadataDriverMock();
251
        $entityManager = $this->_createEntityManager($mockDriver);
252
        $cmf = new ClassMetadataFactoryTestSubject();
253
        $cmf->setEntityManager($entityManager);
254
        return $cmf;
255
    }
256
257
    /**
258
     * @param string $class
0 ignored issues
show
Bug introduced by
There is no parameter named $class. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
259
     * @return ClassMetadata
260
     */
261
    protected function _createValidClassMetadata()
262
    {
263
        // Self-made metadata
264
        $cm1 = new ClassMetadata(TestEntity1::class);
265
        $cm1->initializeReflection(new RuntimeReflectionService());
266
        $cm1->setPrimaryTable(['name' => '`group`']);
267
        // Add a mapped field
268
        $cm1->mapField(['fieldName' => 'name', 'type' => 'string']);
269
        // Add a mapped field
270
        $cm1->mapField(['fieldName' => 'id', 'type' => 'integer', 'id' => true]);
271
        // and a mapped association
272
        $cm1->mapOneToOne(['fieldName' => 'other', 'targetEntity' => 'TestEntity1', 'mappedBy' => 'this']);
273
        // and an association on the owning side
274
        $joinColumns = [
275
            ['name' => 'other_id', 'referencedColumnName' => 'id']
276
        ];
277
        $cm1->mapOneToOne(
278
            ['fieldName' => 'association', 'targetEntity' => 'TestEntity1', 'joinColumns' => $joinColumns]
279
        );
280
        // and an id generator type
281
        $cm1->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_AUTO);
282
        return $cm1;
283
    }
284
285
    /**
286
    * @group DDC-1845
287
    */
288
    public function testQuoteMetadata()
289
    {
290
        $cmf    = new ClassMetadataFactory();
291
        $driver = $this->createAnnotationDriver([__DIR__ . '/../../Models/Quote/']);
292
        $em     = $this->_createEntityManager($driver);
293
        $cmf->setEntityManager($em);
294
295
296
        $userMetadata       = $cmf->getMetadataFor(Quote\User::class);
297
        $phoneMetadata      = $cmf->getMetadataFor(Quote\Phone::class);
298
        $groupMetadata      = $cmf->getMetadataFor(Quote\Group::class);
299
        $addressMetadata    = $cmf->getMetadataFor(Quote\Address::class);
300
301
302
        // Phone Class Metadata
303
        $this->assertTrue($phoneMetadata->fieldMappings['number']['quoted']);
0 ignored issues
show
Bug introduced by
Accessing fieldMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
304
        $this->assertEquals('phone-number', $phoneMetadata->fieldMappings['number']['columnName']);
0 ignored issues
show
Bug introduced by
Accessing fieldMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
305
306
        $user = $phoneMetadata->associationMappings['user'];
0 ignored issues
show
Bug introduced by
Accessing associationMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
307
        $this->assertTrue($user['joinColumns'][0]['quoted']);
308
        $this->assertEquals('user-id', $user['joinColumns'][0]['name']);
309
        $this->assertEquals('user-id', $user['joinColumns'][0]['referencedColumnName']);
310
311
312
313
        // User Group Metadata
314
        $this->assertTrue($groupMetadata->fieldMappings['id']['quoted']);
0 ignored issues
show
Bug introduced by
Accessing fieldMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
315
        $this->assertTrue($groupMetadata->fieldMappings['name']['quoted']);
0 ignored issues
show
Bug introduced by
Accessing fieldMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
316
317
        $this->assertEquals('user-id', $userMetadata->fieldMappings['id']['columnName']);
0 ignored issues
show
Bug introduced by
Accessing fieldMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
318
        $this->assertEquals('user-name', $userMetadata->fieldMappings['name']['columnName']);
0 ignored issues
show
Bug introduced by
Accessing fieldMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
319
320
        $user = $groupMetadata->associationMappings['parent'];
0 ignored issues
show
Bug introduced by
Accessing associationMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
321
        $this->assertTrue($user['joinColumns'][0]['quoted']);
322
        $this->assertEquals('parent-id', $user['joinColumns'][0]['name']);
323
        $this->assertEquals('group-id', $user['joinColumns'][0]['referencedColumnName']);
324
325
326
        // Address Class Metadata
327
        $this->assertTrue($addressMetadata->fieldMappings['id']['quoted']);
0 ignored issues
show
Bug introduced by
Accessing fieldMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
328
        $this->assertTrue($addressMetadata->fieldMappings['zip']['quoted']);
0 ignored issues
show
Bug introduced by
Accessing fieldMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
329
330
        $this->assertEquals('address-id', $addressMetadata->fieldMappings['id']['columnName']);
0 ignored issues
show
Bug introduced by
Accessing fieldMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
331
        $this->assertEquals('address-zip', $addressMetadata->fieldMappings['zip']['columnName']);
0 ignored issues
show
Bug introduced by
Accessing fieldMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
332
333
        $user = $addressMetadata->associationMappings['user'];
0 ignored issues
show
Bug introduced by
Accessing associationMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
334
        $this->assertTrue($user['joinColumns'][0]['quoted']);
335
        $this->assertEquals('user-id', $user['joinColumns'][0]['name']);
336
        $this->assertEquals('user-id', $user['joinColumns'][0]['referencedColumnName']);
337
338
339
340
        // User Class Metadata
341
        $this->assertTrue($userMetadata->fieldMappings['id']['quoted']);
0 ignored issues
show
Bug introduced by
Accessing fieldMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
342
        $this->assertTrue($userMetadata->fieldMappings['name']['quoted']);
0 ignored issues
show
Bug introduced by
Accessing fieldMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
343
344
        $this->assertEquals('user-id', $userMetadata->fieldMappings['id']['columnName']);
0 ignored issues
show
Bug introduced by
Accessing fieldMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
345
        $this->assertEquals('user-name', $userMetadata->fieldMappings['name']['columnName']);
0 ignored issues
show
Bug introduced by
Accessing fieldMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
346
347
348
        $address = $userMetadata->associationMappings['address'];
0 ignored issues
show
Bug introduced by
Accessing associationMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
349
        $this->assertTrue($address['joinColumns'][0]['quoted']);
350
        $this->assertEquals('address-id', $address['joinColumns'][0]['name']);
351
        $this->assertEquals('address-id', $address['joinColumns'][0]['referencedColumnName']);
352
353
        $groups = $userMetadata->associationMappings['groups'];
0 ignored issues
show
Bug introduced by
Accessing associationMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
354
        $this->assertTrue($groups['joinTable']['quoted']);
355
        $this->assertTrue($groups['joinTable']['joinColumns'][0]['quoted']);
356
        $this->assertEquals('quote-users-groups', $groups['joinTable']['name']);
357
        $this->assertEquals('user-id', $groups['joinTable']['joinColumns'][0]['name']);
358
        $this->assertEquals('user-id', $groups['joinTable']['joinColumns'][0]['referencedColumnName']);
359
360
        $this->assertTrue($groups['joinTable']['inverseJoinColumns'][0]['quoted']);
361
        $this->assertEquals('group-id', $groups['joinTable']['inverseJoinColumns'][0]['name']);
362
        $this->assertEquals('group-id', $groups['joinTable']['inverseJoinColumns'][0]['referencedColumnName']);
363
    }
364
365
    /**
366
     * @group DDC-3385
367
     * @group 1181
368
     * @group 385
369
     */
370
    public function testFallbackLoadingCausesEventTriggeringThatCanModifyFetchedMetadata()
371
    {
372
        $test          = $this;
373
        /* @var $metadata \Doctrine\Common\Persistence\Mapping\ClassMetadata */
374
        $metadata      = $this->createMock(ClassMetadata::class);
375
        $cmf           = new ClassMetadataFactory();
376
        $mockDriver    = new MetadataDriverMock();
377
        $em = $this->_createEntityManager($mockDriver);
378
        $listener      = $this->getMockBuilder(\stdClass::class)->setMethods(['onClassMetadataNotFound'])->getMock();
379
        $eventManager  = $em->getEventManager();
380
381
        $cmf->setEntityManager($em);
382
383
        $listener
384
            ->expects($this->any())
385
            ->method('onClassMetadataNotFound')
386
            ->will($this->returnCallback(function (OnClassMetadataNotFoundEventArgs $args) use ($metadata, $em, $test) {
387
                $test->assertNull($args->getFoundMetadata());
388
                $test->assertSame('Foo', $args->getClassName());
389
                $test->assertSame($em, $args->getObjectManager());
390
391
                $args->setFoundMetadata($metadata);
392
            }));
393
394
        $eventManager->addEventListener([Events::onClassMetadataNotFound], $listener);
395
396
        $this->assertSame($metadata, $cmf->getMetadataFor('Foo'));
397
    }
398
399
    /**
400
     * @group DDC-3427
401
     */
402
    public function testAcceptsEntityManagerInterfaceInstances()
403
    {
404
        $classMetadataFactory = new ClassMetadataFactory();
405
406
        /* @var $entityManager EntityManager */
407
        $entityManager        = $this->createMock(EntityManagerInterface::class);
408
409
        $classMetadataFactory->setEntityManager($entityManager);
410
411
        // not really the cleanest way to check it, but we won't add a getter to the CMF just for the sake of testing.
412
        $this->assertAttributeSame($entityManager, 'em', $classMetadataFactory);
413
    }
414
415
    /**
416
     * @group DDC-3305
417
     */
418
    public function testRejectsEmbeddableWithoutValidClassName()
419
    {
420
        $metadata = $this->_createValidClassMetadata();
421
422
        $metadata->mapEmbedded(
423
            [
424
            'fieldName'    => 'embedded',
425
            'class'        => '',
426
            'columnPrefix' => false,
427
            ]
428
        );
429
430
        $cmf = $this->_createTestFactory();
431
432
        $cmf->setMetadataForClass($metadata->name, $metadata);
433
434
        $this->expectException(MappingException::class);
435
        $this->expectExceptionMessage('The embed mapping \'embedded\' misses the \'class\' attribute.');
436
437
        $cmf->getMetadataFor($metadata->name);
438
    }
439
440
    /**
441
     * @group DDC-4006
442
     */
443
    public function testInheritsIdGeneratorMappingFromEmbeddable()
444
    {
445
        $cmf = new ClassMetadataFactory();
446
        $driver = $this->createAnnotationDriver([__DIR__ . '/../../Models/DDC4006/']);
447
        $em = $this->_createEntityManager($driver);
448
        $cmf->setEntityManager($em);
449
450
        $userMetadata = $cmf->getMetadataFor(DDC4006User::class);
451
452
        $this->assertTrue($userMetadata->isIdGeneratorIdentity());
453
    }
454
}
455
456
/* Test subject class with overridden factory method for mocking purposes */
457
class ClassMetadataFactoryTestSubject extends ClassMetadataFactory
458
{
459
    private $mockMetadata = [];
460
    private $requestedClasses = [];
461
462
    /** @override */
463
    protected function newClassMetadataInstance($className)
464
    {
465
        $this->requestedClasses[] = $className;
466
        if ( ! isset($this->mockMetadata[$className])) {
467
            throw new \InvalidArgumentException("No mock metadata found for class $className.");
468
        }
469
        return $this->mockMetadata[$className];
470
    }
471
472
    public function setMetadataForClass($className, $metadata)
473
    {
474
        $this->mockMetadata[$className] = $metadata;
475
    }
476
477
    public function getRequestedClasses()
478
    {
479
        return $this->requestedClasses;
480
    }
481
}
482
483
class TestEntity1
484
{
485
    private $id;
0 ignored issues
show
Unused Code introduced by
The property $id 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...
486
    private $name;
0 ignored issues
show
Unused Code introduced by
The property $name 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...
487
    private $other;
0 ignored issues
show
Unused Code introduced by
The property $other 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...
488
    private $association;
0 ignored issues
show
Unused Code introduced by
The property $association 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...
489
    private $embedded;
0 ignored issues
show
Unused Code introduced by
The property $embedded 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...
490
}
491
492
class CustomIdGenerator extends AbstractIdGenerator
493
{
494
    public function generate(EntityManager $em, $entity)
495
    {
496
    }
497
}
498