diff --git a/composer.json b/composer.json index 9f328d2..5543e1c 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "description": "Swagger yaml generator", "keywords": ["api", "swagger", "open auth"], "license": "MIT", - "version": "1.4.5", + "version": "1.4.6", "authors": [ { "name": "Digit", diff --git a/src/Describer/WithTypeParser.php b/src/Describer/WithTypeParser.php index 14f167a..0ebaa06 100644 --- a/src/Describer/WithTypeParser.php +++ b/src/Describer/WithTypeParser.php @@ -211,19 +211,50 @@ public function isTypeClassName(string $type): bool */ public function normalizeType(string $type, bool $stripArray = false): string { - $type = strpos($type, '|') ? explode('|', $type)[0] : $type; - if ($stripArray && $this->isTypeArray($type, false)) { - $type = substr($type, 0, -2); + [$typeNormalized] = $this->normalizeTypeAndNullableFlag($type, $stripArray); + + return $typeNormalized; + } + + /** + * Normalize the PHP type and return `nullable` flag. + * + * @param string $type + * @param bool $stripArray + * @return array + */ + public function normalizeTypeAndNullableFlag(string $type, bool $stripArray = false): array + { + [$typeParsed, $nullable] = $this->getNormalizedPhpTypeInfo($type); + if ($stripArray && $this->isTypeArray($typeParsed, false)) { + $typeParsed = substr($typeParsed, 0, -2); } - $typeLower = strtolower($type); - if (isset($this->basicTypesSyn[$typeLower])) { - return $this->basicTypesSyn[$typeLower]; + $typeLower = strtolower($typeParsed); + if (($typeSyn = $this->basicTypesSyn[$typeLower] ?? null) !== null) { + return [$typeSyn, $nullable]; } - if (str_contains($type, '\\') || class_exists($type) || interface_exists($type)) { - return ltrim($type, '\\'); + if (str_contains($typeParsed, '\\') || class_exists($typeParsed) || interface_exists($typeParsed)) { + return [ltrim($typeParsed, '\\'), $nullable]; } - return $typeLower; + return [$typeLower, $nullable]; + } + + /** + * Get normalized type info. + * + * @param string $type Type to parse + * @param string $defaultType Default type if nothing was found + * @return array{string,bool} Type, Is_Nullable + */ + protected function getNormalizedPhpTypeInfo(string $type, string $defaultType = 'string'): array + { + $types = strpos($type, '|') ? explode('|', $type) : [$type]; + $nullTypes = ['null', 'NULL', 'Null']; + $nullable = ! empty(array_intersect($nullTypes, $types)); + $typesFiltered = array_diff($types, $nullTypes); + + return [! empty($typesFiltered) ? reset($typesFiltered) : $defaultType, $nullable]; } /** diff --git a/src/Parser/WithDocParser.php b/src/Parser/WithDocParser.php index a1fd9cc..0f9cf4e 100644 --- a/src/Parser/WithDocParser.php +++ b/src/Parser/WithDocParser.php @@ -68,11 +68,14 @@ protected function getDocTagsPropertiesDescribed(string $docStr, string $tagName $type = (string)$tag->getType(); $name = $tag->getVariableName(); $description = $tag->getDescription(); - $type = $this->describer()->normalizeType($type); + [$typeNormalized, $nullable] = $this->describer()->normalizeTypeAndNullableFlag($type); $result[$name] = [ - 'type' => $type, + 'type' => $typeNormalized, 'description' => $description?->render(), ]; + if ($nullable) { + $result[$name]['nullable'] = $nullable; + } } return $result;