From c832b5f85a2faf874923ac78e405c0c052b5f3b0 Mon Sep 17 00:00:00 2001 From: Patrik Foldes Date: Wed, 5 Feb 2020 18:46:00 +0300 Subject: [PATCH] Implemented default value support --- README.md | 1 + src/CodeGenerator/ApiServerCodeGenerator.php | 2 +- src/CodeGenerator/Dto/PhpParserDtoFactory.php | 48 ++++++++++++++++--- .../Naming/DefaultNamingStrategy.php | 2 +- 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 3f6b925..53772f2 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ operation must have an unique `operationId`. Currently, there are also the following limitations: - `number` without `format` is treated as float +- Default values are not supported for `date` and `date-time` string formats - Only scalar types are allowed in path parameters - Partial match pattern are ignored in path parameter patterns, only `^...$` patterns are used - If pattern is specified in path parameter then type- and format-generated requirements are ignored diff --git a/src/CodeGenerator/ApiServerCodeGenerator.php b/src/CodeGenerator/ApiServerCodeGenerator.php index 6df5201..5a6ac99 100644 --- a/src/CodeGenerator/ApiServerCodeGenerator.php +++ b/src/CodeGenerator/ApiServerCodeGenerator.php @@ -85,7 +85,7 @@ public function generate() : void foreach ($this->loader->list() as $specificationName => $specification) { $parsedSpecification = $this->loader->load($specificationName); - $apiName = $specification->getNameSpace(); + $apiName = $this->namingStrategy->stringToNamespace($specification->getNameSpace()); $specMediaType = $specification->getMediaType(); $apiNamespace = $this->namingStrategy->buildNamespace($this->rootNamespace, self::APIS_NAMESPACE, $apiName); $apiPath = $this->namingStrategy->buildPath($this->rootPath, self::APIS_NAMESPACE, $apiName); diff --git a/src/CodeGenerator/Dto/PhpParserDtoFactory.php b/src/CodeGenerator/Dto/PhpParserDtoFactory.php index 989822e..a6ba8cb 100644 --- a/src/CodeGenerator/Dto/PhpParserDtoFactory.php +++ b/src/CodeGenerator/Dto/PhpParserDtoFactory.php @@ -28,6 +28,7 @@ use PhpParser\PrettyPrinter\Standard; use function array_map; use function array_merge; +use function class_exists; use function count; use function implode; use function in_array; @@ -89,11 +90,19 @@ public function generateParamDto( $type = null; $iterableType = null; $required = $parameter->required; + $default = null; if (! $parameter->schema instanceof Schema) { continue; } + /** @var string|int|float|bool|null $schemaDefaultValue */ + $schemaDefaultValue = $parameter->schema->default; + + $defaultValue = $schemaDefaultValue !== null && class_exists( + $this->typeResolver->getPhpType($this->typeResolver->findScalarType($parameter->schema)) + ) ? null : $schemaDefaultValue; + if (Type::isScalar($parameter->schema->type)) { $typeId = $this->typeResolver->findScalarType($parameter->schema); $type = $this->typeResolver->getPhpType($typeId); @@ -138,6 +147,7 @@ public function generateParamDto( $parameter->name, $type, ! $required, + $defaultValue, $iterableType, $parameter->description ) @@ -147,6 +157,7 @@ public function generateParamDto( $parameter->name, $type, ! $required, + $defaultValue, $iterableType ) ); @@ -229,6 +240,7 @@ public function generateDtoClassGraph( $type = null; $iterableType = null; + $defaultValue = null; /** * @psalm-suppress RedundantConditionGivenDocblockType */ @@ -238,6 +250,13 @@ public function generateDtoClassGraph( throw new Exception('Cannot work with References'); } + /** @var string|int|float|bool|null $schemaDefaultValue */ + $schemaDefaultValue = $property->default; + + $defaultValue = $schemaDefaultValue !== null && class_exists( + $this->typeResolver->getPhpType($this->typeResolver->findScalarType($property)) + ) ? null : $schemaDefaultValue; + if (Type::isScalar($property->type)) { $typeId = $this->typeResolver->findScalarType($property); $type = $this->typeResolver->getPhpType($typeId); @@ -307,6 +326,7 @@ public function generateDtoClassGraph( $propertyName, $type, ! $required, + $defaultValue, $iterableType, $property->description ) @@ -328,7 +348,13 @@ public function generateDtoClassGraph( } } - $getterBuilders[] = $this->getGetterDefinition($propertyName, $type, ! $required, $iterableType); + $getterBuilders[] = $this->getGetterDefinition( + $propertyName, + $type, + ! $required, + $defaultValue, + $iterableType + ); } if ($constructorRequired) { @@ -469,10 +495,14 @@ private function getConstructorDocBlock(array $lines) : string return implode(PHP_EOL, ['/**', ...$lines, ' */']); } + /** + * @param string|int|float|bool|null $defaultValue + */ private function getPropertyDefinition( string $name, string $type, bool $nullable = false, + $defaultValue = null, ?string $iterableType = null, ?string $description = null ) : Property { @@ -480,7 +510,9 @@ private function getPropertyDefinition( ->property($name) ->makePrivate(); - if ($nullable) { + if ($defaultValue !== null) { + $property->setDefault($defaultValue); + } elseif ($nullable) { $property->setDefault(null); } @@ -490,10 +522,10 @@ private function getPropertyDefinition( $docCommentLines[] = sprintf(' %s', $description); } - $nullableDocblock = $nullable ? '|null' : ''; + $nullableDocblock = $nullable && $defaultValue === null ? '|null' : ''; if (version_compare($this->languageLevel, '7.4.0') >= 0) { - $property->setType(($nullable ? '?' : '') . ($iterableType ? 'array' : $type)); + $property->setType(($nullable && $defaultValue === null ? '?' : '') . ($iterableType ? 'array' : $type)); } if (count($docCommentLines) > 0) { @@ -542,16 +574,20 @@ private function getAssignmentDefinition(string $name) : Assign return new Assign(new Variable('this->' . $name), new Variable($name)); } + /** + * @param string|int|float|bool|null $defaultValue + */ private function getGetterDefinition( string $name, string $type, bool $nullable = false, + $defaultValue = null, ?string $iterableType = null ) : Method { $method = $this->factory ->method('get' . ucfirst($name)) ->makePublic() - ->setReturnType(($nullable ? '?' : '') . ($iterableType ? 'array' : $type)) + ->setReturnType(($nullable && $defaultValue === null ? '?' : '') . ($iterableType ? 'array' : $type)) ->addStmt(new Return_(new Variable('this->' . $name))); if ($iterableType !== null) { @@ -559,7 +595,7 @@ private function getGetterDefinition( sprintf( '/** @return %s[]%s */', $iterableType, - $nullable ? '|null' : '' + $nullable && $defaultValue === null ? '|null' : '' ) ); } diff --git a/src/CodeGenerator/Naming/DefaultNamingStrategy.php b/src/CodeGenerator/Naming/DefaultNamingStrategy.php index e379fd5..0b4d973 100644 --- a/src/CodeGenerator/Naming/DefaultNamingStrategy.php +++ b/src/CodeGenerator/Naming/DefaultNamingStrategy.php @@ -47,7 +47,7 @@ public function getInterfaceFQCN(string $apiNameSpace, string $operationId) : st ApiServerCodeGenerator::APIS_NAMESPACE, $apiNameSpace, $this->stringToNamespace($operationId), - $this->stringToNamespace($operationId) . ApiServerCodeGenerator::SERVICE_SUFFIX, + $this->stringToNamespace($operationId), ); return $interfaceNamespace;