diff --git a/composer.json b/composer.json index 393732c..737f1b7 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,8 @@ "symfony/yaml": "^2.1|^3.0", "goetas-webservices/xsd-reader": "^0.1.2", "doctrine/inflector": "^1.0", - "zendframework/zend-code": "~2.3" + "zendframework/zend-code": "~2.3", + "cocur/slugify": "^2.3" }, "require-dev": { "phpunit/phpunit": "^4.8|^5.0", diff --git a/lib/Jms/YamlConverter.php b/lib/Jms/YamlConverter.php index 0c82da0..94c3db1 100644 --- a/lib/Jms/YamlConverter.php +++ b/lib/Jms/YamlConverter.php @@ -263,6 +263,11 @@ private function visitSimpleType(&$class, &$data, SimpleType $type, $name) if ($parent instanceof Type) { $this->handleClassExtension($class, $data, $parent, $name); } + + $checks = $restriction->getChecks(); + if (count($checks) && isset($checks['enumeration'])) { + $data['properties']['__value']['xml_element'] = ['cdata' => false]; + } } elseif ($unions = $type->getUnions()) { foreach ($unions as $i => $unon) { $this->handleClassExtension($class, $data, $unon, $name . $i); diff --git a/lib/Php/ClassGenerator.php b/lib/Php/ClassGenerator.php index 1bdc8d8..f809deb 100644 --- a/lib/Php/ClassGenerator.php +++ b/lib/Php/ClassGenerator.php @@ -4,6 +4,7 @@ use Doctrine\Common\Inflector\Inflector; use Goetas\Xsd\XsdToPhp\Php\Structure\PHPClass; use Goetas\Xsd\XsdToPhp\Php\Structure\PHPClassOf; +use Goetas\Xsd\XsdToPhp\Php\Structure\PhpConstant; use Goetas\Xsd\XsdToPhp\Php\Structure\PHPProperty; use Zend\Code\Generator; use Zend\Code\Generator\DocBlock\Tag\ParamTag; @@ -19,6 +20,10 @@ class ClassGenerator private function handleBody(Generator\ClassGenerator $class, PHPClass $type) { + foreach ($type->getConstants() as $const) { + $this->handleConstant($class, $const); + } + foreach ($type->getProperties() as $prop) { if ($prop->getName() !== '__value') { $this->handleProperty($class, $prop); @@ -31,7 +36,12 @@ private function handleBody(Generator\ClassGenerator $class, PHPClass $type) } if (count($type->getProperties()) === 1 && $type->hasProperty('__value')) { - return false; + if (!count($type->getConstants())) { + return false; + } + $class->removeMethod('__construct') + ->removeMethod('__toString') + ->removeMethod('value'); } return true; @@ -150,7 +160,7 @@ private function handleSetter(Generator\ClassGenerator $generator, PHPProperty $ $method = new MethodGenerator("set" . Inflector::classify($prop->getName())); - $parameter = new ParameterGenerator($prop->getName(), "mixed"); + $parameter = new ParameterGenerator($prop->getName(), "mixed", new Generator\ValueGenerator(null, Generator\ValueGenerator::TYPE_NULL)); if ($type && $type instanceof PHPClassOf) { $patramTag->setTypes($this->getPhpType($type->getArg() @@ -389,13 +399,18 @@ private function handleProperty(Generator\ClassGenerator $class, PHPProperty $pr $docBlock->setTag($tag); } + private function handleConstant(Generator\ClassGenerator $class, PhpConstant $const) + { + $class->addConstant($const->getName(), $const->getValue()); + } + public function generate(Generator\ClassGenerator $class, PHPClass $type) { $docblock = new DocBlockGenerator("Class representing " . $type->getName()); if ($type->getDoc()) { $docblock->setLongDescription($type->getDoc()); } - $class->setNamespaceName($type->getNamespace() ?: NULL); + $class->setNamespaceName($type->getNamespace()); $class->setName($type->getName()); $class->setDocblock($docblock); diff --git a/lib/Php/PhpConverter.php b/lib/Php/PhpConverter.php index 00632e1..80245a7 100644 --- a/lib/Php/PhpConverter.php +++ b/lib/Php/PhpConverter.php @@ -1,6 +1,8 @@ visitTypeBase($class, $type); + if ( ( $restriction = $type->getRestriction() ) && $restriction->getChecksByType( 'enumeration' ) ) { + return $class; + } + if ($type instanceof SimpleType) { $this->classes[spl_object_hash($type)]["skip"] = true; return $class; @@ -286,7 +292,14 @@ private function visitSimpleType(PHPClass $class, SimpleType $type) foreach ($restriction->getChecks() as $typeCheck => $checks) { foreach ($checks as $check) { - $class->addCheck('__value', $typeCheck, $check); + if ( $typeCheck === 'enumeration' ) { + $class->addConstant( + $this->createConstantNameFromValue( $check[ 'value' ] ), + $check[ 'value' ] + ); + } else { + $class->addCheck( '__value', $typeCheck, $check ); + } } } } elseif ($unions = $type->getUnions()) { @@ -425,4 +438,100 @@ private function findPHPClass(PHPClass $class, Item $node, $force = false) return $this->visitType($node->getType(), $force); } } + /** + * @param $constantValue + * + * @return string + */ + public function createConstantNameFromValue( $constantValue ) { + static $keywords = [ + 'abstract', + 'and', + 'array', + 'as', + 'break', + 'callable', + 'case', + 'catch', + 'class', + 'clone', + 'const', + 'continue', + 'declare', + 'default', + 'die', + 'do', + 'echo', + 'else', + 'elseif', + 'empty', + 'enddeclare', + 'endfor', + 'endforeach', + 'endif', + 'endswitch', + 'endwhile', + 'eval', + 'exit', + 'extends', + 'final', + 'for', + 'foreach', + 'function', + 'global', + 'goto', + 'if', + 'implements', + 'include', + 'include_once', + 'instanceof', + 'insteadof', + 'interface', + 'isset', + 'list', + 'namespace', + 'new', + 'or', + 'print', + 'private', + 'protected', + 'public', + 'require', + 'require_once', + 'return', + 'static', + 'switch', + 'throw', + 'trait', + 'try', + 'unset', + 'use', + 'var', + 'while', + 'xor', + ]; + + $slugify = new Slugify(); + $constantName = $slugify->slugify( $constantValue, '_' ); + if ( in_array( $constantName, $keywords ) ) { + $constantName = $constantName . '_'; + } + + if (is_numeric($constantName)) { + $constantName = 'NUM_' . $constantName; + } + + if (is_numeric(substr($constantName, 0, 1))) { + $constantName = '_' . $constantName; + } + + if ($constantName === '') { + $constantName = 'EMPTY_STRING'; + } + + $constantName = strtoupper( $constantName ); + + return $constantName; + } + } diff --git a/lib/Php/Structure/PHPClass.php b/lib/Php/Structure/PHPClass.php index 51f285a..808148a 100644 --- a/lib/Php/Structure/PHPClass.php +++ b/lib/Php/Structure/PHPClass.php @@ -239,4 +239,17 @@ public function setAbstract($abstract) $this->abstract = (boolean)$abstract; return $this; } + + public function addConstant($constantName, $constantValue) + { + $this->constants[] = new PhpConstant($constantName, $constantValue); + } + + /** + * @return PHPConstant[] + */ + public function getConstants() + { + return $this->constants; + } } diff --git a/lib/Php/Structure/PhpConstant.php b/lib/Php/Structure/PhpConstant.php new file mode 100644 index 0000000..8c9ee43 --- /dev/null +++ b/lib/Php/Structure/PhpConstant.php @@ -0,0 +1,47 @@ +name = $name; + $this->value = $value; + } + + /** + * @return string + */ + public function getName() { + return $this->name; + } + + /** + * @param string $name + */ + public function setName( $name ) { + $this->name = $name; + } + + /** + * @return string + */ + public function getValue() { + return $this->value; + } + + /** + * @param string $value + */ + public function setValue( $value ) { + $this->value = $value; + } +}