diff --git a/src/ControllerMethod.php b/src/ControllerMethod.php index ce1dabc..5039bb5 100644 --- a/src/ControllerMethod.php +++ b/src/ControllerMethod.php @@ -82,7 +82,12 @@ public static function parse(string $context, array $definitions, ClassMethod $m } else { $responseDescriptions[$statusCode] = $docNode->value->description; } - $responses[] = new ControllerMethodResponse($docNode->value->type, $statusCode, "text/plain", new OpenApiType(type: "string"), null); + + 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); + } 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 6f820e5..0d16d8f 100644 --- a/src/Helpers.php +++ b/src/Helpers.php @@ -106,7 +106,9 @@ public static function mergeSchemas(array $schemas): mixed { } public static function wrapOCSResponse(Route $route, ControllerMethodResponse $response, array|stdClass $schema): array|stdClass { - if ($route->isOCS && $response->className == "DataResponse") { + if ($route->isOCS + && ($response->className === 'DataResponse' + || (str_starts_with($response->className, 'OCS') && str_ends_with($response->className, 'Exception')))) { return [ "type" => "object", "required" => [ diff --git a/tests/appinfo/routes.php b/tests/appinfo/routes.php index 10ad83a..43b8e7b 100644 --- a/tests/appinfo/routes.php +++ b/tests/appinfo/routes.php @@ -63,5 +63,7 @@ ['name' => 'Settings#numericParameter', 'url' => '/api/{apiVersion}/numeric', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], ['name' => 'Settings#arrayListParameter', 'url' => '/api/{apiVersion}/array-list', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], ['name' => 'Settings#arrayKeyedParameter', 'url' => '/api/{apiVersion}/array-keyed', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], + ['name' => 'Settings#throwingOCS', 'url' => '/api/{apiVersion}/throwing/ocs', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], + ['name' => 'Settings#throwingOther', 'url' => '/api/{apiVersion}/throwing/other', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], ], ]; diff --git a/tests/lib/Controller/SettingsController.php b/tests/lib/Controller/SettingsController.php index 27eb597..32ee004 100644 --- a/tests/lib/Controller/SettingsController.php +++ b/tests/lib/Controller/SettingsController.php @@ -31,6 +31,7 @@ use OCP\AppFramework\Http\Attribute\IgnoreOpenAPI; use OCP\AppFramework\Http\Attribute\OpenAPI; use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\OCS\OCSNotFoundException; use OCP\AppFramework\OCSController; /** @@ -410,4 +411,32 @@ public function arrayListParameter(array $value = ['test']): DataResponse { public function arrayKeyedParameter(array $value = ['test' => 'abc']): DataResponse { return new DataResponse(); } + + /** + * @NoAdminRequired + * + * Route throws an OCS exception + * + * @return DataResponse, array{}> + * @throws OCSNotFoundException Description of 404 because we throw all the time + * + * 200: Admin settings updated + */ + public function throwingOCS(): DataResponse { + throw new OCSNotFoundException(); + } + + /** + * @NoAdminRequired + * + * Route throws an OCS exception + * + * @return DataResponse, array{}> + * @throws NotFoundException Description of 404 because we throw all the time + * + * 200: Admin settings updated + */ + public function throwingOther(): DataResponse { + throw new NotFoundException(); + } } diff --git a/tests/openapi-full.json b/tests/openapi-full.json index 9230ef2..44d68b5 100644 --- a/tests/openapi-full.json +++ b/tests/openapi-full.json @@ -2963,6 +2963,186 @@ } } }, + "/ocs/v2.php/apps/notifications/api/{apiVersion}/throwing/ocs": { + "post": { + "operationId": "settings-throwingocs", + "summary": "Route throws an OCS exception", + "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": "Admin settings updated", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + }, + "404": { + "description": "Description of 404 because we throw all the time", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/notifications/api/{apiVersion}/throwing/other": { + "post": { + "operationId": "settings-throwing-other", + "summary": "Route throws an OCS exception", + "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": "Admin settings updated", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + }, + "500": { + "description": "Description of 404 because we throw all the time", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, "/ocs/v2.php/apps/notifications/api/{apiVersion}/controller-scope": { "post": { "operationId": "federation-federation-by-controller", diff --git a/tests/openapi.json b/tests/openapi.json index 7463c73..0394418 100644 --- a/tests/openapi.json +++ b/tests/openapi.json @@ -536,6 +536,186 @@ } } } + }, + "/ocs/v2.php/apps/notifications/api/{apiVersion}/throwing/ocs": { + "post": { + "operationId": "settings-throwingocs", + "summary": "Route throws an OCS exception", + "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": "Admin settings updated", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + }, + "404": { + "description": "Description of 404 because we throw all the time", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/notifications/api/{apiVersion}/throwing/other": { + "post": { + "operationId": "settings-throwing-other", + "summary": "Route throws an OCS exception", + "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": "Admin settings updated", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": {} + } + } + } + } + } + } + }, + "500": { + "description": "Description of 404 because we throw all the time", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + } + } + } } }, "tags": []