forked from nelmio/NelmioApiDocBundle
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMapQueryStringProcessor.php
More file actions
108 lines (88 loc) · 4.34 KB
/
MapQueryStringProcessor.php
File metadata and controls
108 lines (88 loc) · 4.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
<?php
declare(strict_types=1);
/*
* This file is part of the NelmioApiDocBundle package.
*
* (c) Nelmio
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Nelmio\ApiDocBundle\Processor;
use Nelmio\ApiDocBundle\OpenApiPhp\Util;
use Nelmio\ApiDocBundle\RouteDescriber\RouteArgumentDescriber\SymfonyMapQueryStringDescriber;
use OpenApi\Analysis;
use OpenApi\Annotations as OA;
use OpenApi\Generator;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
/**
* A processor that adds query parameters to operations that have a MapQueryString attribute.
* A processor is used to ensure that a Model has been created.
*
* @see SymfonyMapQueryStringDescriber
*/
final class MapQueryStringProcessor
{
public function __invoke(Analysis $analysis): void
{
/** @var OA\Operation[] $operations */
$operations = $analysis->getAnnotationsOfType(OA\Operation::class);
foreach ($operations as $operation) {
if (!isset($operation->_context->{SymfonyMapQueryStringDescriber::CONTEXT_KEY})) {
continue;
}
$mapQueryStringContexts = $operation->_context->{SymfonyMapQueryStringDescriber::CONTEXT_KEY};
if (!is_array($mapQueryStringContexts)) {
throw new \LogicException(sprintf('MapQueryString contexts not found for operation "%s"', $operation->operationId));
}
foreach ($mapQueryStringContexts as $mapQueryStringContext) {
$this->addQueryParameters($analysis, $operation, $mapQueryStringContext);
}
}
}
/**
* @param array<string, mixed> $mapQueryStringContext
*/
private function addQueryParameters(Analysis $analysis, OA\Operation $operation, array $mapQueryStringContext): void
{
$argumentMetaData = $mapQueryStringContext[SymfonyMapQueryStringDescriber::CONTEXT_ARGUMENT_METADATA];
if (!$argumentMetaData instanceof ArgumentMetadata) {
throw new \LogicException(sprintf('MapQueryString ArgumentMetaData not found for operation "%s"', $operation->operationId));
}
$modelRef = $mapQueryStringContext[SymfonyMapQueryStringDescriber::CONTEXT_MODEL_REF];
if (!isset($modelRef)) {
throw new \LogicException(sprintf('MapQueryString Model reference not found for operation "%s"', $operation->operationId));
}
$nativeModelName = str_replace(OA\Components::SCHEMA_REF, '', $modelRef);
$schemaModel = Util::getSchema($analysis->openapi, $nativeModelName);
// There are no properties to map to query parameters
if (Generator::UNDEFINED === $schemaModel->properties) {
return;
}
$isModelOptional = $argumentMetaData->hasDefaultValue() || $argumentMetaData->isNullable();
foreach ($schemaModel->properties as $property) {
$name = 'array' === $property->type
? $property->property.'[]'
: $property->property;
$operationParameter = Util::getOperationParameter($operation, $name, 'query');
// Remove incompatible properties
$propertyVars = get_object_vars($property);
unset($propertyVars['property']);
unset($propertyVars['encoding']);
$schema = new OA\Schema($propertyVars);
Util::modifyAnnotationValue($operationParameter, 'schema', $schema);
Util::modifyAnnotationValue($operationParameter, 'name', $property->property);
Util::modifyAnnotationValue($operationParameter, 'description', $schema->description);
Util::modifyAnnotationValue($operationParameter, 'required', $schema->required);
Util::modifyAnnotationValue($operationParameter, 'deprecated', $schema->deprecated);
Util::modifyAnnotationValue($operationParameter, 'example', $schema->example);
if ($isModelOptional) {
Util::modifyAnnotationValue($operationParameter, 'required', false);
} elseif (is_array($schemaModel->required) && in_array($property->property, $schemaModel->required, true)) {
Util::modifyAnnotationValue($operationParameter, 'required', true);
} else {
Util::modifyAnnotationValue($operationParameter, 'required', false);
}
}
}
}