From 533fd11b4e994369eba5f873c6438e5ce2426cbd Mon Sep 17 00:00:00 2001 From: provokateurin Date: Mon, 15 Apr 2024 06:42:18 +0200 Subject: [PATCH] fix(OpenApiType): Use maxItems instead of maxLength for arrays Signed-off-by: provokateurin --- src/ControllerMethod.php | 2 +- src/Helpers.php | 2 +- src/OpenApiType.php | 10 ++- tests/appinfo/routes.php | 1 + tests/lib/Controller/SettingsController.php | 12 +++ tests/openapi-administration.json | 83 +++++++++++++++++++++ tests/openapi-full.json | 83 +++++++++++++++++++++ 7 files changed, 190 insertions(+), 3 deletions(-) diff --git a/src/ControllerMethod.php b/src/ControllerMethod.php index 90a7d35..83474d1 100644 --- a/src/ControllerMethod.php +++ b/src/ControllerMethod.php @@ -84,7 +84,7 @@ public static function parse(string $context, array $definitions, ClassMethod $m } if (str_starts_with($type->name, 'OCS') && str_ends_with($type->name, 'Exception')) { - $responses[] = new ControllerMethodResponse($docNode->value->type, $statusCode, "application/json", new OpenApiType(type: "array", maxLength: 0), null); + $responses[] = new ControllerMethodResponse($docNode->value->type, $statusCode, "application/json", new OpenApiType(type: "array", maxItems: 0), null); } else { $responses[] = new ControllerMethodResponse($docNode->value->type, $statusCode, "text/plain", new OpenApiType(type: "string"), null); } diff --git a/src/Helpers.php b/src/Helpers.php index 0d16d8f..bfd3058 100644 --- a/src/Helpers.php +++ b/src/Helpers.php @@ -136,7 +136,7 @@ public static function wrapOCSResponse(Route $route, ControllerMethodResponse $r } public static function cleanEmptyResponseArray(array $schema): array|stdClass { - if (key_exists("type", $schema) && $schema["type"] == "array" && key_exists("maxLength", $schema) && $schema["maxLength"] === 0) { + if (array_key_exists('type', $schema) && $schema['type'] === 'array' && array_key_exists('maxItems', $schema) && $schema['maxItems'] === 0) { return new stdClass(); } diff --git a/src/OpenApiType.php b/src/OpenApiType.php index ba5f82f..e649fec 100644 --- a/src/OpenApiType.php +++ b/src/OpenApiType.php @@ -47,6 +47,8 @@ public function __construct( public ?int $maxLength = null, public ?int $minimum = null, public ?int $maximum = null, + public ?int $minItems = null, + public ?int $maxItems = null, public ?array $enum = null, ) { } @@ -120,6 +122,12 @@ public function toArray(string $openapiVersion, bool $isParameter = false): arra if ($this->maximum !== null) { $values["maximum"] = $this->maximum; } + if ($this->minItems !== null) { + $values["minItems"] = $this->minItems; + } + if ($this->maxItems !== null) { + $values["maxItems"] = $this->maxItems; + } if ($this->required !== null) { $values["required"] = $this->required; } @@ -166,7 +174,7 @@ public static function resolve(string $context, array $definitions, ParamTagValu } if ($node instanceof GenericTypeNode && ($node->type->name == "array" || $node->type->name == "list") && count($node->genericTypes) == 1) { if ($node->genericTypes[0] instanceof IdentifierTypeNode && $node->genericTypes[0]->name == "empty") { - return new OpenApiType(type: "array", maxLength: 0); + return new OpenApiType(type: "array", maxItems: 0); } return new OpenApiType(type: "array", items: self::resolve($context, $definitions, $node->genericTypes[0])); } diff --git a/tests/appinfo/routes.php b/tests/appinfo/routes.php index 24945ef..9f13e71 100644 --- a/tests/appinfo/routes.php +++ b/tests/appinfo/routes.php @@ -72,5 +72,6 @@ ['name' => 'Settings#oneOf', 'url' => '/api/{apiVersion}/oneOf', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], ['name' => 'Settings#anyOf', 'url' => '/api/{apiVersion}/anyOf', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], ['name' => 'Settings#floatDouble', 'url' => '/api/{apiVersion}/floatDouble', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], + ['name' => 'Settings#emptyArray', 'url' => '/api/{apiVersion}/emptyArray', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], ], ]; diff --git a/tests/lib/Controller/SettingsController.php b/tests/lib/Controller/SettingsController.php index de9c165..002d10b 100644 --- a/tests/lib/Controller/SettingsController.php +++ b/tests/lib/Controller/SettingsController.php @@ -526,4 +526,16 @@ public function anyOf(): DataResponse { public function floatDouble(): DataResponse { return new DataResponse(); } + + /** + * Route with empty array + * + * @return DataResponse}, array{}> + * + * 200: OK + */ + #[PasswordConfirmationRequired] + public function emptyArray(): DataResponse { + return new DataResponse(); + } } diff --git a/tests/openapi-administration.json b/tests/openapi-administration.json index e34f6fa..c483091 100644 --- a/tests/openapi-administration.json +++ b/tests/openapi-administration.json @@ -3021,6 +3021,89 @@ } } }, + "/ocs/v2.php/apps/notifications/api/{apiVersion}/emptyArray": { + "post": { + "operationId": "settings-empty-array", + "summary": "Route with empty array", + "description": "This endpoint requires admin access\nThis endpoint requires password confirmation", + "tags": [ + "settings" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "apiVersion", + "in": "path", + "required": true, + "schema": { + "type": "string", + "enum": [ + "v2" + ], + "default": "v2" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "test" + ], + "properties": { + "test": { + "type": "array", + "maxItems": 0 + } + } + } + } + } + } + } + } + } + } + } + } + }, "/ocs/v2.php/tests/attribute-ocs/{param}": { "get": { "operationId": "routing-attributeocs-route", diff --git a/tests/openapi-full.json b/tests/openapi-full.json index ca7c8a3..ab89a28 100644 --- a/tests/openapi-full.json +++ b/tests/openapi-full.json @@ -3148,6 +3148,89 @@ } } }, + "/ocs/v2.php/apps/notifications/api/{apiVersion}/emptyArray": { + "post": { + "operationId": "settings-empty-array", + "summary": "Route with empty array", + "description": "This endpoint requires admin access\nThis endpoint requires password confirmation", + "tags": [ + "settings" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "apiVersion", + "in": "path", + "required": true, + "schema": { + "type": "string", + "enum": [ + "v2" + ], + "default": "v2" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "test" + ], + "properties": { + "test": { + "type": "array", + "maxItems": 0 + } + } + } + } + } + } + } + } + } + } + } + } + }, "/ocs/v2.php/tests/attribute-ocs/{param}": { "get": { "operationId": "routing-attributeocs-route",