Failed Conditions
Pull Request — master (#6832)
by Jérémy
19:32
created

EntityGeneratorTest   D

Complexity

Total Complexity 56

Size/Duplication

Total Lines 1259
Duplicated Lines 10.88 %

Coupling/Cohesion

Components 1
Dependencies 12

Importance

Changes 0
Metric Value
wmc 56
lcom 1
cbo 12
dl 137
loc 1259
rs 4.6807
c 0
b 0
f 0

41 Methods

Rating   Name   Duplication   Size   Complexity  
A setUp() 0 15 1
A tearDown() 0 11 3
B generateBookEntityFixture() 0 43 2
A generateEntityTypeFixture() 0 17 1
A generateIsbnEmbeddableFixture() 0 19 2
A generateTestEmbeddableFixture() 0 14 1
A mapEmbedded() 0 10 1
A mapNestedEmbedded() 0 19 4
A loadEntityClass() 0 9 1
A newInstance() 0 6 1
A testEmbeddedEntityWithNamedColumnPrefix() 0 13 1
A testEmbeddedEntityWithoutColumnPrefix() 0 12 1
A testGeneratedEntityClass() 0 61 1
B testEntityUpdatingWorks() 0 40 1
B testDoesNotRegenerateExistingMethodsWithDifferentCase() 0 26 1
A testMethodDocBlockShouldStartWithBackSlash() 0 22 1
A testEntityExtendsStdClass() 0 12 1
A testLifecycleCallbacks() 0 10 1
B testLoadMetadata() 0 37 1
B testLoadPrefixedMetadata() 0 36 1
A testMappedSuperclassAnnotationGeneration() 0 18 1
A testParseTokensInEntityFile() 0 12 1
B testGenerateEntityWithSequenceGenerator() 0 30 1
B testGenerateEntityWithMultipleInverseJoinColumns() 0 42 1
B testGetInheritanceTypeString() 25 25 3
B testGetChangeTrackingPolicyString() 25 25 3
B testGetIdGeneratorTypeString() 25 25 3
B testEntityTypeAlias() 0 24 1
A testTraitPropertiesAndMethodsAreNotDuplicated() 22 22 1
A testTraitPropertiesAndMethodsAreNotDuplicatedInChildClasses() 22 22 1
A testMethodsAndPropertiesAreNotDuplicatedInChildClasses() 0 69 1
B testGeneratedMutableEmbeddablesClass() 0 35 1
A testGeneratedImmutableEmbeddablesClass() 0 70 1
A testRegenerateEntityClass() 0 17 1
A testGenerateMethodsTypeHinting() 0 62 2
B testEntityMethodTypeHintingAlias() 0 28 2
B getEntityTypeAliasDataProvider() 0 85 1
B getParseTokensInEntityFileData() 0 41 1
A assertPhpDocVarType() 9 9 1
A assertPhpDocReturnType() 9 9 1
A assertPhpDocParamType() 0 5 1

How to fix   Duplicated Code    Complexity   

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:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like EntityGeneratorTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use EntityGeneratorTest, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Doctrine\Tests\ORM\Tools;
4
5
use Doctrine\Common\Annotations\AnnotationReader;
6
use Doctrine\Common\Collections\ArrayCollection;
7
use Doctrine\Common\Persistence\Mapping\RuntimeReflectionService;
8
use Doctrine\ORM\Mapping\ClassMetadataFactory;
9
use Doctrine\ORM\Mapping\ClassMetadataInfo;
10
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
11
use Doctrine\ORM\Tools\EntityGenerator;
12
use Doctrine\Tests\Models\DDC2372\DDC2372Admin;
13
use Doctrine\Tests\Models\DDC2372\DDC2372User;
14
use Doctrine\Tests\OrmTestCase;
15
16
class EntityGeneratorTest extends OrmTestCase
17
{
18
19
    /**
20
     * @var EntityGenerator
21
     */
22
    private $_generator;
23
    private $_tmpDir;
24
    private $_namespace;
25
26
    public function setUp()
27
    {
28
        $this->_namespace = uniqid("doctrine_");
29
        $this->_tmpDir = \sys_get_temp_dir();
30
        \mkdir($this->_tmpDir . \DIRECTORY_SEPARATOR . $this->_namespace);
31
        $this->_generator = new EntityGenerator();
32
        $this->_generator->setAnnotationPrefix("");
33
        $this->_generator->setGenerateAnnotations(true);
34
        $this->_generator->setGenerateStubMethods(true);
35
        $this->_generator->setRegenerateEntityIfExists(false);
36
        $this->_generator->setStrictTypes(false);
37
        $this->_generator->setGenerateMethodsTypeHinting(false);
38
        $this->_generator->setUpdateEntityIfExists(true);
39
        $this->_generator->setFieldVisibility(EntityGenerator::FIELD_VISIBLE_PROTECTED);
40
    }
41
42
    public function tearDown()
43
    {
44
        $ri = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->_tmpDir . '/' . $this->_namespace));
45
        foreach ($ri AS $file) {
46
            /* @var $file \SplFileInfo */
47
            if ($file->isFile()) {
48
                \unlink($file->getPathname());
49
            }
50
        }
51
        rmdir($this->_tmpDir . '/' . $this->_namespace);
52
    }
53
54
    /**
55
     * @param ClassMetadataInfo[] $embeddedClasses
56
     *
57
     * @return ClassMetadataInfo
58
     */
59
    public function generateBookEntityFixture(array $embeddedClasses = [])
60
    {
61
        $metadata = new ClassMetadataInfo($this->_namespace . '\EntityGeneratorBook');
62
        $metadata->namespace = $this->_namespace;
63
        $metadata->customRepositoryClassName = $this->_namespace  . '\EntityGeneratorBookRepository';
64
65
        $metadata->table['name'] = 'book';
66
        $metadata->table['uniqueConstraints']['name_uniq'] = ['columns' => ['name']];
67
        $metadata->table['indexes']['status_idx'] = ['columns' => ['status']];
68
        $metadata->mapField(['fieldName' => 'name', 'type' => 'string']);
69
        $metadata->mapField(['fieldName' => 'status', 'type' => 'string', 'options' => ['default' => 'published']]);
70
        $metadata->mapField(['fieldName' => 'id', 'type' => 'integer', 'id' => true]);
71
        $metadata->mapOneToOne(
72
            ['fieldName' => 'author', 'targetEntity' => EntityGeneratorAuthor::class, 'mappedBy' => 'book']
73
        );
74
        $joinColumns = [
0 ignored issues
show
Unused Code introduced by
$joinColumns 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...
75
            ['name' => 'author_id', 'referencedColumnName' => 'id']
76
        ];
77
        $metadata->mapManyToMany(
78
            [
79
            'fieldName' => 'comments',
80
            'targetEntity' => EntityGeneratorComment::class,
81
            'fetch' => ClassMetadataInfo::FETCH_EXTRA_LAZY,
82
            'joinTable' => [
83
                'name' => 'book_comment',
84
                'joinColumns' => [['name' => 'book_id', 'referencedColumnName' => 'id']],
85
                'inverseJoinColumns' => [['name' => 'comment_id', 'referencedColumnName' => 'id']],
86
            ],
87
            ]
88
        );
89
        $metadata->addLifecycleCallback('loading', 'postLoad');
90
        $metadata->addLifecycleCallback('willBeRemoved', 'preRemove');
91
        $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO);
92
93
        foreach ($embeddedClasses as $fieldName => $embeddedClass) {
94
            $this->mapNestedEmbedded($fieldName, $metadata, $embeddedClass);
95
            $this->mapEmbedded($fieldName, $metadata, $embeddedClass);
96
        }
97
98
        $this->_generator->writeEntityClass($metadata, $this->_tmpDir);
99
100
        return $metadata;
101
    }
102
103
    private function generateEntityTypeFixture(array $field)
104
    {
105
        $metadata = new ClassMetadataInfo($this->_namespace . '\EntityType');
106
        $metadata->namespace = $this->_namespace;
107
108
        $metadata->table['name'] = 'entity_type';
109
        $metadata->mapField(['fieldName' => 'id', 'type' => 'integer', 'id' => true]);
110
        $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO);
111
112
        $name  = $field['fieldName'];
113
        $type  = $field['dbType'];
114
        $metadata->mapField(['fieldName' => $name, 'type' => $type]);
115
116
        $this->_generator->writeEntityClass($metadata, $this->_tmpDir);
117
118
        return $metadata;
119
    }
120
121
    /**
122
     * @return ClassMetadataInfo
123
     */
124
    private function generateIsbnEmbeddableFixture(array $embeddedClasses = [], $columnPrefix = null)
125
    {
126
        $metadata = new ClassMetadataInfo($this->_namespace . '\EntityGeneratorIsbn');
127
        $metadata->namespace = $this->_namespace;
128
        $metadata->isEmbeddedClass = true;
129
        $metadata->mapField(['fieldName' => 'prefix', 'type' => 'integer']);
130
        $metadata->mapField(['fieldName' => 'groupNumber', 'type' => 'integer']);
131
        $metadata->mapField(['fieldName' => 'publisherNumber', 'type' => 'integer']);
132
        $metadata->mapField(['fieldName' => 'titleNumber', 'type' => 'integer']);
133
        $metadata->mapField(['fieldName' => 'checkDigit', 'type' => 'integer']);
134
135
        foreach ($embeddedClasses as $fieldName => $embeddedClass) {
136
            $this->mapEmbedded($fieldName, $metadata, $embeddedClass, $columnPrefix);
137
        }
138
139
        $this->_generator->writeEntityClass($metadata, $this->_tmpDir);
140
141
        return $metadata;
142
    }
143
144
    /**
145
     * @return ClassMetadataInfo
146
     */
147
    private function generateTestEmbeddableFixture()
148
    {
149
        $metadata = new ClassMetadataInfo($this->_namespace . '\EntityGeneratorTestEmbeddable');
150
        $metadata->namespace = $this->_namespace;
151
        $metadata->isEmbeddedClass = true;
152
        $metadata->mapField(['fieldName' => 'field1', 'type' => 'integer']);
153
        $metadata->mapField(['fieldName' => 'field2', 'type' => 'integer', 'nullable' => true]);
154
        $metadata->mapField(['fieldName' => 'field3', 'type' => 'datetime']);
155
        $metadata->mapField(['fieldName' => 'field4', 'type' => 'datetime', 'nullable' => true]);
156
157
        $this->_generator->writeEntityClass($metadata, $this->_tmpDir);
158
159
        return $metadata;
160
    }
161
162
    /**
163
     * @param string            $fieldName
164
     * @param ClassMetadataInfo $classMetadata
165
     * @param ClassMetadataInfo $embeddableMetadata
166
     * @param string|null       $columnPrefix
167
     */
168
    private function mapEmbedded(
169
        $fieldName,
170
        ClassMetadataInfo $classMetadata,
171
        ClassMetadataInfo $embeddableMetadata,
172
        $columnPrefix = false
173
    ) {
174
        $classMetadata->mapEmbedded(
175
            ['fieldName' => $fieldName, 'class' => $embeddableMetadata->name, 'columnPrefix' => $columnPrefix]
176
        );
177
    }
178
179
    /**
180
     * @param string            $fieldName
181
     * @param ClassMetadataInfo $classMetadata
182
     * @param ClassMetadataInfo $embeddableMetadata
183
     */
184
    private function mapNestedEmbedded(
185
        $fieldName,
186
        ClassMetadataInfo $classMetadata,
187
        ClassMetadataInfo $embeddableMetadata
188
    ) {
189
        foreach ($embeddableMetadata->embeddedClasses as $property => $embeddableClass) {
190
            $classMetadata->mapEmbedded(
191
                [
192
                'fieldName' => $fieldName . '.' . $property,
193
                'class' => $embeddableClass['class'],
194
                'columnPrefix' => $embeddableClass['columnPrefix'],
195
                'declaredField' => $embeddableClass['declaredField']
196
                        ? $fieldName . '.' . $embeddableClass['declaredField']
197
                        : $fieldName,
198
                'originalField' => $embeddableClass['originalField'] ?: $property,
199
                ]
200
            );
201
        }
202
    }
203
204
    /**
205
     * @param ClassMetadataInfo $metadata
206
     */
207
    private function loadEntityClass(ClassMetadataInfo $metadata)
208
    {
209
        $className = basename(str_replace('\\', '/', $metadata->name));
210
        $path = $this->_tmpDir . '/' . $this->_namespace . '/' . $className . '.php';
211
212
        $this->assertFileExists($path);
213
214
        require_once $path;
215
    }
216
217
    /**
218
     * @param  ClassMetadataInfo $metadata
219
     *
220
     * @return mixed An instance of the given metadata's class.
221
     */
222
    public function newInstance($metadata)
223
    {
224
        $this->loadEntityClass($metadata);
225
226
        return new $metadata->name;
227
    }
228
229
    /**
230
     * @group GH-6314
231
     */
232
    public function testEmbeddedEntityWithNamedColumnPrefix()
233
    {
234
        $columnPrefix = 'GH6314Prefix_';
235
        $testMetadata = $this->generateTestEmbeddableFixture();
236
        $isbnMetadata = $this->generateIsbnEmbeddableFixture(['testEmbedded' => $testMetadata], $columnPrefix);
237
        $isbnEntity = $this->newInstance($isbnMetadata);
238
        $refClass = new \ReflectionClass($isbnEntity);
239
        self::assertTrue($refClass->hasProperty('testEmbedded'));
240
241
        $docComment = $refClass->getProperty('testEmbedded')->getDocComment();
242
        $needle = sprintf('@Embedded(class="%s", columnPrefix="%s")', $testMetadata->name, $columnPrefix);
243
        self::assertContains($needle, $docComment);
244
    }
245
246
    /**
247
     * @group GH-6314
248
     */
249
    public function testEmbeddedEntityWithoutColumnPrefix()
250
    {
251
        $testMetadata = $this->generateTestEmbeddableFixture();
252
        $isbnMetadata = $this->generateIsbnEmbeddableFixture(['testEmbedded' => $testMetadata], false);
253
        $isbnEntity = $this->newInstance($isbnMetadata);
254
        $refClass = new \ReflectionClass($isbnEntity);
255
        self::assertTrue($refClass->hasProperty('testEmbedded'));
256
257
        $docComment = $refClass->getProperty('testEmbedded')->getDocComment();
258
        $needle = sprintf('@Embedded(class="%s", columnPrefix=false)', $testMetadata->name);
259
        self::assertContains($needle, $docComment);
260
    }
261
262
    public function testGeneratedEntityClass()
263
    {
264
        $testMetadata = $this->generateTestEmbeddableFixture();
265
        $isbnMetadata = $this->generateIsbnEmbeddableFixture(['test' => $testMetadata]);
266
        $metadata = $this->generateBookEntityFixture(['isbn' => $isbnMetadata]);
267
268
        $book = $this->newInstance($metadata);
269
        $this->assertTrue(class_exists($metadata->name), "Class does not exist.");
270
        $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', '__construct'), "EntityGeneratorBook::__construct() missing.");
271
        $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'getId'), "EntityGeneratorBook::getId() missing.");
272
        $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'setName'), "EntityGeneratorBook::setName() missing.");
273
        $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'getName'), "EntityGeneratorBook::getName() missing.");
274
        $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'setStatus'), "EntityGeneratorBook::setStatus() missing.");
275
        $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'getStatus'), "EntityGeneratorBook::getStatus() missing.");
276
        $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'setAuthor'), "EntityGeneratorBook::setAuthor() missing.");
277
        $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'getAuthor'), "EntityGeneratorBook::getAuthor() missing.");
278
        $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'getComments'), "EntityGeneratorBook::getComments() missing.");
279
        $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'addComment'), "EntityGeneratorBook::addComment() missing.");
280
        $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'removeComment'), "EntityGeneratorBook::removeComment() missing.");
281
        $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'setIsbn'), "EntityGeneratorBook::setIsbn() missing.");
282
        $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'getIsbn'), "EntityGeneratorBook::getIsbn() missing.");
283
284
        $reflClass = new \ReflectionClass($metadata->name);
285
286
        $this->assertCount(6, $reflClass->getProperties());
287
        $this->assertCount(15, $reflClass->getMethods());
288
289
        $this->assertEquals('published', $book->getStatus());
290
291
        $book->setName('Jonathan H. Wage');
292
        $this->assertEquals('Jonathan H. Wage', $book->getName());
293
294
        $reflMethod = new \ReflectionMethod($metadata->name, 'addComment');
295
        $addCommentParameters = $reflMethod->getParameters();
296
        $this->assertEquals('comment', $addCommentParameters[0]->getName());
0 ignored issues
show
Bug introduced by
Consider using $addCommentParameters[0]->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
297
298
        $reflMethod = new \ReflectionMethod($metadata->name, 'removeComment');
299
        $removeCommentParameters = $reflMethod->getParameters();
300
        $this->assertEquals('comment', $removeCommentParameters[0]->getName());
0 ignored issues
show
Bug introduced by
Consider using $removeCommentParameters[0]->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
301
302
        $author = new EntityGeneratorAuthor();
303
        $book->setAuthor($author);
304
        $this->assertEquals($author, $book->getAuthor());
305
306
        $comment = new EntityGeneratorComment();
307
        $this->assertInstanceOf($metadata->name, $book->addComment($comment));
308
        $this->assertInstanceOf(ArrayCollection::class, $book->getComments());
309
        $this->assertEquals(new ArrayCollection([$comment]), $book->getComments());
310
        $this->assertInternalType('boolean', $book->removeComment($comment));
311
        $this->assertEquals(new ArrayCollection([]), $book->getComments());
312
313
        $this->newInstance($isbnMetadata);
314
        $isbn = new $isbnMetadata->name();
315
316
        $book->setIsbn($isbn);
317
        $this->assertSame($isbn, $book->getIsbn());
318
319
        $reflMethod = new \ReflectionMethod($metadata->name, 'setIsbn');
320
        $reflParameters = $reflMethod->getParameters();
321
        $this->assertEquals($isbnMetadata->name, $reflParameters[0]->getClass()->name);
322
    }
323
324
    public function testEntityUpdatingWorks()
325
    {
326
        $metadata = $this->generateBookEntityFixture(['isbn' => $this->generateIsbnEmbeddableFixture()]);
327
328
        $metadata->mapField(['fieldName' => 'test', 'type' => 'string']);
329
330
        $testEmbeddableMetadata = $this->generateTestEmbeddableFixture();
331
        $this->mapEmbedded('testEmbedded', $metadata, $testEmbeddableMetadata);
332
333
        $this->_generator->writeEntityClass($metadata, $this->_tmpDir);
334
335
        $this->assertFileExists($this->_tmpDir . "/" . $this->_namespace . "/EntityGeneratorBook.php~");
336
337
        $book = $this->newInstance($metadata);
0 ignored issues
show
Unused Code introduced by
$book 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...
338
        $reflClass = new \ReflectionClass($metadata->name);
339
340
        $this->assertTrue($reflClass->hasProperty('name'), "Regenerating keeps property 'name'.");
341
        $this->assertTrue($reflClass->hasProperty('status'), "Regenerating keeps property 'status'.");
342
        $this->assertTrue($reflClass->hasProperty('id'), "Regenerating keeps property 'id'.");
343
        $this->assertTrue($reflClass->hasProperty('isbn'), "Regenerating keeps property 'isbn'.");
344
345
        $this->assertTrue($reflClass->hasProperty('test'), "Check for property test failed.");
346
        $this->assertTrue($reflClass->getProperty('test')->isProtected(), "Check for protected property test failed.");
347
        $this->assertTrue($reflClass->hasProperty('testEmbedded'), "Check for property testEmbedded failed.");
348
        $this->assertTrue($reflClass->getProperty('testEmbedded')->isProtected(), "Check for protected property testEmbedded failed.");
349
        $this->assertTrue($reflClass->hasMethod('getTest'), "Check for method 'getTest' failed.");
350
        $this->assertTrue($reflClass->getMethod('getTest')->isPublic(), "Check for public visibility of method 'getTest' failed.");
351
        $this->assertTrue($reflClass->hasMethod('setTest'), "Check for method 'setTest' failed.");
352
        $this->assertTrue($reflClass->getMethod('setTest')->isPublic(), "Check for public visibility of method 'setTest' failed.");
353
        $this->assertTrue($reflClass->hasMethod('getTestEmbedded'), "Check for method 'getTestEmbedded' failed.");
354
        $this->assertTrue(
355
            $reflClass->getMethod('getTestEmbedded')->isPublic(),
356
            "Check for public visibility of method 'getTestEmbedded' failed."
357
        );
358
        $this->assertTrue($reflClass->hasMethod('setTestEmbedded'), "Check for method 'setTestEmbedded' failed.");
359
        $this->assertTrue(
360
            $reflClass->getMethod('setTestEmbedded')->isPublic(),
361
            "Check for public visibility of method 'setTestEmbedded' failed."
362
        );
363
    }
364
365
    /**
366
     * @group DDC-3152
367
     */
368
    public function testDoesNotRegenerateExistingMethodsWithDifferentCase()
369
    {
370
        $metadata = $this->generateBookEntityFixture(['isbn' => $this->generateIsbnEmbeddableFixture()]);
371
372
        // Workaround to change existing fields case (just to simulate the use case)
373
        $metadata->fieldMappings['status']['fieldName'] = 'STATUS';
374
        $metadata->embeddedClasses['ISBN'] = $metadata->embeddedClasses['isbn'];
375
        unset($metadata->embeddedClasses['isbn']);
376
377
        // Should not throw a PHP fatal error
378
        $this->_generator->writeEntityClass($metadata, $this->_tmpDir);
379
380
        $this->assertFileExists($this->_tmpDir . "/" . $this->_namespace . "/EntityGeneratorBook.php~");
381
382
        $this->newInstance($metadata);
383
        $reflClass = new \ReflectionClass($metadata->name);
384
385
        $this->assertTrue($reflClass->hasProperty('status'));
386
        $this->assertTrue($reflClass->hasProperty('STATUS'));
387
        $this->assertTrue($reflClass->hasProperty('isbn'));
388
        $this->assertTrue($reflClass->hasProperty('ISBN'));
389
        $this->assertTrue($reflClass->hasMethod('getStatus'));
390
        $this->assertTrue($reflClass->hasMethod('setStatus'));
391
        $this->assertTrue($reflClass->hasMethod('getIsbn'));
392
        $this->assertTrue($reflClass->hasMethod('setIsbn'));
393
    }
394
395
    /**
396
     * @group DDC-2121
397
     */
398
    public function testMethodDocBlockShouldStartWithBackSlash()
399
    {
400
        $embeddedMetadata = $this->generateIsbnEmbeddableFixture();
401
        $metadata = $this->generateBookEntityFixture(['isbn' => $embeddedMetadata]);
402
        $book     = $this->newInstance($metadata);
403
404
        $this->assertPhpDocVarType('\Doctrine\Common\Collections\Collection', new \ReflectionProperty($book, 'comments'));
405
        $this->assertPhpDocReturnType('\Doctrine\Common\Collections\Collection', new \ReflectionMethod($book, 'getComments'));
406
        $this->assertPhpDocParamType('\Doctrine\Tests\ORM\Tools\EntityGeneratorComment', new \ReflectionMethod($book, 'addComment'));
407
        $this->assertPhpDocReturnType('EntityGeneratorBook', new \ReflectionMethod($book, 'addComment'));
408
        $this->assertPhpDocParamType('\Doctrine\Tests\ORM\Tools\EntityGeneratorComment', new \ReflectionMethod($book, 'removeComment'));
409
        $this->assertPhpDocReturnType('boolean', new \ReflectionMethod($book, 'removeComment'));
410
411
        $this->assertPhpDocVarType('\Doctrine\Tests\ORM\Tools\EntityGeneratorAuthor', new \ReflectionProperty($book, 'author'));
412
        $this->assertPhpDocReturnType('\Doctrine\Tests\ORM\Tools\EntityGeneratorAuthor|null', new \ReflectionMethod($book, 'getAuthor'));
413
        $this->assertPhpDocParamType('\Doctrine\Tests\ORM\Tools\EntityGeneratorAuthor|null', new \ReflectionMethod($book, 'setAuthor'));
414
415
        $expectedClassName = '\\' . $embeddedMetadata->name;
416
        $this->assertPhpDocVarType($expectedClassName, new \ReflectionProperty($book, 'isbn'));
417
        $this->assertPhpDocReturnType($expectedClassName, new \ReflectionMethod($book, 'getIsbn'));
418
        $this->assertPhpDocParamType($expectedClassName, new \ReflectionMethod($book, 'setIsbn'));
419
    }
420
421
    public function testEntityExtendsStdClass()
422
    {
423
        $this->_generator->setClassToExtend('stdClass');
424
        $metadata = $this->generateBookEntityFixture();
425
426
        $book = $this->newInstance($metadata);
427
        $this->assertInstanceOf('stdClass', $book);
428
429
        $metadata = $this->generateIsbnEmbeddableFixture();
430
        $isbn = $this->newInstance($metadata);
431
        $this->assertInstanceOf('stdClass', $isbn);
432
    }
433
434
    public function testLifecycleCallbacks()
435
    {
436
        $metadata = $this->generateBookEntityFixture();
437
438
        $book = $this->newInstance($metadata);
0 ignored issues
show
Unused Code introduced by
$book 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...
439
        $reflClass = new \ReflectionClass($metadata->name);
440
441
        $this->assertTrue($reflClass->hasMethod('loading'), "Check for postLoad lifecycle callback.");
442
        $this->assertTrue($reflClass->hasMethod('willBeRemoved'), "Check for preRemove lifecycle callback.");
443
    }
444
445
    public function testLoadMetadata()
446
    {
447
        $embeddedMetadata = $this->generateIsbnEmbeddableFixture();
448
        $metadata = $this->generateBookEntityFixture(['isbn' => $embeddedMetadata]);
449
450
        $book = $this->newInstance($metadata);
0 ignored issues
show
Unused Code introduced by
$book 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...
451
452
        $reflectionService = new RuntimeReflectionService();
453
454
        $cm = new ClassMetadataInfo($metadata->name);
455
        $cm->initializeReflection($reflectionService);
456
457
        $driver = $this->createAnnotationDriver();
458
        $driver->loadMetadataForClass($cm->name, $cm);
459
460
        $this->assertEquals($cm->columnNames, $metadata->columnNames);
0 ignored issues
show
Deprecated Code introduced by
The property Doctrine\ORM\Mapping\Cla...adataInfo::$columnNames has been deprecated with message: 3.0 Remove this.

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

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

Loading history...
461
        $this->assertEquals($cm->getTableName(), $metadata->getTableName());
462
        $this->assertEquals($cm->lifecycleCallbacks, $metadata->lifecycleCallbacks);
463
        $this->assertEquals($cm->identifier, $metadata->identifier);
464
        $this->assertEquals($cm->idGenerator, $metadata->idGenerator);
465
        $this->assertEquals($cm->customRepositoryClassName, $metadata->customRepositoryClassName);
466
        $this->assertEquals($cm->embeddedClasses, $metadata->embeddedClasses);
467
        $this->assertEquals($cm->isEmbeddedClass, $metadata->isEmbeddedClass);
468
469
        $this->assertEquals(ClassMetadataInfo::FETCH_EXTRA_LAZY, $cm->associationMappings['comments']['fetch']);
470
471
        $isbn = $this->newInstance($embeddedMetadata);
0 ignored issues
show
Unused Code introduced by
$isbn 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...
472
473
        $cm = new ClassMetadataInfo($embeddedMetadata->name);
474
        $cm->initializeReflection($reflectionService);
475
476
        $driver->loadMetadataForClass($cm->name, $cm);
477
478
        $this->assertEquals($cm->columnNames, $embeddedMetadata->columnNames);
0 ignored issues
show
Deprecated Code introduced by
The property Doctrine\ORM\Mapping\Cla...adataInfo::$columnNames has been deprecated with message: 3.0 Remove this.

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

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

Loading history...
479
        $this->assertEquals($cm->embeddedClasses, $embeddedMetadata->embeddedClasses);
480
        $this->assertEquals($cm->isEmbeddedClass, $embeddedMetadata->isEmbeddedClass);
481
    }
482
483
    public function testLoadPrefixedMetadata()
484
    {
485
        $this->_generator->setAnnotationPrefix('ORM\\');
486
        $embeddedMetadata = $this->generateIsbnEmbeddableFixture();
487
        $metadata = $this->generateBookEntityFixture(['isbn' => $embeddedMetadata]);
488
489
        $reader = new AnnotationReader();
490
        $driver = new AnnotationDriver($reader, []);
491
492
        $book = $this->newInstance($metadata);
0 ignored issues
show
Unused Code introduced by
$book 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...
493
494
        $reflectionService = new RuntimeReflectionService();
495
496
        $cm = new ClassMetadataInfo($metadata->name);
497
        $cm->initializeReflection($reflectionService);
498
499
        $driver->loadMetadataForClass($cm->name, $cm);
500
501
        $this->assertEquals($cm->columnNames, $metadata->columnNames);
0 ignored issues
show
Deprecated Code introduced by
The property Doctrine\ORM\Mapping\Cla...adataInfo::$columnNames has been deprecated with message: 3.0 Remove this.

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

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

Loading history...
502
        $this->assertEquals($cm->getTableName(), $metadata->getTableName());
503
        $this->assertEquals($cm->lifecycleCallbacks, $metadata->lifecycleCallbacks);
504
        $this->assertEquals($cm->identifier, $metadata->identifier);
505
        $this->assertEquals($cm->idGenerator, $metadata->idGenerator);
506
        $this->assertEquals($cm->customRepositoryClassName, $metadata->customRepositoryClassName);
507
508
        $isbn = $this->newInstance($embeddedMetadata);
0 ignored issues
show
Unused Code introduced by
$isbn 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...
509
510
        $cm = new ClassMetadataInfo($embeddedMetadata->name);
511
        $cm->initializeReflection($reflectionService);
512
513
        $driver->loadMetadataForClass($cm->name, $cm);
514
515
        $this->assertEquals($cm->columnNames, $embeddedMetadata->columnNames);
0 ignored issues
show
Deprecated Code introduced by
The property Doctrine\ORM\Mapping\Cla...adataInfo::$columnNames has been deprecated with message: 3.0 Remove this.

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

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

Loading history...
516
        $this->assertEquals($cm->embeddedClasses, $embeddedMetadata->embeddedClasses);
517
        $this->assertEquals($cm->isEmbeddedClass, $embeddedMetadata->isEmbeddedClass);
518
    }
519
520
    /**
521
     * @group DDC-3272
522
     */
523
    public function testMappedSuperclassAnnotationGeneration()
524
    {
525
        $metadata                     = new ClassMetadataInfo($this->_namespace . '\EntityGeneratorBook');
526
        $metadata->namespace          = $this->_namespace;
527
        $metadata->isMappedSuperclass = true;
528
529
        $this->_generator->setAnnotationPrefix('ORM\\');
530
        $this->_generator->writeEntityClass($metadata, $this->_tmpDir);
531
        $this->newInstance($metadata); // force instantiation (causes autoloading to kick in)
532
533
        $driver = new AnnotationDriver(new AnnotationReader(), []);
534
        $cm     = new ClassMetadataInfo($metadata->name);
535
536
        $cm->initializeReflection(new RuntimeReflectionService);
537
        $driver->loadMetadataForClass($cm->name, $cm);
538
539
        $this->assertTrue($cm->isMappedSuperclass);
540
    }
541
542
    /**
543
     * @dataProvider getParseTokensInEntityFileData
544
     */
545
    public function testParseTokensInEntityFile($php, $classes)
546
    {
547
        $r = new \ReflectionObject($this->_generator);
548
        $m = $r->getMethod('parseTokensInEntityFile');
549
        $m->setAccessible(true);
550
551
        $p = $r->getProperty('staticReflection');
552
        $p->setAccessible(true);
553
554
        $ret = $m->invoke($this->_generator, $php);
0 ignored issues
show
Unused Code introduced by
$ret 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...
555
        $this->assertEquals($classes, array_keys($p->getValue($this->_generator)));
556
    }
557
558
    /**
559
     * @group DDC-1784
560
     */
561
    public function testGenerateEntityWithSequenceGenerator()
562
    {
563
        $metadata               = new ClassMetadataInfo($this->_namespace . '\DDC1784Entity');
564
        $metadata->namespace    = $this->_namespace;
565
        $metadata->mapField(['fieldName' => 'id', 'type' => 'integer', 'id' => true]);
566
        $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE);
567
        $metadata->setSequenceGeneratorDefinition(
568
            [
569
            'sequenceName'      => 'DDC1784_ID_SEQ',
570
            'allocationSize'    => 1,
571
            'initialValue'      => 2
572
            ]
573
        );
574
        $this->_generator->writeEntityClass($metadata, $this->_tmpDir);
575
576
        $filename = $this->_tmpDir . DIRECTORY_SEPARATOR
577
                  . $this->_namespace . DIRECTORY_SEPARATOR . 'DDC1784Entity.php';
578
579
        $this->assertFileExists($filename);
580
        require_once $filename;
581
582
583
        $reflection = new \ReflectionProperty($metadata->name, 'id');
584
        $docComment = $reflection->getDocComment();
585
586
        $this->assertContains('@Id', $docComment);
587
        $this->assertContains('@Column(name="id", type="integer")', $docComment);
588
        $this->assertContains('@GeneratedValue(strategy="SEQUENCE")', $docComment);
589
        $this->assertContains('@SequenceGenerator(sequenceName="DDC1784_ID_SEQ", allocationSize=1, initialValue=2)', $docComment);
590
    }
591
592
    /**
593
     * @group DDC-2079
594
     */
595
    public function testGenerateEntityWithMultipleInverseJoinColumns()
596
    {
597
        $metadata               = new ClassMetadataInfo($this->_namespace . '\DDC2079Entity');
598
        $metadata->namespace    = $this->_namespace;
599
        $metadata->mapField(['fieldName' => 'id', 'type' => 'integer', 'id' => true]);
600
        $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE);
601
        $metadata->mapManyToMany(
602
            [
603
            'fieldName'     => 'centroCustos',
604
            'targetEntity'  => 'DDC2079CentroCusto',
605
            'joinTable'     => [
606
                'name'                  => 'unidade_centro_custo',
607
                'joinColumns'           => [
608
                    ['name' => 'idorcamento',      'referencedColumnName' => 'idorcamento'],
609
                    ['name' => 'idunidade',        'referencedColumnName' => 'idunidade']
610
                ],
611
                'inverseJoinColumns'    => [
612
                    ['name' => 'idcentrocusto',    'referencedColumnName' => 'idcentrocusto'],
613
                    ['name' => 'idpais',           'referencedColumnName' => 'idpais'],
614
                ],
615
            ],
616
            ]
617
        );
618
        $this->_generator->writeEntityClass($metadata, $this->_tmpDir);
619
620
        $filename = $this->_tmpDir . DIRECTORY_SEPARATOR
621
            . $this->_namespace . DIRECTORY_SEPARATOR . 'DDC2079Entity.php';
622
623
        $this->assertFileExists($filename);
624
        require_once $filename;
625
626
        $property   = new \ReflectionProperty($metadata->name, 'centroCustos');
627
        $docComment = $property->getDocComment();
628
629
        //joinColumns
630
        $this->assertContains('@JoinColumn(name="idorcamento", referencedColumnName="idorcamento"),', $docComment);
631
        $this->assertContains('@JoinColumn(name="idunidade", referencedColumnName="idunidade")', $docComment);
632
        //inverseJoinColumns
633
        $this->assertContains('@JoinColumn(name="idcentrocusto", referencedColumnName="idcentrocusto"),', $docComment);
634
        $this->assertContains('@JoinColumn(name="idpais", referencedColumnName="idpais")', $docComment);
635
636
    }
637
638
     /**
639
     * @group DDC-2172
640
     */
641 View Code Duplication
    public function testGetInheritanceTypeString()
642
    {
643
        $reflection = new \ReflectionClass('\Doctrine\ORM\Mapping\ClassMetadataInfo');
644
        $method     = new \ReflectionMethod($this->_generator, 'getInheritanceTypeString');
645
        $constants  = $reflection->getConstants();
646
        $pattern    = '/^INHERITANCE_TYPE_/';
647
648
        $method->setAccessible(true);
649
650
        foreach ($constants as $name => $value) {
651
            if( ! preg_match($pattern, $name)) {
652
                continue;
653
            }
654
655
            $expected = preg_replace($pattern, '', $name);
656
            $actual   = $method->invoke($this->_generator, $value);
657
658
            $this->assertEquals($expected, $actual);
659
        }
660
661
        $this->expectException(\InvalidArgumentException::class);
662
        $this->expectExceptionMessage('Invalid provided InheritanceType: INVALID');
663
664
        $method->invoke($this->_generator, 'INVALID');
665
    }
666
667
    /**
668
    * @group DDC-2172
669
    */
670 View Code Duplication
    public function testGetChangeTrackingPolicyString()
671
    {
672
        $reflection = new \ReflectionClass('\Doctrine\ORM\Mapping\ClassMetadata');
673
        $method     = new \ReflectionMethod($this->_generator, 'getChangeTrackingPolicyString');
674
        $constants  = $reflection->getConstants();
675
        $pattern    = '/^CHANGETRACKING_/';
676
677
        $method->setAccessible(true);
678
679
        foreach ($constants as $name => $value) {
680
            if( ! preg_match($pattern, $name)) {
681
                continue;
682
            }
683
684
            $expected = preg_replace($pattern, '', $name);
685
            $actual   = $method->invoke($this->_generator, $value);
686
687
            $this->assertEquals($expected, $actual);
688
        }
689
690
        $this->expectException(\InvalidArgumentException::class);
691
        $this->expectExceptionMessage('Invalid provided ChangeTrackingPolicy: INVALID');
692
693
        $method->invoke($this->_generator, 'INVALID');
694
    }
695
696
    /**
697
     * @group DDC-2172
698
     */
699 View Code Duplication
    public function testGetIdGeneratorTypeString()
700
    {
701
        $reflection = new \ReflectionClass('\Doctrine\ORM\Mapping\ClassMetadataInfo');
702
        $method     = new \ReflectionMethod($this->_generator, 'getIdGeneratorTypeString');
703
        $constants  = $reflection->getConstants();
704
        $pattern    = '/^GENERATOR_TYPE_/';
705
706
        $method->setAccessible(true);
707
708
        foreach ($constants as $name => $value) {
709
            if( ! preg_match($pattern, $name)) {
710
                continue;
711
            }
712
713
            $expected = preg_replace($pattern, '', $name);
714
            $actual   = $method->invoke($this->_generator, $value);
715
716
            $this->assertEquals($expected, $actual);
717
        }
718
719
        $this->expectException(\InvalidArgumentException::class);
720
        $this->expectExceptionMessage('Invalid provided IdGeneratorType: INVALID');
721
722
        $method->invoke($this->_generator, 'INVALID');
723
    }
724
725
    /**
726
     * @dataProvider getEntityTypeAliasDataProvider
727
     *
728
     * @group DDC-1694
729
     */
730
    public function testEntityTypeAlias(array $field)
731
    {
732
        $metadata   = $this->generateEntityTypeFixture($field);
733
        $path       = $this->_tmpDir . '/'. $this->_namespace . '/EntityType.php';
734
735
        $this->assertFileExists($path);
736
        require_once $path;
737
738
        $entity     = new $metadata->name;
739
        $reflClass  = new \ReflectionClass($metadata->name);
740
741
        $type   = $field['phpType'];
742
        $name   = $field['fieldName'];
743
        $value  = $field['value'];
744
        $getter = "get" . ucfirst($name);
745
        $setter = "set" . ucfirst($name);
746
747
        $this->assertPhpDocVarType($type, $reflClass->getProperty($name));
748
        $this->assertPhpDocParamType($type, $reflClass->getMethod($setter));
749
        $this->assertPhpDocReturnType($type, $reflClass->getMethod($getter));
750
751
        $this->assertSame($entity, $entity->{$setter}($value));
752
        $this->assertEquals($value, $entity->{$getter}());
753
    }
754
755
    /**
756
     * @group DDC-2372
757
     */
758 View Code Duplication
    public function testTraitPropertiesAndMethodsAreNotDuplicated()
759
    {
760
        $cmf = new ClassMetadataFactory();
761
        $em = $this->_getTestEntityManager();
762
        $cmf->setEntityManager($em);
763
764
        $user = new DDC2372User();
765
        $metadata = $cmf->getMetadataFor(get_class($user));
766
        $metadata->name = $this->_namespace . "\DDC2372User";
0 ignored issues
show
Bug introduced by
Accessing name 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...
767
        $metadata->namespace = $this->_namespace;
0 ignored issues
show
Bug introduced by
Accessing namespace 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...
768
769
        $this->_generator->writeEntityClass($metadata, $this->_tmpDir);
0 ignored issues
show
Compatibility introduced by
$metadata of type object<Doctrine\Common\P...\Mapping\ClassMetadata> is not a sub-type of object<Doctrine\ORM\Mapping\ClassMetadataInfo>. It seems like you assume a concrete implementation of the interface Doctrine\Common\Persistence\Mapping\ClassMetadata to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
770
771
        $this->assertFileExists($this->_tmpDir . "/" . $this->_namespace . "/DDC2372User.php");
772
        require $this->_tmpDir . "/" . $this->_namespace . "/DDC2372User.php";
773
774
        $reflClass = new \ReflectionClass($metadata->name);
0 ignored issues
show
Bug introduced by
Accessing name 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...
775
776
        $this->assertSame($reflClass->hasProperty('address'), false);
777
        $this->assertSame($reflClass->hasMethod('setAddress'), false);
778
        $this->assertSame($reflClass->hasMethod('getAddress'), false);
779
    }
780
781
    /**
782
     * @group DDC-2372
783
     */
784 View Code Duplication
    public function testTraitPropertiesAndMethodsAreNotDuplicatedInChildClasses()
785
    {
786
        $cmf = new ClassMetadataFactory();
787
        $em = $this->_getTestEntityManager();
788
        $cmf->setEntityManager($em);
789
790
        $user = new DDC2372Admin();
791
        $metadata = $cmf->getMetadataFor(get_class($user));
792
        $metadata->name = $this->_namespace . "\DDC2372Admin";
0 ignored issues
show
Bug introduced by
Accessing name 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...
793
        $metadata->namespace = $this->_namespace;
0 ignored issues
show
Bug introduced by
Accessing namespace 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...
794
795
        $this->_generator->writeEntityClass($metadata, $this->_tmpDir);
0 ignored issues
show
Compatibility introduced by
$metadata of type object<Doctrine\Common\P...\Mapping\ClassMetadata> is not a sub-type of object<Doctrine\ORM\Mapping\ClassMetadataInfo>. It seems like you assume a concrete implementation of the interface Doctrine\Common\Persistence\Mapping\ClassMetadata to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
796
797
        $this->assertFileExists($this->_tmpDir . "/" . $this->_namespace . "/DDC2372Admin.php");
798
        require $this->_tmpDir . "/" . $this->_namespace . "/DDC2372Admin.php";
799
800
        $reflClass = new \ReflectionClass($metadata->name);
0 ignored issues
show
Bug introduced by
Accessing name 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...
801
802
        $this->assertSame($reflClass->hasProperty('address'), false);
803
        $this->assertSame($reflClass->hasMethod('setAddress'), false);
804
        $this->assertSame($reflClass->hasMethod('getAddress'), false);
805
    }
806
807
    /**
808
     * @group DDC-1590
809
     */
810
    public function testMethodsAndPropertiesAreNotDuplicatedInChildClasses()
811
    {
812
        $cmf    = new ClassMetadataFactory();
813
        $em     = $this->_getTestEntityManager();
814
815
        $cmf->setEntityManager($em);
816
817
        $ns     = $this->_namespace;
818
        $nsdir  = $this->_tmpDir . '/' . $ns;
819
820
        $content = str_replace(
821
            'namespace Doctrine\Tests\Models\DDC1590',
822
            'namespace ' . $ns,
823
            file_get_contents(__DIR__ . '/../../Models/DDC1590/DDC1590User.php')
824
        );
825
826
        $fname = $nsdir . "/DDC1590User.php";
827
        file_put_contents($fname, $content);
828
        require $fname;
829
830
831
        $metadata = $cmf->getMetadataFor($ns . '\DDC1590User');
832
        $this->_generator->writeEntityClass($metadata, $this->_tmpDir);
0 ignored issues
show
Compatibility introduced by
$metadata of type object<Doctrine\Common\P...\Mapping\ClassMetadata> is not a sub-type of object<Doctrine\ORM\Mapping\ClassMetadataInfo>. It seems like you assume a concrete implementation of the interface Doctrine\Common\Persistence\Mapping\ClassMetadata to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
833
834
        // class DDC1590User extends DDC1590Entity { ... }
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% of this comment could be valid code. Did you maybe forget this after debugging?

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

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

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

Loading history...
835
        $source = file_get_contents($fname);
836
837
        // class _DDC1590User extends DDC1590Entity { ... }
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% of this comment could be valid code. Did you maybe forget this after debugging?

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

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

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

Loading history...
838
        $source2    = str_replace('class DDC1590User', 'class _DDC1590User', $source);
839
        $fname2     = $nsdir . "/_DDC1590User.php";
840
        file_put_contents($fname2, $source2);
841
        require $fname2;
842
843
        // class __DDC1590User { ... }
0 ignored issues
show
Unused Code Comprehensibility introduced by
40% of this comment could be valid code. Did you maybe forget this after debugging?

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

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

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

Loading history...
844
        $source3    = str_replace('class DDC1590User extends DDC1590Entity', 'class __DDC1590User', $source);
845
        $fname3     = $nsdir . "/__DDC1590User.php";
846
        file_put_contents($fname3, $source3);
847
        require $fname3;
848
849
850
        // class _DDC1590User extends DDC1590Entity { ... }
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% of this comment could be valid code. Did you maybe forget this after debugging?

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

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

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

Loading history...
851
        $rc2 = new \ReflectionClass($ns.'\_DDC1590User');
852
853
        $this->assertTrue($rc2->hasProperty('name'));
854
        $this->assertTrue($rc2->hasProperty('id'));
855
        $this->assertTrue($rc2->hasProperty('created_at'));
856
857
        $this->assertTrue($rc2->hasMethod('getName'));
858
        $this->assertTrue($rc2->hasMethod('setName'));
859
        $this->assertTrue($rc2->hasMethod('getId'));
860
        $this->assertFalse($rc2->hasMethod('setId'));
861
        $this->assertTrue($rc2->hasMethod('getCreatedAt'));
862
        $this->assertTrue($rc2->hasMethod('setCreatedAt'));
863
864
865
        // class __DDC1590User { ... }
0 ignored issues
show
Unused Code Comprehensibility introduced by
40% of this comment could be valid code. Did you maybe forget this after debugging?

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

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

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

Loading history...
866
        $rc3 = new \ReflectionClass($ns.'\__DDC1590User');
867
868
        $this->assertTrue($rc3->hasProperty('name'));
869
        $this->assertFalse($rc3->hasProperty('id'));
870
        $this->assertFalse($rc3->hasProperty('created_at'));
871
872
        $this->assertTrue($rc3->hasMethod('getName'));
873
        $this->assertTrue($rc3->hasMethod('setName'));
874
        $this->assertFalse($rc3->hasMethod('getId'));
875
        $this->assertFalse($rc3->hasMethod('setId'));
876
        $this->assertFalse($rc3->hasMethod('getCreatedAt'));
877
        $this->assertFalse($rc3->hasMethod('setCreatedAt'));
878
    }
879
880
    /**
881
     * @group DDC-3304
882
     */
883
    public function testGeneratedMutableEmbeddablesClass()
884
    {
885
        $embeddedMetadata = $this->generateTestEmbeddableFixture();
886
        $metadata = $this->generateIsbnEmbeddableFixture(['test' => $embeddedMetadata]);
887
888
        $isbn = $this->newInstance($metadata);
889
890
        $this->assertTrue(class_exists($metadata->name), "Class does not exist.");
891
        $this->assertFalse(method_exists($metadata->name, '__construct'), "EntityGeneratorIsbn::__construct present.");
892
        $this->assertTrue(method_exists($metadata->name, 'getPrefix'), "EntityGeneratorIsbn::getPrefix() missing.");
893
        $this->assertTrue(method_exists($metadata->name, 'setPrefix'), "EntityGeneratorIsbn::setPrefix() missing.");
894
        $this->assertTrue(method_exists($metadata->name, 'getGroupNumber'), "EntityGeneratorIsbn::getGroupNumber() missing.");
895
        $this->assertTrue(method_exists($metadata->name, 'setGroupNumber'), "EntityGeneratorIsbn::setGroupNumber() missing.");
896
        $this->assertTrue(method_exists($metadata->name, 'getPublisherNumber'), "EntityGeneratorIsbn::getPublisherNumber() missing.");
897
        $this->assertTrue(method_exists($metadata->name, 'setPublisherNumber'), "EntityGeneratorIsbn::setPublisherNumber() missing.");
898
        $this->assertTrue(method_exists($metadata->name, 'getTitleNumber'), "EntityGeneratorIsbn::getTitleNumber() missing.");
899
        $this->assertTrue(method_exists($metadata->name, 'setTitleNumber'), "EntityGeneratorIsbn::setTitleNumber() missing.");
900
        $this->assertTrue(method_exists($metadata->name, 'getCheckDigit'), "EntityGeneratorIsbn::getCheckDigit() missing.");
901
        $this->assertTrue(method_exists($metadata->name, 'setCheckDigit'), "EntityGeneratorIsbn::setCheckDigit() missing.");
902
        $this->assertTrue(method_exists($metadata->name, 'getTest'), "EntityGeneratorIsbn::getTest() missing.");
903
        $this->assertTrue(method_exists($metadata->name, 'setTest'), "EntityGeneratorIsbn::setTest() missing.");
904
905
        $isbn->setPrefix(978);
906
        $this->assertSame(978, $isbn->getPrefix());
907
908
        $this->newInstance($embeddedMetadata);
909
        $test = new $embeddedMetadata->name();
910
911
        $isbn->setTest($test);
912
        $this->assertSame($test, $isbn->getTest());
913
914
        $reflMethod = new \ReflectionMethod($metadata->name, 'setTest');
915
        $reflParameters = $reflMethod->getParameters();
916
        $this->assertEquals($embeddedMetadata->name, $reflParameters[0]->getClass()->name);
917
    }
918
919
    /**
920
     * @group DDC-3304
921
     */
922
    public function testGeneratedImmutableEmbeddablesClass()
923
    {
924
        $this->_generator->setEmbeddablesImmutable(true);
925
        $embeddedMetadata = $this->generateTestEmbeddableFixture();
926
        $metadata = $this->generateIsbnEmbeddableFixture(['test' => $embeddedMetadata]);
927
928
        $this->loadEntityClass($embeddedMetadata);
929
        $this->loadEntityClass($metadata);
930
931
        $this->assertTrue(class_exists($metadata->name), "Class does not exist.");
932
        $this->assertTrue(method_exists($metadata->name, '__construct'), "EntityGeneratorIsbn::__construct missing.");
933
        $this->assertTrue(method_exists($metadata->name, 'getPrefix'), "EntityGeneratorIsbn::getPrefix() missing.");
934
        $this->assertFalse(method_exists($metadata->name, 'setPrefix'), "EntityGeneratorIsbn::setPrefix() present.");
935
        $this->assertTrue(method_exists($metadata->name, 'getGroupNumber'), "EntityGeneratorIsbn::getGroupNumber() missing.");
936
        $this->assertFalse(method_exists($metadata->name, 'setGroupNumber'), "EntityGeneratorIsbn::setGroupNumber() present.");
937
        $this->assertTrue(method_exists($metadata->name, 'getPublisherNumber'), "EntityGeneratorIsbn::getPublisherNumber() missing.");
938
        $this->assertFalse(method_exists($metadata->name, 'setPublisherNumber'), "EntityGeneratorIsbn::setPublisherNumber() present.");
939
        $this->assertTrue(method_exists($metadata->name, 'getTitleNumber'), "EntityGeneratorIsbn::getTitleNumber() missing.");
940
        $this->assertFalse(method_exists($metadata->name, 'setTitleNumber'), "EntityGeneratorIsbn::setTitleNumber() present.");
941
        $this->assertTrue(method_exists($metadata->name, 'getCheckDigit'), "EntityGeneratorIsbn::getCheckDigit() missing.");
942
        $this->assertFalse(method_exists($metadata->name, 'setCheckDigit'), "EntityGeneratorIsbn::setCheckDigit() present.");
943
        $this->assertTrue(method_exists($metadata->name, 'getTest'), "EntityGeneratorIsbn::getTest() missing.");
944
        $this->assertFalse(method_exists($metadata->name, 'setTest'), "EntityGeneratorIsbn::setTest() present.");
945
946
        $test = new $embeddedMetadata->name(1, new \DateTime());
947
        $isbn = new $metadata->name($test, 978, 3, 12, 732320, 83);
948
949
        $reflMethod = new \ReflectionMethod($isbn, '__construct');
950
        $reflParameters = $reflMethod->getParameters();
951
952
        $this->assertCount(6, $reflParameters);
953
954
        $this->assertSame($embeddedMetadata->name, $reflParameters[0]->getClass()->name);
955
        $this->assertSame('test', $reflParameters[0]->getName());
0 ignored issues
show
Bug introduced by
Consider using $reflParameters[0]->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
956
        $this->assertFalse($reflParameters[0]->isOptional());
957
958
        $this->assertSame('prefix', $reflParameters[1]->getName());
0 ignored issues
show
Bug introduced by
Consider using $reflParameters[1]->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
959
        $this->assertFalse($reflParameters[1]->isOptional());
960
961
        $this->assertSame('groupNumber', $reflParameters[2]->getName());
0 ignored issues
show
Bug introduced by
Consider using $reflParameters[2]->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
962
        $this->assertFalse($reflParameters[2]->isOptional());
963
964
        $this->assertSame('publisherNumber', $reflParameters[3]->getName());
0 ignored issues
show
Bug introduced by
Consider using $reflParameters[3]->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
965
        $this->assertFalse($reflParameters[3]->isOptional());
966
967
        $this->assertSame('titleNumber', $reflParameters[4]->getName());
0 ignored issues
show
Bug introduced by
Consider using $reflParameters[4]->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
968
        $this->assertFalse($reflParameters[4]->isOptional());
969
970
        $this->assertSame('checkDigit', $reflParameters[5]->getName());
0 ignored issues
show
Bug introduced by
Consider using $reflParameters[5]->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
971
        $this->assertFalse($reflParameters[5]->isOptional());
972
973
        $reflMethod = new \ReflectionMethod($test, '__construct');
974
        $reflParameters = $reflMethod->getParameters();
975
976
        $this->assertCount(4, $reflParameters);
977
978
        $this->assertSame('field1', $reflParameters[0]->getName());
0 ignored issues
show
Bug introduced by
Consider using $reflParameters[0]->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
979
        $this->assertFalse($reflParameters[0]->isOptional());
980
981
        $this->assertSame('DateTime', $reflParameters[1]->getClass()->name);
982
        $this->assertSame('field3', $reflParameters[1]->getName());
0 ignored issues
show
Bug introduced by
Consider using $reflParameters[1]->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
983
        $this->assertFalse($reflParameters[1]->isOptional());
984
985
        $this->assertSame('field2', $reflParameters[2]->getName());
0 ignored issues
show
Bug introduced by
Consider using $reflParameters[2]->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
986
        $this->assertTrue($reflParameters[2]->isOptional());
987
988
        $this->assertSame('DateTime', $reflParameters[3]->getClass()->name);
989
        $this->assertSame('field4', $reflParameters[3]->getName());
0 ignored issues
show
Bug introduced by
Consider using $reflParameters[3]->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
990
        $this->assertTrue($reflParameters[3]->isOptional());
991
    }
992
993
    public function testRegenerateEntityClass()
994
    {
995
        $metadata = $this->generateBookEntityFixture();
996
        $this->loadEntityClass($metadata);
997
998
        $className = basename(str_replace('\\', '/', $metadata->name));
999
        $path = $this->_tmpDir . '/' . $this->_namespace . '/' . $className . '.php';
1000
        $classTest = file_get_contents($path);
1001
1002
        $this->_generator->setRegenerateEntityIfExists(true);
1003
        $this->_generator->setBackupExisting(false);
1004
1005
        $this->_generator->writeEntityClass($metadata, $this->_tmpDir);
1006
        $classNew = file_get_contents($path);
1007
1008
        $this->assertSame($classTest,$classNew);
1009
    }
1010
1011
    public function testGenerateMethodsTypeHinting()
1012
    {
1013
        if (version_compare(PHP_VERSION, '7.0.0', '<')) {
1014
            $this->markTestSkipped('Scalar type hinting and method return types are available in PHP >= 7.0.0');
1015
        }
1016
1017
        $this->_generator->setGenerateMethodsTypeHinting(true);
1018
1019
        $metadata = $this->generateBookEntityFixture();
1020
        $this->loadEntityClass($metadata);
1021
1022
        $reflClass = new \ReflectionClass($metadata->name);
1023
1024
        $this->assertCount(5, $reflClass->getProperties());
1025
        $this->assertCount(13, $reflClass->getMethods());
1026
1027
        $reflMethod = new \ReflectionMethod($metadata->name, 'getId');
1028
        $this->assertEquals('int', $reflMethod->getReturnType());
1029
1030
        $reflMethod = new \ReflectionMethod($metadata->name, 'setName');
1031
        $parameters = $reflMethod->getParameters();
1032
        $this->assertEquals(1, count($parameters));
1033
        $this->assertEquals('string', $parameters[0]->getType());
1034
        $this->assertEquals('self', $reflMethod->getReturnType());
1035
1036
        $reflMethod = new \ReflectionMethod($metadata->name, 'getName');
1037
        $this->assertEquals('string', $reflMethod->getReturnType());
1038
1039
        $reflMethod = new \ReflectionMethod($metadata->name, 'setStatus');
1040
        $parameters = $reflMethod->getParameters();
1041
        $this->assertEquals(1, count($parameters));
1042
        $this->assertEquals('string', $parameters[0]->getType());
1043
        $this->assertEquals('self', $reflMethod->getReturnType());
1044
1045
        $reflMethod = new \ReflectionMethod($metadata->name, 'getStatus');
1046
        $this->assertEquals('string', $reflMethod->getReturnType());
1047
1048
        $authorClass = get_class(new EntityGeneratorAuthor());
1049
        $reflMethod = new \ReflectionMethod($metadata->name, 'setAuthor');
1050
        $parameters = $reflMethod->getParameters();
1051
        $this->assertEquals(1, count($parameters));
1052
        $this->assertEquals($authorClass, (string) $parameters[0]->getType());
1053
        $this->assertEquals('self', $reflMethod->getReturnType());
1054
1055
        $reflMethod = new \ReflectionMethod($metadata->name, 'getAuthor');
1056
        $this->assertNull($reflMethod->getReturnType());
1057
1058
        $reflMethod = new \ReflectionMethod($metadata->name, 'addComment');
1059
        $this->assertEquals('self', $reflMethod->getReturnType());
1060
1061
        $reflMethod = new \ReflectionMethod($metadata->name, 'removeComment');
1062
        $this->assertEquals('bool', $reflMethod->getReturnType());
1063
1064
        $reflMethod = new \ReflectionMethod($metadata->name, 'getComments');
1065
        $this->assertEquals('Doctrine\Common\Collections\Collection', $reflMethod->getReturnType());
1066
1067
        $reflMethod = new \ReflectionMethod($metadata->name, 'loading');
1068
        $this->assertNull($reflMethod->getReturnType());
1069
1070
        $reflMethod = new \ReflectionMethod($metadata->name, 'willBeRemoved');
1071
        $this->assertNull($reflMethod->getReturnType());
1072
    }
1073
1074
    /**
1075
     * @dataProvider getEntityTypeAliasDataProvider
1076
     */
1077
    public function testEntityMethodTypeHintingAlias(array $field)
1078
    {
1079
        $this->_generator->setGenerateMethodsTypeHinting(true);
1080
1081
        $metadata   = $this->generateEntityTypeFixture($field);
1082
        $path       = $this->_tmpDir . '/'. $this->_namespace . '/EntityType.php';
1083
1084
        $this->assertFileExists($path);
1085
        require_once $path;
1086
1087
        $type   = $field['phpType'];
1088
        if ('\\' === $type[0]) {
1089
            $type = substr($type, 1);
1090
        }
1091
1092
        $name   = $field['fieldName'];
1093
        $getter = "get" . ucfirst($name);
1094
        $setter = "set" . ucfirst($name);
1095
1096
        $reflMethod = new \ReflectionMethod($metadata->name, $setter);
1097
        $parameters = $reflMethod->getParameters();
1098
        $this->assertEquals(1, count($parameters));
1099
        $this->assertEquals($type, $parameters[0]->getType());
1100
        $this->assertEquals('self', $reflMethod->getReturnType());
1101
1102
        $reflMethod = new \ReflectionMethod($metadata->name, $getter);
1103
        $this->assertEquals($type, (string) $reflMethod->getReturnType());
1104
    }
1105
1106
    /**
1107
     * @return array
1108
     */
1109
    public function getEntityTypeAliasDataProvider()
1110
    {
1111
        return [
1112
            [
1113
                [
1114
                'fieldName' => 'datetimetz',
1115
                'phpType' => '\\DateTime',
1116
                'dbType' => 'datetimetz',
1117
                'value' => new \DateTime
1118
                ]
1119
            ],
1120
            [
1121
                [
1122
                'fieldName' => 'datetime',
1123
                'phpType' => '\\DateTime',
1124
                'dbType' => 'datetime',
1125
                'value' => new \DateTime
1126
                ]
1127
            ],
1128
            [
1129
                [
1130
                'fieldName' => 'date',
1131
                'phpType' => '\\DateTime',
1132
                'dbType' => 'date',
1133
                'value' => new \DateTime
1134
                ]
1135
            ],
1136
            [
1137
                [
1138
                'fieldName' => 'time',
1139
                'phpType' => '\DateTime',
1140
                'dbType' => 'time',
1141
                'value' => new \DateTime
1142
                ]
1143
            ],
1144
            [
1145
                [
1146
                'fieldName' => 'object',
1147
                'phpType' => '\stdClass',
1148
                'dbType' => 'object',
1149
                'value' => new \stdClass()
1150
                ]
1151
            ],
1152
            [
1153
                [
1154
                'fieldName' => 'bigint',
1155
                'phpType' => 'int',
1156
                'dbType' => 'bigint',
1157
                'value' => 11
1158
                ]
1159
            ],
1160
            [
1161
                [
1162
                'fieldName' => 'smallint',
1163
                'phpType' => 'int',
1164
                'dbType' => 'smallint',
1165
                'value' => 22
1166
                ]
1167
            ],
1168
            [
1169
                [
1170
                'fieldName' => 'text',
1171
                'phpType' => 'string',
1172
                'dbType' => 'text',
1173
                'value' => 'text'
1174
                ]
1175
            ],
1176
            [
1177
                [
1178
                'fieldName' => 'blob',
1179
                'phpType' => 'string',
1180
                'dbType' => 'blob',
1181
                'value' => 'blob'
1182
                ]
1183
            ],
1184
            [
1185
                [
1186
                'fieldName' => 'decimal',
1187
                'phpType' => 'string',
1188
                'dbType' => 'decimal',
1189
                'value' => '12.34'
1190
                ],
1191
            ]
1192
        ];
1193
    }
1194
1195
    public function getParseTokensInEntityFileData()
1196
    {
1197
        return [
1198
            [
1199
                '<?php namespace Foo\Bar; class Baz {}',
1200
                ['Foo\Bar\Baz'],
1201
            ],
1202
            [
1203
                '<?php namespace Foo\Bar; use Foo; class Baz {}',
1204
                ['Foo\Bar\Baz'],
1205
            ],
1206
            [
1207
                '<?php namespace /*Comment*/ Foo\Bar; /** Foo */class /* Comment */ Baz {}',
1208
                ['Foo\Bar\Baz'],
1209
            ],
1210
            [
1211
                '
1212
<?php namespace
1213
/*Comment*/
1214
Foo\Bar
1215
;
1216
1217
/** Foo */
1218
class
1219
/* Comment */
1220
 Baz {}
1221
     ',
1222
                ['Foo\Bar\Baz'],
1223
            ],
1224
            [
1225
                '
1226
<?php namespace Foo\Bar; class Baz {
1227
    public static function someMethod(){
1228
        return self::class;
1229
    }
1230
}
1231
',
1232
                ['Foo\Bar\Baz'],
1233
            ],
1234
        ];
1235
    }
1236
1237
    /**
1238
     * @param string $type
1239
     * @param \ReflectionProperty $property
1240
     */
1241 View Code Duplication
    private function assertPhpDocVarType($type, \ReflectionProperty $property)
1242
    {
1243
        $docComment = $property->getDocComment();
1244
        $regex      = '/@var\s+([\S]+)$/m';
1245
1246
        $this->assertRegExp($regex, $docComment);
1247
        $this->assertEquals(1, preg_match($regex, $docComment, $matches));
1248
        $this->assertEquals($type, $matches[1]);
1249
    }
1250
1251
    /**
1252
     * @param string $type
1253
     * @param \ReflectionMethod $method
1254
     */
1255 View Code Duplication
    private function assertPhpDocReturnType($type, \ReflectionMethod $method)
1256
    {
1257
        $docComment = $method->getDocComment();
1258
        $regex      = '/@return\s+([\S]+)(\s+.*)$/m';
1259
1260
        $this->assertRegExp($regex, $docComment);
1261
        $this->assertEquals(1, preg_match($regex, $docComment, $matches));
1262
        $this->assertEquals($type, $matches[1]);
1263
    }
1264
1265
    /**
1266
     * @param string $type
1267
     * @param \ReflectionProperty $method
1268
     */
1269
    private function assertPhpDocParamType($type, \ReflectionMethod $method)
1270
    {
1271
        $this->assertEquals(1, preg_match('/@param\s+([^\s]+)/', $method->getDocComment(), $matches));
1272
        $this->assertEquals($type, $matches[1]);
1273
    }
1274
}
1275
1276
class EntityGeneratorAuthor {}
1277
class EntityGeneratorComment {}
1278