Completed
Pull Request — master (#5883)
by Sebastian
19:21
created

testFallbackLoadingCausesEventTriggeringThatCanModifyFetchedMetadata()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 28
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 28
c 0
b 0
f 0
rs 8.8571
cc 1
eloc 19
nc 1
nop 0
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\OrmTestCase;
24
25
class ClassMetadataFactoryTest extends OrmTestCase
26
{
27
    public function testGetMetadataForSingleClass()
28
    {
29
        $mockDriver = new MetadataDriverMock();
30
        $entityManager = $this->_createEntityManager($mockDriver);
31
32
        $conn = $entityManager->getConnection();
33
        $mockPlatform = $conn->getDatabasePlatform();
34
        $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...
35
        $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...
36
37
        $cm1 = $this->_createValidClassMetadata();
38
39
        // SUT
40
        $cmf = new ClassMetadataFactory();
41
        $cmf->setEntityManager($entityManager);
42
        $cmf->setMetadataFor($cm1->name, $cm1);
43
44
        // Prechecks
45
        $this->assertEquals(array(), $cm1->parentClasses);
46
        $this->assertEquals(ClassMetadata::INHERITANCE_TYPE_NONE, $cm1->inheritanceType);
47
        $this->assertTrue($cm1->hasField('name'));
48
        $this->assertEquals(2, count($cm1->associationMappings));
49
        $this->assertEquals(ClassMetadata::GENERATOR_TYPE_AUTO, $cm1->generatorType);
50
        $this->assertEquals('group', $cm1->table['name']);
51
52
        // Go
53
        $cmMap1 = $cmf->getMetadataFor($cm1->name);
54
55
        $this->assertSame($cm1, $cmMap1);
56
        $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...
57
        $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...
58
        $this->assertEquals(array(), $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...
59
        $this->assertTrue($cmMap1->hasField('name'));
60
    }
61
62
    public function testGetMetadataFor_ReturnsLoadedCustomIdGenerator()
63
    {
64
        $cm1 = $this->_createValidClassMetadata();
65
        $cm1->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_CUSTOM);
66
        $cm1->customGeneratorDefinition = array(
67
            "class" => "Doctrine\Tests\ORM\Mapping\CustomIdGenerator");
68
        $cmf = $this->_createTestFactory();
69
        $cmf->setMetadataForClass($cm1->name, $cm1);
70
71
        $actual = $cmf->getMetadataFor($cm1->name);
72
73
        $this->assertEquals(ClassMetadata::GENERATOR_TYPE_CUSTOM,
74
            $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...
75
        $this->assertInstanceOf("Doctrine\Tests\ORM\Mapping\CustomIdGenerator",
76
            $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...
77
    }
78
79
    public function testGetMetadataFor_ThrowsExceptionOnUnknownCustomGeneratorClass()
80
    {
81
        $cm1 = $this->_createValidClassMetadata();
82
        $cm1->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_CUSTOM);
83
        $cm1->customGeneratorDefinition = array("class" => "NotExistingGenerator");
84
        $cmf = $this->_createTestFactory();
85
        $cmf->setMetadataForClass($cm1->name, $cm1);
86
        $this->expectException(ORMException::class);
87
88
        $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...
89
    }
90
91
    public function testGetMetadataFor_ThrowsExceptionOnMissingCustomGeneratorDefinition()
92
    {
93
        $cm1 = $this->_createValidClassMetadata();
94
        $cm1->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_CUSTOM);
95
        $cmf = $this->_createTestFactory();
96
        $cmf->setMetadataForClass($cm1->name, $cm1);
97
        $this->expectException(ORMException::class);
98
99
        $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...
100
    }
101
102
    public function testHasGetMetadata_NamespaceSeparatorIsNotNormalized()
103
    {
104
        require_once __DIR__."/../../Models/Global/GlobalNamespaceModel.php";
105
106
        $metadataDriver = $this->createAnnotationDriver(array(__DIR__ . '/../../Models/Global/'));
107
108
        $entityManager = $this->_createEntityManager($metadataDriver);
109
110
        $mf = $entityManager->getMetadataFactory();
111
        $m1 = $mf->getMetadataFor("DoctrineGlobal_Article");
112
        $h1 = $mf->hasMetadataFor("DoctrineGlobal_Article");
113
        $h2 = $mf->hasMetadataFor("\DoctrineGlobal_Article");
114
        $m2 = $mf->getMetadataFor("\DoctrineGlobal_Article");
115
116
        $this->assertNotSame($m1, $m2);
117
        $this->assertFalse($h2);
118
        $this->assertTrue($h1);
119
    }
120
121
    /**
122
     * @group DDC-1512
123
     */
124
    public function testIsTransient()
125
    {
126
        $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...
127
        $driver = $this->createMock(MappingDriver::class);
128
        $driver->expects($this->at(0))
129
               ->method('isTransient')
130
               ->with($this->equalTo('Doctrine\Tests\Models\CMS\CmsUser'))
131
               ->will($this->returnValue(true));
132
        $driver->expects($this->at(1))
133
               ->method('isTransient')
134
               ->with($this->equalTo('Doctrine\Tests\Models\CMS\CmsArticle'))
135
               ->will($this->returnValue(false));
136
137
        $em = $this->_createEntityManager($driver);
138
139
        $this->assertTrue($em->getMetadataFactory()->isTransient('Doctrine\Tests\Models\CMS\CmsUser'));
140
        $this->assertFalse($em->getMetadataFactory()->isTransient('Doctrine\Tests\Models\CMS\CmsArticle'));
141
    }
142
143
    /**
144
     * @group DDC-1512
145
     */
146
    public function testIsTransientEntityNamespace()
147
    {
148
        $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...
149
        $driver = $this->createMock(MappingDriver::class);
150
        $driver->expects($this->at(0))
151
               ->method('isTransient')
152
               ->with($this->equalTo('Doctrine\Tests\Models\CMS\CmsUser'))
153
               ->will($this->returnValue(true));
154
        $driver->expects($this->at(1))
155
               ->method('isTransient')
156
               ->with($this->equalTo('Doctrine\Tests\Models\CMS\CmsArticle'))
157
               ->will($this->returnValue(false));
158
159
        $em = $this->_createEntityManager($driver);
160
        $em->getConfiguration()->addEntityNamespace('CMS', 'Doctrine\Tests\Models\CMS');
161
162
        $this->assertTrue($em->getMetadataFactory()->isTransient('CMS:CmsUser'));
163
        $this->assertFalse($em->getMetadataFactory()->isTransient('CMS:CmsArticle'));
164
    }
165
166
    public function testAddDefaultDiscriminatorMap()
167
    {
168
        $cmf = new ClassMetadataFactory();
169
        $driver = $this->createAnnotationDriver(array(__DIR__ . '/../../Models/JoinedInheritanceType/'));
170
        $em = $this->_createEntityManager($driver);
171
        $cmf->setEntityManager($em);
172
173
        $rootMetadata = $cmf->getMetadataFor('Doctrine\Tests\Models\JoinedInheritanceType\RootClass');
174
        $childMetadata = $cmf->getMetadataFor('Doctrine\Tests\Models\JoinedInheritanceType\ChildClass');
175
        $anotherChildMetadata = $cmf->getMetadataFor('Doctrine\Tests\Models\JoinedInheritanceType\AnotherChildClass');
176
        $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...
177
        $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...
178
        $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...
179
180
        $rootClass = 'Doctrine\Tests\Models\JoinedInheritanceType\RootClass';
181
        $childClass = 'Doctrine\Tests\Models\JoinedInheritanceType\ChildClass';
182
        $anotherChildClass = 'Doctrine\Tests\Models\JoinedInheritanceType\AnotherChildClass';
183
184
        $rootClassKey = array_search($rootClass, $rootDiscriminatorMap);
185
        $childClassKey = array_search($childClass, $rootDiscriminatorMap);
186
        $anotherChildClassKey = array_search($anotherChildClass, $rootDiscriminatorMap);
187
188
        $this->assertEquals('rootclass', $rootClassKey);
189
        $this->assertEquals('childclass', $childClassKey);
190
        $this->assertEquals('anotherchildclass', $anotherChildClassKey);
191
192
        $this->assertEquals($childDiscriminatorMap, $rootDiscriminatorMap);
193
        $this->assertEquals($anotherChildDiscriminatorMap, $rootDiscriminatorMap);
194
195
        // ClassMetadataFactory::addDefaultDiscriminatorMap shouldn't be called again, because the
196
        // discriminator map is already cached
197
        $cmf = $this->getMockBuilder(ClassMetadataFactory::class)->setMethods(array('addDefaultDiscriminatorMap'))->getMock();
198
        $cmf->setEntityManager($em);
199
        $cmf->expects($this->never())
200
            ->method('addDefaultDiscriminatorMap');
201
202
        $rootMetadata = $cmf->getMetadataFor('Doctrine\Tests\Models\JoinedInheritanceType\RootClass');
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...
203
    }
204
205
    public function testGetAllMetadataWorksWithBadConnection()
206
    {
207
        // DDC-3551
208
        $conn = $this->createMock(Connection::class);
209
        $mockDriver    = new MetadataDriverMock();
210
        $em = $this->_createEntityManager($mockDriver, $conn);
211
212
        $conn->expects($this->any())
213
            ->method('getDatabasePlatform')
214
            ->will($this->throwException(new \Exception('Exception thrown in test when calling getDatabasePlatform')));
215
216
        $cmf = new ClassMetadataFactory();
217
        $cmf->setEntityManager($em);
218
219
        // getting all the metadata should work, even if get DatabasePlatform blows up
220
        $metadata = $cmf->getAllMetadata();
221
        // this will just be an empty array - there was no error
222
        $this->assertEquals(array(), $metadata);
223
    }
224
225
    protected function _createEntityManager($metadataDriver, $conn = null)
226
    {
227
        $driverMock = new DriverMock();
228
        $config = new Configuration();
229
        $config->setProxyDir(__DIR__ . '/../../Proxies');
230
        $config->setProxyNamespace('Doctrine\Tests\Proxies');
231
        $eventManager = new EventManager();
232
        if (!$conn) {
233
            $conn = new ConnectionMock(array(), $driverMock, $config, $eventManager);
234
        }
235
        $config->setMetadataDriverImpl($metadataDriver);
236
237
        return EntityManagerMock::create($conn, $config, $eventManager);
238
    }
239
240
    /**
241
     * @return ClassMetadataFactoryTestSubject
242
     */
243
    protected function _createTestFactory()
244
    {
245
        $mockDriver = new MetadataDriverMock();
246
        $entityManager = $this->_createEntityManager($mockDriver);
247
        $cmf = new ClassMetadataFactoryTestSubject();
248
        $cmf->setEntityManager($entityManager);
249
        return $cmf;
250
    }
251
252
    /**
253
     * @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...
254
     * @return ClassMetadata
255
     */
256
    protected function _createValidClassMetadata()
257
    {
258
        // Self-made metadata
259
        $cm1 = new ClassMetadata('Doctrine\Tests\ORM\Mapping\TestEntity1');
260
        $cm1->initializeReflection(new RuntimeReflectionService());
261
        $cm1->setPrimaryTable(array('name' => '`group`'));
262
        // Add a mapped field
263
        $cm1->mapField(array('fieldName' => 'name', 'type' => 'string'));
264
        // Add a mapped field
265
        $cm1->mapField(array('fieldName' => 'id', 'type' => 'integer', 'id' => true));
266
        // and a mapped association
267
        $cm1->mapOneToOne(array('fieldName' => 'other', 'targetEntity' => 'TestEntity1', 'mappedBy' => 'this'));
268
        // and an association on the owning side
269
        $joinColumns = array(
270
            array('name' => 'other_id', 'referencedColumnName' => 'id')
271
        );
272
        $cm1->mapOneToOne(array('fieldName' => 'association', 'targetEntity' => 'TestEntity1', 'joinColumns' => $joinColumns));
273
        // and an id generator type
274
        $cm1->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_AUTO);
275
        return $cm1;
276
    }
277
278
    /**
279
    * @group DDC-1845
280
    */
281
    public function testQuoteMetadata()
282
    {
283
        $cmf    = new ClassMetadataFactory();
284
        $driver = $this->createAnnotationDriver(array(__DIR__ . '/../../Models/Quote/'));
285
        $em     = $this->_createEntityManager($driver);
286
        $cmf->setEntityManager($em);
287
288
289
        $userMetadata       = $cmf->getMetadataFor('Doctrine\Tests\Models\Quote\User');
290
        $phoneMetadata      = $cmf->getMetadataFor('Doctrine\Tests\Models\Quote\Phone');
291
        $groupMetadata      = $cmf->getMetadataFor('Doctrine\Tests\Models\Quote\Group');
292
        $addressMetadata    = $cmf->getMetadataFor('Doctrine\Tests\Models\Quote\Address');
293
294
295
        // Phone Class Metadata
296
        $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...
297
        $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...
298
299
        $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...
300
        $this->assertTrue($user['joinColumns'][0]['quoted']);
301
        $this->assertEquals('user-id', $user['joinColumns'][0]['name']);
302
        $this->assertEquals('user-id', $user['joinColumns'][0]['referencedColumnName']);
303
304
305
306
        // User Group Metadata
307
        $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...
308
        $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...
309
310
        $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...
311
        $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...
312
313
        $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...
314
        $this->assertTrue($user['joinColumns'][0]['quoted']);
315
        $this->assertEquals('parent-id', $user['joinColumns'][0]['name']);
316
        $this->assertEquals('group-id', $user['joinColumns'][0]['referencedColumnName']);
317
318
319
        // Address Class Metadata
320
        $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...
321
        $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...
322
323
        $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...
324
        $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...
325
326
        $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...
327
        $this->assertTrue($user['joinColumns'][0]['quoted']);
328
        $this->assertEquals('user-id', $user['joinColumns'][0]['name']);
329
        $this->assertEquals('user-id', $user['joinColumns'][0]['referencedColumnName']);
330
331
332
333
        // User Class Metadata
334
        $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...
335
        $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...
336
337
        $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...
338
        $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...
339
340
341
        $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...
342
        $this->assertTrue($address['joinColumns'][0]['quoted']);
343
        $this->assertEquals('address-id', $address['joinColumns'][0]['name']);
344
        $this->assertEquals('address-id', $address['joinColumns'][0]['referencedColumnName']);
345
346
        $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...
347
        $this->assertTrue($groups['joinTable']['quoted']);
348
        $this->assertTrue($groups['joinTable']['joinColumns'][0]['quoted']);
349
        $this->assertEquals('quote-users-groups', $groups['joinTable']['name']);
350
        $this->assertEquals('user-id', $groups['joinTable']['joinColumns'][0]['name']);
351
        $this->assertEquals('user-id', $groups['joinTable']['joinColumns'][0]['referencedColumnName']);
352
353
        $this->assertTrue($groups['joinTable']['inverseJoinColumns'][0]['quoted']);
354
        $this->assertEquals('group-id', $groups['joinTable']['inverseJoinColumns'][0]['name']);
355
        $this->assertEquals('group-id', $groups['joinTable']['inverseJoinColumns'][0]['referencedColumnName']);
356
    }
357
358
    /**
359
     * @group DDC-3385
360
     * @group 1181
361
     * @group 385
362
     */
363
    public function testFallbackLoadingCausesEventTriggeringThatCanModifyFetchedMetadata()
364
    {
365
        $test          = $this;
366
        /* @var $metadata \Doctrine\Common\Persistence\Mapping\ClassMetadata */
367
        $metadata      = $this->createMock(ClassMetadata::class);
368
        $cmf           = new ClassMetadataFactory();
369
        $mockDriver    = new MetadataDriverMock();
370
        $em = $this->_createEntityManager($mockDriver);
371
        $listener      = $this->getMockBuilder(\stdClass::class)->setMethods(array('onClassMetadataNotFound'))->getMock();
372
        $eventManager  = $em->getEventManager();
373
374
        $cmf->setEntityManager($em);
375
376
        $listener
377
            ->expects($this->any())
378
            ->method('onClassMetadataNotFound')
379
            ->will($this->returnCallback(function (OnClassMetadataNotFoundEventArgs $args) use ($metadata, $em, $test) {
380
                $test->assertNull($args->getFoundMetadata());
381
                $test->assertSame('Foo', $args->getClassName());
382
                $test->assertSame($em, $args->getObjectManager());
383
384
                $args->setFoundMetadata($metadata);
385
            }));
386
387
        $eventManager->addEventListener(array(Events::onClassMetadataNotFound), $listener);
388
389
        $this->assertSame($metadata, $cmf->getMetadataFor('Foo'));
390
    }
391
392
    /**
393
     * @group DDC-3427
394
     */
395
    public function testAcceptsEntityManagerInterfaceInstances()
396
    {
397
        $classMetadataFactory = new ClassMetadataFactory();
398
399
        /* @var $entityManager EntityManager */
400
        $entityManager        = $this->createMock(EntityManagerInterface::class);
401
402
        $classMetadataFactory->setEntityManager($entityManager);
403
404
        // not really the cleanest way to check it, but we won't add a getter to the CMF just for the sake of testing.
405
        $this->assertAttributeSame($entityManager, 'em', $classMetadataFactory);
406
    }
407
408
    /**
409
     * @group DDC-3305
410
     */
411
    public function testRejectsEmbeddableWithoutValidClassName()
412
    {
413
        $metadata = $this->_createValidClassMetadata();
414
415
        $metadata->mapEmbedded(array(
416
            'fieldName'    => 'embedded',
417
            'class'        => '',
418
            'columnPrefix' => false,
419
        ));
420
421
        $cmf = $this->_createTestFactory();
422
423
        $cmf->setMetadataForClass($metadata->name, $metadata);
424
425
        $this->expectException(MappingException::class);
426
        $this->expectExceptionMessage('The embed mapping \'embedded\' misses the \'class\' attribute.');
427
428
        $cmf->getMetadataFor($metadata->name);
429
    }
430
431
    /**
432
     * @group DDC-4006
433
     */
434
    public function testInheritsIdGeneratorMappingFromEmbeddable()
435
    {
436
        $cmf = new ClassMetadataFactory();
437
        $driver = $this->createAnnotationDriver(array(__DIR__ . '/../../Models/DDC4006/'));
438
        $em = $this->_createEntityManager($driver);
439
        $cmf->setEntityManager($em);
440
441
        $userMetadata = $cmf->getMetadataFor('Doctrine\Tests\Models\DDC4006\DDC4006User');
442
443
        $this->assertTrue($userMetadata->isIdGeneratorIdentity());
444
    }
445
}
446
447
/* Test subject class with overridden factory method for mocking purposes */
448
class ClassMetadataFactoryTestSubject extends ClassMetadataFactory
449
{
450
    private $mockMetadata = array();
451
    private $requestedClasses = array();
452
453
    /** @override */
454
    protected function newClassMetadataInstance($className)
455
    {
456
        $this->requestedClasses[] = $className;
457
        if ( ! isset($this->mockMetadata[$className])) {
458
            throw new \InvalidArgumentException("No mock metadata found for class $className.");
459
        }
460
        return $this->mockMetadata[$className];
461
    }
462
463
    public function setMetadataForClass($className, $metadata)
464
    {
465
        $this->mockMetadata[$className] = $metadata;
466
    }
467
468
    public function getRequestedClasses()
469
    {
470
        return $this->requestedClasses;
471
    }
472
}
473
474
class TestEntity1
475
{
476
    private $id;
477
    private $name;
478
    private $other;
479
    private $association;
480
    private $embedded;
481
}
482
483
class CustomIdGenerator extends AbstractIdGenerator
484
{
485
    public function generate(EntityManager $em, $entity)
486
    {
487
    }
488
}
489