Skip to content

Commit 9152e77

Browse files
eceltovkrulis-martin
authored andcommitted
response formats now propagate to the swagger
1 parent 161186c commit 9152e77

File tree

4 files changed

+53
-24
lines changed

4 files changed

+53
-24
lines changed

app/helpers/MetaFormats/Attributes/ResponseFormat.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@
77
/**
88
* Attribute defining response format on endpoints.
99
*/
10-
#[Attribute]
10+
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
1111
class ResponseFormat
1212
{
13-
public string $class;
13+
public readonly string $format;
14+
public readonly int $statusCode;
1415

15-
public function __construct(string $class)
16+
public function __construct(string $format, int $statusCode = 200)
1617
{
17-
$this->class = $class;
18+
$this->format = $format;
19+
$this->statusCode = $statusCode;
1820
}
1921
}

app/helpers/MetaFormats/MetaFormatHelper.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,21 @@ public static function extractFormatFromAttribute(
4444
}
4545

4646
/**
47-
* Checks whether an entity contains a ResponseFormat attribute and extracts the format if so.
47+
* Checks whether an entity contains ResponseFormat attributes and returns them.
4848
* @param \ReflectionClass|\ReflectionProperty|\ReflectionMethod $reflectionObject A reflection
4949
* object of the entity.
50-
* @return ?string Returns the format or null if no ResponseFormat attribute was present.
50+
* @return array Returns an array of attribute instances.
5151
*/
5252
public static function extractResponseFormatFromAttribute(
5353
ReflectionClass | ReflectionProperty | ReflectionMethod $reflectionObject
54-
): ?string {
54+
): array {
5555
$formatAttributes = $reflectionObject->getAttributes(ResponseFormat::class);
56-
if (count($formatAttributes) === 0) {
57-
return null;
56+
$instances = [];
57+
foreach ($formatAttributes as $formatAttribute) {
58+
$instances[] = $formatAttribute->newInstance();
5859
}
5960

60-
$formatAttribute = $formatAttributes[0]->newInstance();
61-
return $formatAttribute->class;
61+
return $instances;
6262
}
6363

6464
/**

app/helpers/Swagger/AnnotationData.php

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ class AnnotationData
3131
* @var AnnotationParameterData[]
3232
*/
3333
public array $fileParams;
34+
/**
35+
* @var array<int, array<AnnotationParameterData>>
36+
*/
37+
public array $statusToParamsMap;
3438
public ?string $endpointDescription;
3539

3640
public function __construct(
@@ -41,8 +45,8 @@ public function __construct(
4145
array $queryParams,
4246
array $bodyParams,
4347
array $fileParams,
48+
array $statusToParamsMap,
4449
?string $endpointDescription = null,
45-
?array $responseParams = null,
4650
) {
4751
$this->className = $className;
4852
$this->methodName = $methodName;
@@ -51,8 +55,8 @@ public function __construct(
5155
$this->queryParams = $queryParams;
5256
$this->bodyParams = $bodyParams;
5357
$this->fileParams = $fileParams;
58+
$this->statusToParamsMap = $statusToParamsMap;
5459
$this->endpointDescription = $endpointDescription;
55-
$this->responseParams = $responseParams;
5660
}
5761

5862
public function getAllParams(): array
@@ -231,9 +235,21 @@ public function toSwaggerAnnotations(string $route)
231235
$body->addValue($bodyProperties);
232236
}
233237

234-
///TODO: A placeholder for the response type. This has to be replaced with the autogenerated meta-view
235-
/// response data structure in the future.
236-
$body->addValue('@OA\Response(response="200",description="The data")');
238+
// generate responses
239+
foreach ($this->statusToParamsMap as $statusCode => $responseParams) {
240+
$responseSchema = $this->serializeBodyParams(
241+
"application/json",
242+
$responseParams
243+
);
244+
245+
$body->addValue('@OA\Response(response="' . $statusCode . '", ' . $responseSchema . ' )');
246+
}
247+
248+
// add a placeholder response if none present
249+
if (count($this->statusToParamsMap) === 0) {
250+
$body->addValue('@OA\Response(response="200",description="Placeholder response")');
251+
}
252+
237253
return $httpMethodAnnotation . $body->toString();
238254
}
239255
}

app/helpers/Swagger/AnnotationHelper.php

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace App\Helpers\Swagger;
44

5+
use App\Exceptions\InternalServerException;
56
use App\Helpers\MetaFormats\FormatCache;
67
use App\Helpers\MetaFormats\MetaFormatHelper;
78
use App\V1Module\Router\MethodRoute;
@@ -289,8 +290,8 @@ private static function annotationParameterDataToAnnotationData(
289290
string $methodName,
290291
HttpMethods $httpMethod,
291292
array $params,
293+
array $statusToParamsMap,
292294
?string $description,
293-
?array $responseParams = null,
294295
): AnnotationData {
295296
$pathParams = [];
296297
$queryParams = [];
@@ -319,8 +320,8 @@ private static function annotationParameterDataToAnnotationData(
319320
$queryParams,
320321
$bodyParams,
321322
$fileParams,
323+
$statusToParamsMap,
322324
$description,
323-
$responseParams,
324325
);
325326
}
326327

@@ -350,6 +351,7 @@ public static function extractStandardAnnotationData(
350351
$methodName,
351352
$httpMethod,
352353
$params,
354+
[], // there are no reponse params defined in the old annotations
353355
$description
354356
);
355357
}
@@ -379,14 +381,23 @@ public static function extractAttributeData(string $className, string $methodNam
379381
$attributeData = array_merge($attributeData, FormatCache::getFieldDefinitions($format));
380382
}
381383

382-
// if the endpoint uses a response format, extract its parameters
383-
$responseFormat = MetaFormatHelper::extractResponseFormatFromAttribute($reflectionMethod);
384-
$responseParams = null;
385-
if ($responseFormat !== null) {
386-
$responseFieldDefinitions = FormatCache::getFieldDefinitions($responseFormat);
384+
// if the endpoint uses response formats, extract their parameters
385+
$responseAttributes = MetaFormatHelper::extractResponseFormatFromAttribute($reflectionMethod);
386+
$statusToParamsMap = [];
387+
foreach ($responseAttributes as $responseAttribute) {
388+
$responseFieldDefinitions = FormatCache::getFieldDefinitions($responseAttribute->format);
387389
$responseParams = array_map(function ($data) {
388390
return $data->toAnnotationParameterData();
389391
}, $responseFieldDefinitions);
392+
393+
// check if all response status codes are unique
394+
if (array_key_exists($responseAttribute->statusCode, $statusToParamsMap)) {
395+
throw new InternalServerException(
396+
"The method " . $reflectionMethod->name . " contains duplicate response codes."
397+
);
398+
}
399+
400+
$statusToParamsMap[$responseAttribute->statusCode] = $responseParams;
390401
}
391402

392403
$params = array_map(function ($data) {
@@ -399,8 +410,8 @@ public static function extractAttributeData(string $className, string $methodNam
399410
$methodName,
400411
$httpMethod,
401412
$params,
413+
$statusToParamsMap,
402414
$description,
403-
$responseParams,
404415
);
405416
}
406417

0 commit comments

Comments
 (0)