These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
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 | View Code Duplication | 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->setUpdateEntityIfExists(true); |
||
37 | $this->_generator->setFieldVisibility(EntityGenerator::FIELD_VISIBLE_PROTECTED); |
||
38 | } |
||
39 | |||
40 | public function tearDown() |
||
41 | { |
||
42 | $ri = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->_tmpDir . '/' . $this->_namespace)); |
||
43 | foreach ($ri AS $file) { |
||
44 | /* @var $file \SplFileInfo */ |
||
45 | if ($file->isFile()) { |
||
46 | \unlink($file->getPathname()); |
||
47 | } |
||
48 | } |
||
49 | rmdir($this->_tmpDir . '/' . $this->_namespace); |
||
50 | } |
||
51 | |||
52 | /** |
||
53 | * @param ClassMetadataInfo[] $embeddedClasses |
||
54 | * |
||
55 | * @return ClassMetadataInfo |
||
56 | */ |
||
57 | public function generateBookEntityFixture(array $embeddedClasses = []) |
||
58 | { |
||
59 | $metadata = new ClassMetadataInfo($this->_namespace . '\EntityGeneratorBook'); |
||
60 | $metadata->namespace = $this->_namespace; |
||
61 | $metadata->customRepositoryClassName = $this->_namespace . '\EntityGeneratorBookRepository'; |
||
62 | |||
63 | $metadata->table['name'] = 'book'; |
||
64 | $metadata->table['uniqueConstraints']['name_uniq'] = ['columns' => ['name']]; |
||
65 | $metadata->table['indexes']['status_idx'] = ['columns' => ['status']]; |
||
66 | $metadata->mapField(['fieldName' => 'name', 'type' => 'string']); |
||
67 | $metadata->mapField(['fieldName' => 'status', 'type' => 'string', 'options' => ['default' => 'published']]); |
||
68 | $metadata->mapField(['fieldName' => 'id', 'type' => 'integer', 'id' => true]); |
||
69 | $metadata->mapOneToOne( |
||
70 | ['fieldName' => 'author', 'targetEntity' => EntityGeneratorAuthor::class, 'mappedBy' => 'book'] |
||
71 | ); |
||
72 | $joinColumns = [ |
||
73 | ['name' => 'author_id', 'referencedColumnName' => 'id'] |
||
74 | ]; |
||
75 | $metadata->mapManyToMany( |
||
76 | [ |
||
77 | 'fieldName' => 'comments', |
||
78 | 'targetEntity' => EntityGeneratorComment::class, |
||
79 | 'fetch' => ClassMetadataInfo::FETCH_EXTRA_LAZY, |
||
80 | 'joinTable' => [ |
||
81 | 'name' => 'book_comment', |
||
82 | 'joinColumns' => [['name' => 'book_id', 'referencedColumnName' => 'id']], |
||
83 | 'inverseJoinColumns' => [['name' => 'comment_id', 'referencedColumnName' => 'id']], |
||
84 | ], |
||
85 | ] |
||
86 | ); |
||
87 | $metadata->addLifecycleCallback('loading', 'postLoad'); |
||
88 | $metadata->addLifecycleCallback('willBeRemoved', 'preRemove'); |
||
89 | $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO); |
||
90 | |||
91 | foreach ($embeddedClasses as $fieldName => $embeddedClass) { |
||
92 | $this->mapNestedEmbedded($fieldName, $metadata, $embeddedClass); |
||
93 | $this->mapEmbedded($fieldName, $metadata, $embeddedClass); |
||
94 | } |
||
95 | |||
96 | $this->_generator->writeEntityClass($metadata, $this->_tmpDir); |
||
97 | |||
98 | return $metadata; |
||
99 | } |
||
100 | |||
101 | private function generateEntityTypeFixture(array $field) |
||
102 | { |
||
103 | $metadata = new ClassMetadataInfo($this->_namespace . '\EntityType'); |
||
104 | $metadata->namespace = $this->_namespace; |
||
105 | |||
106 | $metadata->table['name'] = 'entity_type'; |
||
107 | $metadata->mapField(['fieldName' => 'id', 'type' => 'integer', 'id' => true]); |
||
108 | $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO); |
||
109 | |||
110 | $name = $field['fieldName']; |
||
111 | $type = $field['dbType']; |
||
112 | $metadata->mapField(['fieldName' => $name, 'type' => $type]); |
||
113 | |||
114 | $this->_generator->writeEntityClass($metadata, $this->_tmpDir); |
||
115 | |||
116 | return $metadata; |
||
117 | } |
||
118 | |||
119 | /** |
||
120 | * @return ClassMetadataInfo |
||
121 | */ |
||
122 | private function generateIsbnEmbeddableFixture(array $embeddedClasses = [], $columnPrefix = null) |
||
123 | { |
||
124 | $metadata = new ClassMetadataInfo($this->_namespace . '\EntityGeneratorIsbn'); |
||
125 | $metadata->namespace = $this->_namespace; |
||
126 | $metadata->isEmbeddedClass = true; |
||
127 | $metadata->mapField(['fieldName' => 'prefix', 'type' => 'integer']); |
||
128 | $metadata->mapField(['fieldName' => 'groupNumber', 'type' => 'integer']); |
||
129 | $metadata->mapField(['fieldName' => 'publisherNumber', 'type' => 'integer']); |
||
130 | $metadata->mapField(['fieldName' => 'titleNumber', 'type' => 'integer']); |
||
131 | $metadata->mapField(['fieldName' => 'checkDigit', 'type' => 'integer']); |
||
132 | |||
133 | foreach ($embeddedClasses as $fieldName => $embeddedClass) { |
||
134 | $this->mapEmbedded($fieldName, $metadata, $embeddedClass, $columnPrefix); |
||
135 | } |
||
136 | |||
137 | $this->_generator->writeEntityClass($metadata, $this->_tmpDir); |
||
138 | |||
139 | return $metadata; |
||
140 | } |
||
141 | |||
142 | /** |
||
143 | * @return ClassMetadataInfo |
||
144 | */ |
||
145 | private function generateTestEmbeddableFixture() |
||
146 | { |
||
147 | $metadata = new ClassMetadataInfo($this->_namespace . '\EntityGeneratorTestEmbeddable'); |
||
148 | $metadata->namespace = $this->_namespace; |
||
149 | $metadata->isEmbeddedClass = true; |
||
150 | $metadata->mapField(['fieldName' => 'field1', 'type' => 'integer']); |
||
151 | $metadata->mapField(['fieldName' => 'field2', 'type' => 'integer', 'nullable' => true]); |
||
152 | $metadata->mapField(['fieldName' => 'field3', 'type' => 'datetime']); |
||
153 | $metadata->mapField(['fieldName' => 'field4', 'type' => 'datetime', 'nullable' => true]); |
||
154 | |||
155 | $this->_generator->writeEntityClass($metadata, $this->_tmpDir); |
||
156 | |||
157 | return $metadata; |
||
158 | } |
||
159 | |||
160 | /** |
||
161 | * @param string $fieldName |
||
162 | * @param ClassMetadataInfo $classMetadata |
||
163 | * @param ClassMetadataInfo $embeddableMetadata |
||
164 | * @param string|null $columnPrefix |
||
165 | */ |
||
166 | private function mapEmbedded( |
||
167 | $fieldName, |
||
168 | ClassMetadataInfo $classMetadata, |
||
169 | ClassMetadataInfo $embeddableMetadata, |
||
170 | $columnPrefix = false |
||
171 | ) { |
||
172 | $classMetadata->mapEmbedded( |
||
173 | ['fieldName' => $fieldName, 'class' => $embeddableMetadata->name, 'columnPrefix' => $columnPrefix] |
||
174 | ); |
||
175 | } |
||
176 | |||
177 | /** |
||
178 | * @param string $fieldName |
||
179 | * @param ClassMetadataInfo $classMetadata |
||
180 | * @param ClassMetadataInfo $embeddableMetadata |
||
181 | */ |
||
182 | private function mapNestedEmbedded( |
||
183 | $fieldName, |
||
184 | ClassMetadataInfo $classMetadata, |
||
185 | ClassMetadataInfo $embeddableMetadata |
||
186 | ) { |
||
187 | foreach ($embeddableMetadata->embeddedClasses as $property => $embeddableClass) { |
||
188 | $classMetadata->mapEmbedded( |
||
189 | [ |
||
190 | 'fieldName' => $fieldName . '.' . $property, |
||
191 | 'class' => $embeddableClass['class'], |
||
192 | 'columnPrefix' => $embeddableClass['columnPrefix'], |
||
193 | 'declaredField' => $embeddableClass['declaredField'] |
||
194 | ? $fieldName . '.' . $embeddableClass['declaredField'] |
||
195 | : $fieldName, |
||
196 | 'originalField' => $embeddableClass['originalField'] ?: $property, |
||
197 | ] |
||
198 | ); |
||
199 | } |
||
200 | } |
||
201 | |||
202 | /** |
||
203 | * @param ClassMetadataInfo $metadata |
||
204 | */ |
||
205 | private function loadEntityClass(ClassMetadataInfo $metadata) |
||
206 | { |
||
207 | $className = basename(str_replace('\\', '/', $metadata->name)); |
||
208 | $path = $this->_tmpDir . '/' . $this->_namespace . '/' . $className . '.php'; |
||
209 | |||
210 | $this->assertFileExists($path); |
||
211 | |||
212 | require_once $path; |
||
213 | } |
||
214 | |||
215 | /** |
||
216 | * @param ClassMetadataInfo $metadata |
||
217 | * |
||
218 | * @return mixed An instance of the given metadata's class. |
||
219 | */ |
||
220 | public function newInstance($metadata) |
||
221 | { |
||
222 | $this->loadEntityClass($metadata); |
||
223 | |||
224 | return new $metadata->name; |
||
225 | } |
||
226 | |||
227 | /** |
||
228 | * @group GH-6314 |
||
229 | */ |
||
230 | public function testEmbeddedEntityWithNamedColumnPrefix() |
||
231 | { |
||
232 | $columnPrefix = 'GH6314Prefix_'; |
||
233 | $testMetadata = $this->generateTestEmbeddableFixture(); |
||
234 | $isbnMetadata = $this->generateIsbnEmbeddableFixture(['testEmbedded' => $testMetadata], $columnPrefix); |
||
235 | $isbnEntity = $this->newInstance($isbnMetadata); |
||
236 | $refClass = new \ReflectionClass($isbnEntity); |
||
237 | self::assertTrue($refClass->hasProperty('testEmbedded')); |
||
238 | |||
239 | $docComment = $refClass->getProperty('testEmbedded')->getDocComment(); |
||
240 | $needle = sprintf('@Embedded(class="%s", columnPrefix="%s")', $testMetadata->name, $columnPrefix); |
||
241 | self::assertContains($needle, $docComment); |
||
242 | } |
||
243 | |||
244 | /** |
||
245 | * @group GH-6314 |
||
246 | */ |
||
247 | public function testEmbeddedEntityWithoutColumnPrefix() |
||
248 | { |
||
249 | $testMetadata = $this->generateTestEmbeddableFixture(); |
||
250 | $isbnMetadata = $this->generateIsbnEmbeddableFixture(['testEmbedded' => $testMetadata], false); |
||
251 | $isbnEntity = $this->newInstance($isbnMetadata); |
||
252 | $refClass = new \ReflectionClass($isbnEntity); |
||
253 | self::assertTrue($refClass->hasProperty('testEmbedded')); |
||
254 | |||
255 | $docComment = $refClass->getProperty('testEmbedded')->getDocComment(); |
||
256 | $needle = sprintf('@Embedded(class="%s", columnPrefix=false)', $testMetadata->name); |
||
257 | self::assertContains($needle, $docComment); |
||
258 | } |
||
259 | |||
260 | public function testGeneratedEntityClass() |
||
261 | { |
||
262 | $testMetadata = $this->generateTestEmbeddableFixture(); |
||
263 | $isbnMetadata = $this->generateIsbnEmbeddableFixture(['test' => $testMetadata]); |
||
264 | $metadata = $this->generateBookEntityFixture(['isbn' => $isbnMetadata]); |
||
265 | |||
266 | $book = $this->newInstance($metadata); |
||
267 | $this->assertTrue(class_exists($metadata->name), "Class does not exist."); |
||
268 | $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', '__construct'), "EntityGeneratorBook::__construct() missing."); |
||
269 | $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'getId'), "EntityGeneratorBook::getId() missing."); |
||
270 | $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'setName'), "EntityGeneratorBook::setName() missing."); |
||
271 | $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'getName'), "EntityGeneratorBook::getName() missing."); |
||
272 | $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'setStatus'), "EntityGeneratorBook::setStatus() missing."); |
||
273 | $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'getStatus'), "EntityGeneratorBook::getStatus() missing."); |
||
274 | $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'setAuthor'), "EntityGeneratorBook::setAuthor() missing."); |
||
275 | $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'getAuthor'), "EntityGeneratorBook::getAuthor() missing."); |
||
276 | $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'getComments'), "EntityGeneratorBook::getComments() missing."); |
||
277 | $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'addComment'), "EntityGeneratorBook::addComment() missing."); |
||
278 | $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'removeComment'), "EntityGeneratorBook::removeComment() missing."); |
||
279 | $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'setIsbn'), "EntityGeneratorBook::setIsbn() missing."); |
||
280 | $this->assertTrue(method_exists($metadata->namespace . '\EntityGeneratorBook', 'getIsbn'), "EntityGeneratorBook::getIsbn() missing."); |
||
281 | |||
282 | $reflClass = new \ReflectionClass($metadata->name); |
||
283 | |||
284 | $this->assertCount(6, $reflClass->getProperties()); |
||
285 | $this->assertCount(15, $reflClass->getMethods()); |
||
286 | |||
287 | $this->assertEquals('published', $book->getStatus()); |
||
288 | |||
289 | $book->setName('Jonathan H. Wage'); |
||
290 | $this->assertEquals('Jonathan H. Wage', $book->getName()); |
||
291 | |||
292 | $reflMethod = new \ReflectionMethod($metadata->name, 'addComment'); |
||
293 | $addCommentParameters = $reflMethod->getParameters(); |
||
294 | $this->assertEquals('comment', $addCommentParameters[0]->getName()); |
||
295 | |||
296 | $reflMethod = new \ReflectionMethod($metadata->name, 'removeComment'); |
||
297 | $removeCommentParameters = $reflMethod->getParameters(); |
||
298 | $this->assertEquals('comment', $removeCommentParameters[0]->getName()); |
||
299 | |||
300 | $author = new EntityGeneratorAuthor(); |
||
301 | $book->setAuthor($author); |
||
302 | $this->assertEquals($author, $book->getAuthor()); |
||
303 | |||
304 | $comment = new EntityGeneratorComment(); |
||
305 | $this->assertInstanceOf($metadata->name, $book->addComment($comment)); |
||
306 | $this->assertInstanceOf(ArrayCollection::class, $book->getComments()); |
||
307 | $this->assertEquals(new ArrayCollection([$comment]), $book->getComments()); |
||
308 | $this->assertInternalType('boolean', $book->removeComment($comment)); |
||
309 | $this->assertEquals(new ArrayCollection([]), $book->getComments()); |
||
310 | |||
311 | $this->newInstance($isbnMetadata); |
||
312 | $isbn = new $isbnMetadata->name(); |
||
313 | |||
314 | $book->setIsbn($isbn); |
||
315 | $this->assertSame($isbn, $book->getIsbn()); |
||
316 | |||
317 | $reflMethod = new \ReflectionMethod($metadata->name, 'setIsbn'); |
||
318 | $reflParameters = $reflMethod->getParameters(); |
||
319 | $this->assertEquals($isbnMetadata->name, $reflParameters[0]->getClass()->name); |
||
320 | } |
||
321 | |||
322 | public function testEntityUpdatingWorks() |
||
323 | { |
||
324 | $metadata = $this->generateBookEntityFixture(['isbn' => $this->generateIsbnEmbeddableFixture()]); |
||
325 | |||
326 | $metadata->mapField(['fieldName' => 'test', 'type' => 'string']); |
||
327 | |||
328 | $testEmbeddableMetadata = $this->generateTestEmbeddableFixture(); |
||
329 | $this->mapEmbedded('testEmbedded', $metadata, $testEmbeddableMetadata); |
||
330 | |||
331 | $this->_generator->writeEntityClass($metadata, $this->_tmpDir); |
||
332 | |||
333 | $this->assertFileExists($this->_tmpDir . "/" . $this->_namespace . "/EntityGeneratorBook.php~"); |
||
334 | |||
335 | $book = $this->newInstance($metadata); |
||
336 | $reflClass = new \ReflectionClass($metadata->name); |
||
337 | |||
338 | $this->assertTrue($reflClass->hasProperty('name'), "Regenerating keeps property 'name'."); |
||
339 | $this->assertTrue($reflClass->hasProperty('status'), "Regenerating keeps property 'status'."); |
||
340 | $this->assertTrue($reflClass->hasProperty('id'), "Regenerating keeps property 'id'."); |
||
341 | $this->assertTrue($reflClass->hasProperty('isbn'), "Regenerating keeps property 'isbn'."); |
||
342 | |||
343 | $this->assertTrue($reflClass->hasProperty('test'), "Check for property test failed."); |
||
344 | $this->assertTrue($reflClass->getProperty('test')->isProtected(), "Check for protected property test failed."); |
||
345 | $this->assertTrue($reflClass->hasProperty('testEmbedded'), "Check for property testEmbedded failed."); |
||
346 | $this->assertTrue($reflClass->getProperty('testEmbedded')->isProtected(), "Check for protected property testEmbedded failed."); |
||
347 | $this->assertTrue($reflClass->hasMethod('getTest'), "Check for method 'getTest' failed."); |
||
348 | $this->assertTrue($reflClass->getMethod('getTest')->isPublic(), "Check for public visibility of method 'getTest' failed."); |
||
349 | $this->assertTrue($reflClass->hasMethod('setTest'), "Check for method 'setTest' failed."); |
||
350 | $this->assertTrue($reflClass->getMethod('setTest')->isPublic(), "Check for public visibility of method 'setTest' failed."); |
||
351 | $this->assertTrue($reflClass->hasMethod('getTestEmbedded'), "Check for method 'getTestEmbedded' failed."); |
||
352 | $this->assertTrue( |
||
353 | $reflClass->getMethod('getTestEmbedded')->isPublic(), |
||
354 | "Check for public visibility of method 'getTestEmbedded' failed." |
||
355 | ); |
||
356 | $this->assertTrue($reflClass->hasMethod('setTestEmbedded'), "Check for method 'setTestEmbedded' failed."); |
||
357 | $this->assertTrue( |
||
358 | $reflClass->getMethod('setTestEmbedded')->isPublic(), |
||
359 | "Check for public visibility of method 'setTestEmbedded' failed." |
||
360 | ); |
||
361 | } |
||
362 | |||
363 | /** |
||
364 | * @group DDC-3152 |
||
365 | */ |
||
366 | public function testDoesNotRegenerateExistingMethodsWithDifferentCase() |
||
367 | { |
||
368 | $metadata = $this->generateBookEntityFixture(['isbn' => $this->generateIsbnEmbeddableFixture()]); |
||
369 | |||
370 | // Workaround to change existing fields case (just to simulate the use case) |
||
371 | $metadata->fieldMappings['status']['fieldName'] = 'STATUS'; |
||
372 | $metadata->embeddedClasses['ISBN'] = $metadata->embeddedClasses['isbn']; |
||
373 | unset($metadata->embeddedClasses['isbn']); |
||
374 | |||
375 | // Should not throw a PHP fatal error |
||
376 | $this->_generator->writeEntityClass($metadata, $this->_tmpDir); |
||
377 | |||
378 | $this->assertFileExists($this->_tmpDir . "/" . $this->_namespace . "/EntityGeneratorBook.php~"); |
||
379 | |||
380 | $this->newInstance($metadata); |
||
381 | $reflClass = new \ReflectionClass($metadata->name); |
||
382 | |||
383 | $this->assertTrue($reflClass->hasProperty('status')); |
||
384 | $this->assertTrue($reflClass->hasProperty('STATUS')); |
||
385 | $this->assertTrue($reflClass->hasProperty('isbn')); |
||
386 | $this->assertTrue($reflClass->hasProperty('ISBN')); |
||
387 | $this->assertTrue($reflClass->hasMethod('getStatus')); |
||
388 | $this->assertTrue($reflClass->hasMethod('setStatus')); |
||
389 | $this->assertTrue($reflClass->hasMethod('getIsbn')); |
||
390 | $this->assertTrue($reflClass->hasMethod('setIsbn')); |
||
391 | } |
||
392 | |||
393 | /** |
||
394 | * @group DDC-2121 |
||
395 | */ |
||
396 | public function testMethodDocBlockShouldStartWithBackSlash() |
||
397 | { |
||
398 | $embeddedMetadata = $this->generateIsbnEmbeddableFixture(); |
||
399 | $metadata = $this->generateBookEntityFixture(['isbn' => $embeddedMetadata]); |
||
400 | $book = $this->newInstance($metadata); |
||
401 | |||
402 | $this->assertPhpDocVarType('\Doctrine\Common\Collections\Collection', new \ReflectionProperty($book, 'comments')); |
||
403 | $this->assertPhpDocReturnType('\Doctrine\Common\Collections\Collection', new \ReflectionMethod($book, 'getComments')); |
||
404 | $this->assertPhpDocParamType('\Doctrine\Tests\ORM\Tools\EntityGeneratorComment', new \ReflectionMethod($book, 'addComment')); |
||
405 | $this->assertPhpDocReturnType('EntityGeneratorBook', new \ReflectionMethod($book, 'addComment')); |
||
406 | $this->assertPhpDocParamType('\Doctrine\Tests\ORM\Tools\EntityGeneratorComment', new \ReflectionMethod($book, 'removeComment')); |
||
407 | $this->assertPhpDocReturnType('boolean', new \ReflectionMethod($book, 'removeComment')); |
||
408 | |||
409 | $this->assertPhpDocVarType('\Doctrine\Tests\ORM\Tools\EntityGeneratorAuthor', new \ReflectionProperty($book, 'author')); |
||
410 | $this->assertPhpDocReturnType('\Doctrine\Tests\ORM\Tools\EntityGeneratorAuthor|null', new \ReflectionMethod($book, 'getAuthor')); |
||
411 | $this->assertPhpDocParamType('\Doctrine\Tests\ORM\Tools\EntityGeneratorAuthor|null', new \ReflectionMethod($book, 'setAuthor')); |
||
412 | |||
413 | $expectedClassName = '\\' . $embeddedMetadata->name; |
||
414 | $this->assertPhpDocVarType($expectedClassName, new \ReflectionProperty($book, 'isbn')); |
||
415 | $this->assertPhpDocReturnType($expectedClassName, new \ReflectionMethod($book, 'getIsbn')); |
||
416 | $this->assertPhpDocParamType($expectedClassName, new \ReflectionMethod($book, 'setIsbn')); |
||
417 | } |
||
418 | |||
419 | public function testEntityExtendsStdClass() |
||
420 | { |
||
421 | $this->_generator->setClassToExtend('stdClass'); |
||
422 | $metadata = $this->generateBookEntityFixture(); |
||
423 | |||
424 | $book = $this->newInstance($metadata); |
||
425 | $this->assertInstanceOf('stdClass', $book); |
||
426 | |||
427 | $metadata = $this->generateIsbnEmbeddableFixture(); |
||
428 | $isbn = $this->newInstance($metadata); |
||
429 | $this->assertInstanceOf('stdClass', $isbn); |
||
430 | } |
||
431 | |||
432 | public function testLifecycleCallbacks() |
||
433 | { |
||
434 | $metadata = $this->generateBookEntityFixture(); |
||
435 | |||
436 | $book = $this->newInstance($metadata); |
||
437 | $reflClass = new \ReflectionClass($metadata->name); |
||
438 | |||
439 | $this->assertTrue($reflClass->hasMethod('loading'), "Check for postLoad lifecycle callback."); |
||
440 | $this->assertTrue($reflClass->hasMethod('willBeRemoved'), "Check for preRemove lifecycle callback."); |
||
441 | } |
||
442 | |||
443 | public function testLoadMetadata() |
||
444 | { |
||
445 | $embeddedMetadata = $this->generateIsbnEmbeddableFixture(); |
||
446 | $metadata = $this->generateBookEntityFixture(['isbn' => $embeddedMetadata]); |
||
447 | |||
448 | $book = $this->newInstance($metadata); |
||
449 | |||
450 | $reflectionService = new RuntimeReflectionService(); |
||
451 | |||
452 | $cm = new ClassMetadataInfo($metadata->name); |
||
453 | $cm->initializeReflection($reflectionService); |
||
454 | |||
455 | $driver = $this->createAnnotationDriver(); |
||
456 | $driver->loadMetadataForClass($cm->name, $cm); |
||
457 | |||
458 | $this->assertEquals($cm->columnNames, $metadata->columnNames); |
||
459 | $this->assertEquals($cm->getTableName(), $metadata->getTableName()); |
||
460 | $this->assertEquals($cm->lifecycleCallbacks, $metadata->lifecycleCallbacks); |
||
461 | $this->assertEquals($cm->identifier, $metadata->identifier); |
||
462 | $this->assertEquals($cm->idGenerator, $metadata->idGenerator); |
||
463 | $this->assertEquals($cm->customRepositoryClassName, $metadata->customRepositoryClassName); |
||
464 | $this->assertEquals($cm->embeddedClasses, $metadata->embeddedClasses); |
||
465 | $this->assertEquals($cm->isEmbeddedClass, $metadata->isEmbeddedClass); |
||
466 | |||
467 | $this->assertEquals(ClassMetadataInfo::FETCH_EXTRA_LAZY, $cm->associationMappings['comments']['fetch']); |
||
468 | |||
469 | $isbn = $this->newInstance($embeddedMetadata); |
||
470 | |||
471 | $cm = new ClassMetadataInfo($embeddedMetadata->name); |
||
472 | $cm->initializeReflection($reflectionService); |
||
473 | |||
474 | $driver->loadMetadataForClass($cm->name, $cm); |
||
475 | |||
476 | $this->assertEquals($cm->columnNames, $embeddedMetadata->columnNames); |
||
477 | $this->assertEquals($cm->embeddedClasses, $embeddedMetadata->embeddedClasses); |
||
478 | $this->assertEquals($cm->isEmbeddedClass, $embeddedMetadata->isEmbeddedClass); |
||
479 | } |
||
480 | |||
481 | public function testLoadPrefixedMetadata() |
||
482 | { |
||
483 | $this->_generator->setAnnotationPrefix('ORM\\'); |
||
484 | $embeddedMetadata = $this->generateIsbnEmbeddableFixture(); |
||
485 | $metadata = $this->generateBookEntityFixture(['isbn' => $embeddedMetadata]); |
||
486 | |||
487 | $reader = new AnnotationReader(); |
||
488 | $driver = new AnnotationDriver($reader, []); |
||
489 | |||
490 | $book = $this->newInstance($metadata); |
||
491 | |||
492 | $reflectionService = new RuntimeReflectionService(); |
||
493 | |||
494 | $cm = new ClassMetadataInfo($metadata->name); |
||
495 | $cm->initializeReflection($reflectionService); |
||
496 | |||
497 | $driver->loadMetadataForClass($cm->name, $cm); |
||
498 | |||
499 | $this->assertEquals($cm->columnNames, $metadata->columnNames); |
||
500 | $this->assertEquals($cm->getTableName(), $metadata->getTableName()); |
||
501 | $this->assertEquals($cm->lifecycleCallbacks, $metadata->lifecycleCallbacks); |
||
502 | $this->assertEquals($cm->identifier, $metadata->identifier); |
||
503 | $this->assertEquals($cm->idGenerator, $metadata->idGenerator); |
||
504 | $this->assertEquals($cm->customRepositoryClassName, $metadata->customRepositoryClassName); |
||
505 | |||
506 | $isbn = $this->newInstance($embeddedMetadata); |
||
507 | |||
508 | $cm = new ClassMetadataInfo($embeddedMetadata->name); |
||
509 | $cm->initializeReflection($reflectionService); |
||
510 | |||
511 | $driver->loadMetadataForClass($cm->name, $cm); |
||
512 | |||
513 | $this->assertEquals($cm->columnNames, $embeddedMetadata->columnNames); |
||
514 | $this->assertEquals($cm->embeddedClasses, $embeddedMetadata->embeddedClasses); |
||
515 | $this->assertEquals($cm->isEmbeddedClass, $embeddedMetadata->isEmbeddedClass); |
||
516 | } |
||
517 | |||
518 | /** |
||
519 | * @group DDC-3272 |
||
520 | */ |
||
521 | public function testMappedSuperclassAnnotationGeneration() |
||
522 | { |
||
523 | $metadata = new ClassMetadataInfo($this->_namespace . '\EntityGeneratorBook'); |
||
524 | $metadata->namespace = $this->_namespace; |
||
525 | $metadata->isMappedSuperclass = true; |
||
526 | |||
527 | $this->_generator->setAnnotationPrefix('ORM\\'); |
||
528 | $this->_generator->writeEntityClass($metadata, $this->_tmpDir); |
||
529 | $this->newInstance($metadata); // force instantiation (causes autoloading to kick in) |
||
530 | |||
531 | $driver = new AnnotationDriver(new AnnotationReader(), []); |
||
532 | $cm = new ClassMetadataInfo($metadata->name); |
||
533 | |||
534 | $cm->initializeReflection(new RuntimeReflectionService); |
||
535 | $driver->loadMetadataForClass($cm->name, $cm); |
||
536 | |||
537 | $this->assertTrue($cm->isMappedSuperclass); |
||
538 | } |
||
539 | |||
540 | /** |
||
541 | * @dataProvider getParseTokensInEntityFileData |
||
542 | */ |
||
543 | public function testParseTokensInEntityFile($php, $classes) |
||
544 | { |
||
545 | $r = new \ReflectionObject($this->_generator); |
||
546 | $m = $r->getMethod('parseTokensInEntityFile'); |
||
547 | $m->setAccessible(true); |
||
548 | |||
549 | $p = $r->getProperty('staticReflection'); |
||
550 | $p->setAccessible(true); |
||
551 | |||
552 | $ret = $m->invoke($this->_generator, $php); |
||
553 | $this->assertEquals($classes, array_keys($p->getValue($this->_generator))); |
||
554 | } |
||
555 | |||
556 | /** |
||
557 | * @group DDC-1784 |
||
558 | */ |
||
559 | public function testGenerateEntityWithSequenceGenerator() |
||
560 | { |
||
561 | $metadata = new ClassMetadataInfo($this->_namespace . '\DDC1784Entity'); |
||
562 | $metadata->namespace = $this->_namespace; |
||
563 | $metadata->mapField(['fieldName' => 'id', 'type' => 'integer', 'id' => true]); |
||
564 | $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE); |
||
565 | $metadata->setSequenceGeneratorDefinition( |
||
566 | [ |
||
567 | 'sequenceName' => 'DDC1784_ID_SEQ', |
||
568 | 'allocationSize' => 1, |
||
569 | 'initialValue' => 2 |
||
570 | ] |
||
571 | ); |
||
572 | $this->_generator->writeEntityClass($metadata, $this->_tmpDir); |
||
573 | |||
574 | $filename = $this->_tmpDir . DIRECTORY_SEPARATOR |
||
575 | . $this->_namespace . DIRECTORY_SEPARATOR . 'DDC1784Entity.php'; |
||
576 | |||
577 | $this->assertFileExists($filename); |
||
578 | require_once $filename; |
||
579 | |||
580 | |||
581 | $reflection = new \ReflectionProperty($metadata->name, 'id'); |
||
582 | $docComment = $reflection->getDocComment(); |
||
583 | |||
584 | $this->assertContains('@Id', $docComment); |
||
585 | $this->assertContains('@Column(name="id", type="integer")', $docComment); |
||
586 | $this->assertContains('@GeneratedValue(strategy="SEQUENCE")', $docComment); |
||
587 | $this->assertContains('@SequenceGenerator(sequenceName="DDC1784_ID_SEQ", allocationSize=1, initialValue=2)', $docComment); |
||
588 | } |
||
589 | |||
590 | /** |
||
591 | * @group DDC-2079 |
||
592 | */ |
||
593 | public function testGenerateEntityWithMultipleInverseJoinColumns() |
||
594 | { |
||
595 | $metadata = new ClassMetadataInfo($this->_namespace . '\DDC2079Entity'); |
||
596 | $metadata->namespace = $this->_namespace; |
||
597 | $metadata->mapField(['fieldName' => 'id', 'type' => 'integer', 'id' => true]); |
||
598 | $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE); |
||
599 | $metadata->mapManyToMany( |
||
600 | [ |
||
601 | 'fieldName' => 'centroCustos', |
||
602 | 'targetEntity' => 'DDC2079CentroCusto', |
||
603 | 'joinTable' => [ |
||
604 | 'name' => 'unidade_centro_custo', |
||
605 | 'joinColumns' => [ |
||
606 | ['name' => 'idorcamento', 'referencedColumnName' => 'idorcamento'], |
||
607 | ['name' => 'idunidade', 'referencedColumnName' => 'idunidade'] |
||
608 | ], |
||
609 | 'inverseJoinColumns' => [ |
||
610 | ['name' => 'idcentrocusto', 'referencedColumnName' => 'idcentrocusto'], |
||
611 | ['name' => 'idpais', 'referencedColumnName' => 'idpais'], |
||
612 | ], |
||
613 | ], |
||
614 | ] |
||
615 | ); |
||
616 | $this->_generator->writeEntityClass($metadata, $this->_tmpDir); |
||
617 | |||
618 | $filename = $this->_tmpDir . DIRECTORY_SEPARATOR |
||
619 | . $this->_namespace . DIRECTORY_SEPARATOR . 'DDC2079Entity.php'; |
||
620 | |||
621 | $this->assertFileExists($filename); |
||
622 | require_once $filename; |
||
623 | |||
624 | $property = new \ReflectionProperty($metadata->name, 'centroCustos'); |
||
625 | $docComment = $property->getDocComment(); |
||
626 | |||
627 | //joinColumns |
||
628 | $this->assertContains('@JoinColumn(name="idorcamento", referencedColumnName="idorcamento"),', $docComment); |
||
629 | $this->assertContains('@JoinColumn(name="idunidade", referencedColumnName="idunidade")', $docComment); |
||
630 | //inverseJoinColumns |
||
631 | $this->assertContains('@JoinColumn(name="idcentrocusto", referencedColumnName="idcentrocusto"),', $docComment); |
||
632 | $this->assertContains('@JoinColumn(name="idpais", referencedColumnName="idpais")', $docComment); |
||
633 | |||
634 | } |
||
635 | |||
636 | /** |
||
637 | * @group DDC-2172 |
||
638 | */ |
||
639 | View Code Duplication | public function testGetInheritanceTypeString() |
|
640 | { |
||
641 | $reflection = new \ReflectionClass('\Doctrine\ORM\Mapping\ClassMetadataInfo'); |
||
642 | $method = new \ReflectionMethod($this->_generator, 'getInheritanceTypeString'); |
||
643 | $constants = $reflection->getConstants(); |
||
644 | $pattern = '/^INHERITANCE_TYPE_/'; |
||
645 | |||
646 | $method->setAccessible(true); |
||
647 | |||
648 | foreach ($constants as $name => $value) { |
||
649 | if( ! preg_match($pattern, $name)) { |
||
650 | continue; |
||
651 | } |
||
652 | |||
653 | $expected = preg_replace($pattern, '', $name); |
||
654 | $actual = $method->invoke($this->_generator, $value); |
||
655 | |||
656 | $this->assertEquals($expected, $actual); |
||
657 | } |
||
658 | |||
659 | $this->expectException(\InvalidArgumentException::class); |
||
660 | $this->expectExceptionMessage('Invalid provided InheritanceType: INVALID'); |
||
661 | |||
662 | $method->invoke($this->_generator, 'INVALID'); |
||
663 | } |
||
664 | |||
665 | /** |
||
666 | * @group DDC-2172 |
||
667 | */ |
||
668 | View Code Duplication | public function testGetChangeTrackingPolicyString() |
|
669 | { |
||
670 | $reflection = new \ReflectionClass('\Doctrine\ORM\Mapping\ClassMetadata'); |
||
671 | $method = new \ReflectionMethod($this->_generator, 'getChangeTrackingPolicyString'); |
||
672 | $constants = $reflection->getConstants(); |
||
673 | $pattern = '/^CHANGETRACKING_/'; |
||
674 | |||
675 | $method->setAccessible(true); |
||
676 | |||
677 | foreach ($constants as $name => $value) { |
||
678 | if( ! preg_match($pattern, $name)) { |
||
679 | continue; |
||
680 | } |
||
681 | |||
682 | $expected = preg_replace($pattern, '', $name); |
||
683 | $actual = $method->invoke($this->_generator, $value); |
||
684 | |||
685 | $this->assertEquals($expected, $actual); |
||
686 | } |
||
687 | |||
688 | $this->expectException(\InvalidArgumentException::class); |
||
689 | $this->expectExceptionMessage('Invalid provided ChangeTrackingPolicy: INVALID'); |
||
690 | |||
691 | $method->invoke($this->_generator, 'INVALID'); |
||
692 | } |
||
693 | |||
694 | /** |
||
695 | * @group DDC-2172 |
||
696 | */ |
||
697 | View Code Duplication | public function testGetIdGeneratorTypeString() |
|
698 | { |
||
699 | $reflection = new \ReflectionClass('\Doctrine\ORM\Mapping\ClassMetadataInfo'); |
||
700 | $method = new \ReflectionMethod($this->_generator, 'getIdGeneratorTypeString'); |
||
701 | $constants = $reflection->getConstants(); |
||
702 | $pattern = '/^GENERATOR_TYPE_/'; |
||
703 | |||
704 | $method->setAccessible(true); |
||
705 | |||
706 | foreach ($constants as $name => $value) { |
||
707 | if( ! preg_match($pattern, $name)) { |
||
708 | continue; |
||
709 | } |
||
710 | |||
711 | $expected = preg_replace($pattern, '', $name); |
||
712 | $actual = $method->invoke($this->_generator, $value); |
||
713 | |||
714 | $this->assertEquals($expected, $actual); |
||
715 | } |
||
716 | |||
717 | $this->expectException(\InvalidArgumentException::class); |
||
718 | $this->expectExceptionMessage('Invalid provided IdGeneratorType: INVALID'); |
||
719 | |||
720 | $method->invoke($this->_generator, 'INVALID'); |
||
721 | } |
||
722 | |||
723 | /** |
||
724 | * @dataProvider getEntityTypeAliasDataProvider |
||
725 | * |
||
726 | * @group DDC-1694 |
||
727 | */ |
||
728 | public function testEntityTypeAlias(array $field) |
||
729 | { |
||
730 | $metadata = $this->generateEntityTypeFixture($field); |
||
731 | $path = $this->_tmpDir . '/'. $this->_namespace . '/EntityType.php'; |
||
732 | |||
733 | $this->assertFileExists($path); |
||
734 | require_once $path; |
||
735 | |||
736 | $entity = new $metadata->name; |
||
737 | $reflClass = new \ReflectionClass($metadata->name); |
||
738 | |||
739 | $type = $field['phpType']; |
||
740 | $name = $field['fieldName']; |
||
741 | $value = $field['value']; |
||
742 | $getter = "get" . ucfirst($name); |
||
743 | $setter = "set" . ucfirst($name); |
||
744 | |||
745 | $this->assertPhpDocVarType($type, $reflClass->getProperty($name)); |
||
746 | $this->assertPhpDocParamType($type, $reflClass->getMethod($setter)); |
||
747 | $this->assertPhpDocReturnType($type, $reflClass->getMethod($getter)); |
||
748 | |||
749 | $this->assertSame($entity, $entity->{$setter}($value)); |
||
750 | $this->assertEquals($value, $entity->{$getter}()); |
||
751 | } |
||
752 | |||
753 | /** |
||
754 | * @group DDC-2372 |
||
755 | */ |
||
756 | View Code Duplication | public function testTraitPropertiesAndMethodsAreNotDuplicated() |
|
757 | { |
||
758 | $cmf = new ClassMetadataFactory(); |
||
759 | $em = $this->_getTestEntityManager(); |
||
760 | $cmf->setEntityManager($em); |
||
761 | |||
762 | $user = new DDC2372User(); |
||
763 | $metadata = $cmf->getMetadataFor(get_class($user)); |
||
764 | $metadata->name = $this->_namespace . "\DDC2372User"; |
||
0 ignored issues
–
show
|
|||
765 | $metadata->namespace = $this->_namespace; |
||
0 ignored issues
–
show
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
Loading history...
|
|||
766 | |||
767 | $this->_generator->writeEntityClass($metadata, $this->_tmpDir); |
||
0 ignored issues
–
show
$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...
|
|||
768 | |||
769 | $this->assertFileExists($this->_tmpDir . "/" . $this->_namespace . "/DDC2372User.php"); |
||
770 | require $this->_tmpDir . "/" . $this->_namespace . "/DDC2372User.php"; |
||
771 | |||
772 | $reflClass = new \ReflectionClass($metadata->name); |
||
0 ignored issues
–
show
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
Loading history...
|
|||
773 | |||
774 | $this->assertSame($reflClass->hasProperty('address'), false); |
||
775 | $this->assertSame($reflClass->hasMethod('setAddress'), false); |
||
776 | $this->assertSame($reflClass->hasMethod('getAddress'), false); |
||
777 | } |
||
778 | |||
779 | /** |
||
780 | * @group DDC-2372 |
||
781 | */ |
||
782 | View Code Duplication | public function testTraitPropertiesAndMethodsAreNotDuplicatedInChildClasses() |
|
783 | { |
||
784 | $cmf = new ClassMetadataFactory(); |
||
785 | $em = $this->_getTestEntityManager(); |
||
786 | $cmf->setEntityManager($em); |
||
787 | |||
788 | $user = new DDC2372Admin(); |
||
789 | $metadata = $cmf->getMetadataFor(get_class($user)); |
||
790 | $metadata->name = $this->_namespace . "\DDC2372Admin"; |
||
0 ignored issues
–
show
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
Loading history...
|
|||
791 | $metadata->namespace = $this->_namespace; |
||
0 ignored issues
–
show
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
Loading history...
|
|||
792 | |||
793 | $this->_generator->writeEntityClass($metadata, $this->_tmpDir); |
||
0 ignored issues
–
show
$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...
|
|||
794 | |||
795 | $this->assertFileExists($this->_tmpDir . "/" . $this->_namespace . "/DDC2372Admin.php"); |
||
796 | require $this->_tmpDir . "/" . $this->_namespace . "/DDC2372Admin.php"; |
||
797 | |||
798 | $reflClass = new \ReflectionClass($metadata->name); |
||
0 ignored issues
–
show
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
Loading history...
|
|||
799 | |||
800 | $this->assertSame($reflClass->hasProperty('address'), false); |
||
801 | $this->assertSame($reflClass->hasMethod('setAddress'), false); |
||
802 | $this->assertSame($reflClass->hasMethod('getAddress'), false); |
||
803 | } |
||
804 | |||
805 | /** |
||
806 | * @group DDC-1590 |
||
807 | */ |
||
808 | public function testMethodsAndPropertiesAreNotDuplicatedInChildClasses() |
||
809 | { |
||
810 | $cmf = new ClassMetadataFactory(); |
||
811 | $em = $this->_getTestEntityManager(); |
||
812 | |||
813 | $cmf->setEntityManager($em); |
||
814 | |||
815 | $ns = $this->_namespace; |
||
816 | $nsdir = $this->_tmpDir . '/' . $ns; |
||
817 | |||
818 | $content = str_replace( |
||
819 | 'namespace Doctrine\Tests\Models\DDC1590', |
||
820 | 'namespace ' . $ns, |
||
821 | file_get_contents(__DIR__ . '/../../Models/DDC1590/DDC1590User.php') |
||
822 | ); |
||
823 | |||
824 | $fname = $nsdir . "/DDC1590User.php"; |
||
825 | file_put_contents($fname, $content); |
||
826 | require $fname; |
||
827 | |||
828 | |||
829 | $metadata = $cmf->getMetadataFor($ns . '\DDC1590User'); |
||
830 | $this->_generator->writeEntityClass($metadata, $this->_tmpDir); |
||
831 | |||
832 | // class DDC1590User extends DDC1590Entity { ... } |
||
833 | $source = file_get_contents($fname); |
||
834 | |||
835 | // class _DDC1590User extends DDC1590Entity { ... } |
||
836 | $source2 = str_replace('class DDC1590User', 'class _DDC1590User', $source); |
||
837 | $fname2 = $nsdir . "/_DDC1590User.php"; |
||
838 | file_put_contents($fname2, $source2); |
||
839 | require $fname2; |
||
840 | |||
841 | // class __DDC1590User { ... } |
||
842 | $source3 = str_replace('class DDC1590User extends DDC1590Entity', 'class __DDC1590User', $source); |
||
843 | $fname3 = $nsdir . "/__DDC1590User.php"; |
||
844 | file_put_contents($fname3, $source3); |
||
845 | require $fname3; |
||
846 | |||
847 | |||
848 | // class _DDC1590User extends DDC1590Entity { ... } |
||
849 | $rc2 = new \ReflectionClass($ns.'\_DDC1590User'); |
||
850 | |||
851 | $this->assertTrue($rc2->hasProperty('name')); |
||
852 | $this->assertTrue($rc2->hasProperty('id')); |
||
853 | $this->assertTrue($rc2->hasProperty('created_at')); |
||
854 | |||
855 | $this->assertTrue($rc2->hasMethod('getName')); |
||
856 | $this->assertTrue($rc2->hasMethod('setName')); |
||
857 | $this->assertTrue($rc2->hasMethod('getId')); |
||
858 | $this->assertFalse($rc2->hasMethod('setId')); |
||
859 | $this->assertTrue($rc2->hasMethod('getCreatedAt')); |
||
860 | $this->assertTrue($rc2->hasMethod('setCreatedAt')); |
||
861 | |||
862 | |||
863 | // class __DDC1590User { ... } |
||
864 | $rc3 = new \ReflectionClass($ns.'\__DDC1590User'); |
||
865 | |||
866 | $this->assertTrue($rc3->hasProperty('name')); |
||
867 | $this->assertFalse($rc3->hasProperty('id')); |
||
868 | $this->assertFalse($rc3->hasProperty('created_at')); |
||
869 | |||
870 | $this->assertTrue($rc3->hasMethod('getName')); |
||
871 | $this->assertTrue($rc3->hasMethod('setName')); |
||
872 | $this->assertFalse($rc3->hasMethod('getId')); |
||
873 | $this->assertFalse($rc3->hasMethod('setId')); |
||
874 | $this->assertFalse($rc3->hasMethod('getCreatedAt')); |
||
875 | $this->assertFalse($rc3->hasMethod('setCreatedAt')); |
||
876 | } |
||
877 | |||
878 | /** |
||
879 | * @group DDC-3304 |
||
880 | */ |
||
881 | public function testGeneratedMutableEmbeddablesClass() |
||
882 | { |
||
883 | $embeddedMetadata = $this->generateTestEmbeddableFixture(); |
||
884 | $metadata = $this->generateIsbnEmbeddableFixture(['test' => $embeddedMetadata]); |
||
885 | |||
886 | $isbn = $this->newInstance($metadata); |
||
887 | |||
888 | $this->assertTrue(class_exists($metadata->name), "Class does not exist."); |
||
889 | $this->assertFalse(method_exists($metadata->name, '__construct'), "EntityGeneratorIsbn::__construct present."); |
||
890 | $this->assertTrue(method_exists($metadata->name, 'getPrefix'), "EntityGeneratorIsbn::getPrefix() missing."); |
||
891 | $this->assertTrue(method_exists($metadata->name, 'setPrefix'), "EntityGeneratorIsbn::setPrefix() missing."); |
||
892 | $this->assertTrue(method_exists($metadata->name, 'getGroupNumber'), "EntityGeneratorIsbn::getGroupNumber() missing."); |
||
893 | $this->assertTrue(method_exists($metadata->name, 'setGroupNumber'), "EntityGeneratorIsbn::setGroupNumber() missing."); |
||
894 | $this->assertTrue(method_exists($metadata->name, 'getPublisherNumber'), "EntityGeneratorIsbn::getPublisherNumber() missing."); |
||
895 | $this->assertTrue(method_exists($metadata->name, 'setPublisherNumber'), "EntityGeneratorIsbn::setPublisherNumber() missing."); |
||
896 | $this->assertTrue(method_exists($metadata->name, 'getTitleNumber'), "EntityGeneratorIsbn::getTitleNumber() missing."); |
||
897 | $this->assertTrue(method_exists($metadata->name, 'setTitleNumber'), "EntityGeneratorIsbn::setTitleNumber() missing."); |
||
898 | $this->assertTrue(method_exists($metadata->name, 'getCheckDigit'), "EntityGeneratorIsbn::getCheckDigit() missing."); |
||
899 | $this->assertTrue(method_exists($metadata->name, 'setCheckDigit'), "EntityGeneratorIsbn::setCheckDigit() missing."); |
||
900 | $this->assertTrue(method_exists($metadata->name, 'getTest'), "EntityGeneratorIsbn::getTest() missing."); |
||
901 | $this->assertTrue(method_exists($metadata->name, 'setTest'), "EntityGeneratorIsbn::setTest() missing."); |
||
902 | |||
903 | $isbn->setPrefix(978); |
||
904 | $this->assertSame(978, $isbn->getPrefix()); |
||
905 | |||
906 | $this->newInstance($embeddedMetadata); |
||
907 | $test = new $embeddedMetadata->name(); |
||
908 | |||
909 | $isbn->setTest($test); |
||
910 | $this->assertSame($test, $isbn->getTest()); |
||
911 | |||
912 | $reflMethod = new \ReflectionMethod($metadata->name, 'setTest'); |
||
913 | $reflParameters = $reflMethod->getParameters(); |
||
914 | $this->assertEquals($embeddedMetadata->name, $reflParameters[0]->getClass()->name); |
||
915 | } |
||
916 | |||
917 | /** |
||
918 | * @group DDC-3304 |
||
919 | */ |
||
920 | public function testGeneratedImmutableEmbeddablesClass() |
||
921 | { |
||
922 | $this->_generator->setEmbeddablesImmutable(true); |
||
923 | $embeddedMetadata = $this->generateTestEmbeddableFixture(); |
||
924 | $metadata = $this->generateIsbnEmbeddableFixture(['test' => $embeddedMetadata]); |
||
925 | |||
926 | $this->loadEntityClass($embeddedMetadata); |
||
927 | $this->loadEntityClass($metadata); |
||
928 | |||
929 | $this->assertTrue(class_exists($metadata->name), "Class does not exist."); |
||
930 | $this->assertTrue(method_exists($metadata->name, '__construct'), "EntityGeneratorIsbn::__construct missing."); |
||
931 | $this->assertTrue(method_exists($metadata->name, 'getPrefix'), "EntityGeneratorIsbn::getPrefix() missing."); |
||
932 | $this->assertFalse(method_exists($metadata->name, 'setPrefix'), "EntityGeneratorIsbn::setPrefix() present."); |
||
933 | $this->assertTrue(method_exists($metadata->name, 'getGroupNumber'), "EntityGeneratorIsbn::getGroupNumber() missing."); |
||
934 | $this->assertFalse(method_exists($metadata->name, 'setGroupNumber'), "EntityGeneratorIsbn::setGroupNumber() present."); |
||
935 | $this->assertTrue(method_exists($metadata->name, 'getPublisherNumber'), "EntityGeneratorIsbn::getPublisherNumber() missing."); |
||
936 | $this->assertFalse(method_exists($metadata->name, 'setPublisherNumber'), "EntityGeneratorIsbn::setPublisherNumber() present."); |
||
937 | $this->assertTrue(method_exists($metadata->name, 'getTitleNumber'), "EntityGeneratorIsbn::getTitleNumber() missing."); |
||
938 | $this->assertFalse(method_exists($metadata->name, 'setTitleNumber'), "EntityGeneratorIsbn::setTitleNumber() present."); |
||
939 | $this->assertTrue(method_exists($metadata->name, 'getCheckDigit'), "EntityGeneratorIsbn::getCheckDigit() missing."); |
||
940 | $this->assertFalse(method_exists($metadata->name, 'setCheckDigit'), "EntityGeneratorIsbn::setCheckDigit() present."); |
||
941 | $this->assertTrue(method_exists($metadata->name, 'getTest'), "EntityGeneratorIsbn::getTest() missing."); |
||
942 | $this->assertFalse(method_exists($metadata->name, 'setTest'), "EntityGeneratorIsbn::setTest() present."); |
||
943 | |||
944 | $test = new $embeddedMetadata->name(1, new \DateTime()); |
||
945 | $isbn = new $metadata->name($test, 978, 3, 12, 732320, 83); |
||
946 | |||
947 | $reflMethod = new \ReflectionMethod($isbn, '__construct'); |
||
948 | $reflParameters = $reflMethod->getParameters(); |
||
949 | |||
950 | $this->assertCount(6, $reflParameters); |
||
951 | |||
952 | $this->assertSame($embeddedMetadata->name, $reflParameters[0]->getClass()->name); |
||
953 | $this->assertSame('test', $reflParameters[0]->getName()); |
||
954 | $this->assertFalse($reflParameters[0]->isOptional()); |
||
955 | |||
956 | $this->assertSame('prefix', $reflParameters[1]->getName()); |
||
957 | $this->assertFalse($reflParameters[1]->isOptional()); |
||
958 | |||
959 | $this->assertSame('groupNumber', $reflParameters[2]->getName()); |
||
960 | $this->assertFalse($reflParameters[2]->isOptional()); |
||
961 | |||
962 | $this->assertSame('publisherNumber', $reflParameters[3]->getName()); |
||
963 | $this->assertFalse($reflParameters[3]->isOptional()); |
||
964 | |||
965 | $this->assertSame('titleNumber', $reflParameters[4]->getName()); |
||
966 | $this->assertFalse($reflParameters[4]->isOptional()); |
||
967 | |||
968 | $this->assertSame('checkDigit', $reflParameters[5]->getName()); |
||
969 | $this->assertFalse($reflParameters[5]->isOptional()); |
||
970 | |||
971 | $reflMethod = new \ReflectionMethod($test, '__construct'); |
||
972 | $reflParameters = $reflMethod->getParameters(); |
||
973 | |||
974 | $this->assertCount(4, $reflParameters); |
||
975 | |||
976 | $this->assertSame('field1', $reflParameters[0]->getName()); |
||
977 | $this->assertFalse($reflParameters[0]->isOptional()); |
||
978 | |||
979 | $this->assertSame('DateTime', $reflParameters[1]->getClass()->name); |
||
980 | $this->assertSame('field3', $reflParameters[1]->getName()); |
||
981 | $this->assertFalse($reflParameters[1]->isOptional()); |
||
982 | |||
983 | $this->assertSame('field2', $reflParameters[2]->getName()); |
||
984 | $this->assertTrue($reflParameters[2]->isOptional()); |
||
985 | |||
986 | $this->assertSame('DateTime', $reflParameters[3]->getClass()->name); |
||
987 | $this->assertSame('field4', $reflParameters[3]->getName()); |
||
988 | $this->assertTrue($reflParameters[3]->isOptional()); |
||
989 | } |
||
990 | |||
991 | public function testRegenerateEntityClass() |
||
992 | { |
||
993 | $metadata = $this->generateBookEntityFixture(); |
||
994 | $this->loadEntityClass($metadata); |
||
995 | |||
996 | $className = basename(str_replace('\\', '/', $metadata->name)); |
||
997 | $path = $this->_tmpDir . '/' . $this->_namespace . '/' . $className . '.php'; |
||
998 | $classTest = file_get_contents($path); |
||
999 | |||
1000 | $this->_generator->setRegenerateEntityIfExists(true); |
||
1001 | $this->_generator->setBackupExisting(false); |
||
1002 | |||
1003 | $this->_generator->writeEntityClass($metadata, $this->_tmpDir); |
||
1004 | $classNew = file_get_contents($path); |
||
1005 | |||
1006 | $this->assertSame($classTest,$classNew); |
||
1007 | } |
||
1008 | |||
1009 | /** |
||
1010 | * @return array |
||
1011 | */ |
||
1012 | public function getEntityTypeAliasDataProvider() |
||
1013 | { |
||
1014 | return [ |
||
1015 | [ |
||
1016 | [ |
||
1017 | 'fieldName' => 'datetimetz', |
||
1018 | 'phpType' => '\\DateTime', |
||
1019 | 'dbType' => 'datetimetz', |
||
1020 | 'value' => new \DateTime |
||
1021 | ] |
||
1022 | ], |
||
1023 | [ |
||
1024 | [ |
||
1025 | 'fieldName' => 'datetime', |
||
1026 | 'phpType' => '\\DateTime', |
||
1027 | 'dbType' => 'datetime', |
||
1028 | 'value' => new \DateTime |
||
1029 | ] |
||
1030 | ], |
||
1031 | [ |
||
1032 | [ |
||
1033 | 'fieldName' => 'date', |
||
1034 | 'phpType' => '\\DateTime', |
||
1035 | 'dbType' => 'date', |
||
1036 | 'value' => new \DateTime |
||
1037 | ] |
||
1038 | ], |
||
1039 | [ |
||
1040 | [ |
||
1041 | 'fieldName' => 'time', |
||
1042 | 'phpType' => '\DateTime', |
||
1043 | 'dbType' => 'time', |
||
1044 | 'value' => new \DateTime |
||
1045 | ] |
||
1046 | ], |
||
1047 | [ |
||
1048 | [ |
||
1049 | 'fieldName' => 'object', |
||
1050 | 'phpType' => '\stdClass', |
||
1051 | 'dbType' => 'object', |
||
1052 | 'value' => new \stdClass() |
||
1053 | ] |
||
1054 | ], |
||
1055 | [ |
||
1056 | [ |
||
1057 | 'fieldName' => 'bigint', |
||
1058 | 'phpType' => 'int', |
||
1059 | 'dbType' => 'bigint', |
||
1060 | 'value' => 11 |
||
1061 | ] |
||
1062 | ], |
||
1063 | [ |
||
1064 | [ |
||
1065 | 'fieldName' => 'smallint', |
||
1066 | 'phpType' => 'int', |
||
1067 | 'dbType' => 'smallint', |
||
1068 | 'value' => 22 |
||
1069 | ] |
||
1070 | ], |
||
1071 | [ |
||
1072 | [ |
||
1073 | 'fieldName' => 'text', |
||
1074 | 'phpType' => 'string', |
||
1075 | 'dbType' => 'text', |
||
1076 | 'value' => 'text' |
||
1077 | ] |
||
1078 | ], |
||
1079 | [ |
||
1080 | [ |
||
1081 | 'fieldName' => 'blob', |
||
1082 | 'phpType' => 'string', |
||
1083 | 'dbType' => 'blob', |
||
1084 | 'value' => 'blob' |
||
1085 | ] |
||
1086 | ], |
||
1087 | [ |
||
1088 | [ |
||
1089 | 'fieldName' => 'decimal', |
||
1090 | 'phpType' => 'string', |
||
1091 | 'dbType' => 'decimal', |
||
1092 | 'value' => '12.34' |
||
1093 | ], |
||
1094 | ] |
||
1095 | ]; |
||
1096 | } |
||
1097 | |||
1098 | public function getParseTokensInEntityFileData() |
||
1099 | { |
||
1100 | return [ |
||
1101 | [ |
||
1102 | '<?php namespace Foo\Bar; class Baz {}', |
||
1103 | ['Foo\Bar\Baz'], |
||
1104 | ], |
||
1105 | [ |
||
1106 | '<?php namespace Foo\Bar; use Foo; class Baz {}', |
||
1107 | ['Foo\Bar\Baz'], |
||
1108 | ], |
||
1109 | [ |
||
1110 | '<?php namespace /*Comment*/ Foo\Bar; /** Foo */class /* Comment */ Baz {}', |
||
1111 | ['Foo\Bar\Baz'], |
||
1112 | ], |
||
1113 | [ |
||
1114 | ' |
||
1115 | <?php namespace |
||
1116 | /*Comment*/ |
||
1117 | Foo\Bar |
||
1118 | ; |
||
1119 | |||
1120 | /** Foo */ |
||
1121 | class |
||
1122 | /* Comment */ |
||
1123 | Baz {} |
||
1124 | ', |
||
1125 | ['Foo\Bar\Baz'], |
||
1126 | ], |
||
1127 | [ |
||
1128 | ' |
||
1129 | <?php namespace Foo\Bar; class Baz { |
||
1130 | public static function someMethod(){ |
||
1131 | return self::class; |
||
1132 | } |
||
1133 | } |
||
1134 | ', |
||
1135 | ['Foo\Bar\Baz'], |
||
1136 | ], |
||
1137 | ]; |
||
1138 | } |
||
1139 | |||
1140 | /** |
||
1141 | * @param string $type |
||
1142 | * @param \ReflectionProperty $property |
||
1143 | */ |
||
1144 | View Code Duplication | private function assertPhpDocVarType($type, \ReflectionProperty $property) |
|
1145 | { |
||
1146 | $docComment = $property->getDocComment(); |
||
1147 | $regex = '/@var\s+([\S]+)$/m'; |
||
1148 | |||
1149 | $this->assertRegExp($regex, $docComment); |
||
1150 | $this->assertEquals(1, preg_match($regex, $docComment, $matches)); |
||
1151 | $this->assertEquals($type, $matches[1]); |
||
1152 | } |
||
1153 | |||
1154 | /** |
||
1155 | * @param string $type |
||
1156 | * @param \ReflectionMethod $method |
||
1157 | */ |
||
1158 | View Code Duplication | private function assertPhpDocReturnType($type, \ReflectionMethod $method) |
|
1159 | { |
||
1160 | $docComment = $method->getDocComment(); |
||
1161 | $regex = '/@return\s+([\S]+)(\s+.*)$/m'; |
||
1162 | |||
1163 | $this->assertRegExp($regex, $docComment); |
||
1164 | $this->assertEquals(1, preg_match($regex, $docComment, $matches)); |
||
1165 | $this->assertEquals($type, $matches[1]); |
||
1166 | } |
||
1167 | |||
1168 | /** |
||
1169 | * @param string $type |
||
1170 | * @param \ReflectionProperty $method |
||
1171 | */ |
||
1172 | private function assertPhpDocParamType($type, \ReflectionMethod $method) |
||
1173 | { |
||
1174 | $this->assertEquals(1, preg_match('/@param\s+([^\s]+)/', $method->getDocComment(), $matches)); |
||
1175 | $this->assertEquals($type, $matches[1]); |
||
1176 | } |
||
1177 | } |
||
1178 | |||
1179 | class EntityGeneratorAuthor {} |
||
1180 | class EntityGeneratorComment {} |
||
1181 |
If you access a property on an interface, you most likely code against a concrete implementation of the interface.
Available Fixes
Adding an additional type check:
Changing the type hint: