From 4a6f4ab33480923ac6553ded903c97de168f37fe Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Sat, 25 Jun 2016 10:36:45 +0200 Subject: [PATCH] Make sure that valid classnames are being used in the implements and extends section of a class. --- src/Generator/ClassGenerator.php | 22 ++++++++++++- test/Generator/ClassGeneratorTest.php | 45 ++++++++++++++++++++++++--- 2 files changed, 62 insertions(+), 5 deletions(-) diff --git a/src/Generator/ClassGenerator.php b/src/Generator/ClassGenerator.php index c84e1b4c..2d382ebf 100644 --- a/src/Generator/ClassGenerator.php +++ b/src/Generator/ClassGenerator.php @@ -950,12 +950,13 @@ public function generate() $output .= static::OBJECT_TYPE . ' ' . $this->getName(); if (!empty($this->extendedClass)) { - $output .= ' extends ' . $this->extendedClass; + $output .= ' extends ' . $this->generateShortOrCompleteClassname($this->extendedClass); } $implemented = $this->getImplementedInterfaces(); if (!empty($implemented)) { + $implemented = array_map([$this, 'generateShortOrCompleteClassname'], $implemented); $output .= ' ' . static::IMPLEMENTS_KEYWORD . ' ' . implode(', ', $implemented); } @@ -1009,4 +1010,23 @@ private function validateConstantValue($value) gettype($value) )); } + + /** + * @param string $fqnClassName + * + * @return string + */ + private function generateShortOrCompleteClassname($fqnClassName) + { + $parts = explode('\\', $fqnClassName); + $className = array_pop($parts); + $classNamespace = implode('\\', $parts); + $currentNamespace = (string) $this->getNamespaceName(); + + if ($classNamespace === $currentNamespace || in_array($fqnClassName, $this->getUses())) { + return $className; + } + + return '\\' . $fqnClassName; + } } diff --git a/test/Generator/ClassGeneratorTest.php b/test/Generator/ClassGeneratorTest.php index c79f4dcb..039e5cd6 100644 --- a/test/Generator/ClassGeneratorTest.php +++ b/test/Generator/ClassGeneratorTest.php @@ -242,8 +242,8 @@ public function testClassFromReflectionThatImplementsInterfaces() $code = $classGenerator->generate(); $expectedClassDef = 'class ClassWithInterface' - . ' implements ZendTest\Code\Generator\TestAsset\OneInterface' - . ', ZendTest\Code\Generator\TestAsset\TwoInterface'; + . ' implements OneInterface' + . ', TwoInterface'; $this->assertContains($expectedClassDef, $code); } @@ -260,8 +260,8 @@ public function testClassFromReflectionDiscardParentImplementedInterfaces() $code = $classGenerator->generate(); $expectedClassDef = 'class NewClassWithInterface' - . ' extends ZendTest\Code\Generator\TestAsset\ClassWithInterface' - . ' implements ZendTest\Code\Generator\TestAsset\ThreeInterface'; + . ' extends ClassWithInterface' + . ' implements ThreeInterface'; $this->assertContains($expectedClassDef, $code); } @@ -1085,4 +1085,41 @@ final class SomeClass $output = $classGenerator->generate(); $this->assertEquals($expectedOutput, $output, $output); } + + public function testCorrectExtendNames() + { + $classGenerator = new ClassGenerator(); + $classGenerator->setName('ClassName'); + $classGenerator->setNamespaceName('SomeNamespace'); + $classGenerator->addUse('Zend\Code\NameInformation'); + $classGenerator->setExtendedClass('Zend\Code\NameInformation'); + $this->assertContains('class ClassName extends NameInformation', $classGenerator->generate()); + + $classGenerator = new ClassGenerator(); + $classGenerator->setName('ClassName'); + $classGenerator->setNamespaceName('SomeNamespace'); + $classGenerator->setExtendedClass('DateTime'); + $this->assertContains('class ClassName extends \DateTime', $classGenerator->generate()); + + $classGenerator = new ClassGenerator(); + $classGenerator->setName('ClassName'); + $classGenerator->setExtendedClass('DateTime'); + $this->assertContains('class ClassName extends DateTime', $classGenerator->generate()); + } + + public function testCorrectImplementNames() + { + $classGenerator = new ClassGenerator(); + $classGenerator->setName('ClassName'); + $classGenerator->setNamespaceName('SomeNamespace'); + $classGenerator->addUse('Zend\Code\Generator\GeneratorInterface'); + $classGenerator->setImplementedInterfaces([ + 'SomeNamespace\ClassInterface', + 'Zend\Code\Generator\GeneratorInterface', + 'Iteratable' + ]); + + $expected = 'class ClassName implements ClassInterface, GeneratorInterface, \Iteratable'; + $this->assertContains($expected, $classGenerator->generate()); + } }