From 10f4c435c9870292a6cf7f84d955eeeb6941e4b8 Mon Sep 17 00:00:00 2001 From: Rouven Hurling Date: Wed, 24 Jan 2024 12:05:57 +0100 Subject: [PATCH] rewrite generateEndpointResponsesSpec to allow multiple content types and schemas (via oneOf) according to OpenAPI 3.0 spec --- src/Writing/OpenAPISpecWriter.php | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Writing/OpenAPISpecWriter.php b/src/Writing/OpenAPISpecWriter.php index 509c01f0..f1f1f5ff 100644 --- a/src/Writing/OpenAPISpecWriter.php +++ b/src/Writing/OpenAPISpecWriter.php @@ -263,12 +263,34 @@ protected function generateEndpointResponsesSpec(OutputEndpointData $endpoint) foreach ($endpoint->responses as $response) { // OpenAPI groups responses by status code - // Only one response type per status code, so only the last one will be used + // OpenAPI 3.0 allows multiple different response content types and schemas per content type (via oneOf), so all responses will be used and merged (but not deduplicated) + // Only the first response per status code sets the overall description of the response status code if (intval($response->status) === 204) { // Must not add content for 204 $responses[204] = [ 'description' => $this->getResponseDescription($response), ]; + } elseif (isset($responses[$response->status])) { + $content = $this->generateResponseContentSpec($response->content, $endpoint); + $contentType = array_keys($content)[0]; + if (isset($responses[$response->status]['content'][$contentType])) { + if (!isset($responses[$response->status]['content'][$contentType]['schema']['oneOf'])) { + $oldSchema = array_replace([ + 'description' => $responses[$response->status]['description'], + ], $responses[$response->status]['content'][$contentType]['schema']); + + $responses[$response->status]['content'][$contentType]['schema'] = [ + 'oneOf' => [$newSchema], + ]; + } + $newSchema = array_replace([ + 'description' => $this->getResponseDescription($response), + ], $content[$contentType]['schema']); + + $responses[$response->status]['content'][$contentType]['schema']['oneOf'][] = $newSchema; + } else { + $responses[$response->status]['content'][$contentType] = $content[$contentType]; + } } else { $responses[$response->status] = [ 'description' => $this->getResponseDescription($response),