18
18
use ApiPlatform \Metadata \Parameter ;
19
19
use ApiPlatform \Metadata \Parameters ;
20
20
use ApiPlatform \Metadata \Resource \ResourceMetadataCollection ;
21
- use ApiPlatform \OpenApi ;
21
+ use ApiPlatform \OpenApi \ Model \ Parameter as OpenApiParameter ;
22
22
use ApiPlatform \Serializer \Filter \FilterInterface as SerializerFilterInterface ;
23
23
use Psr \Container \ContainerInterface ;
24
+ use Symfony \Component \Validator \Constraints \Choice ;
25
+ use Symfony \Component \Validator \Constraints \Count ;
26
+ use Symfony \Component \Validator \Constraints \DivisibleBy ;
27
+ use Symfony \Component \Validator \Constraints \GreaterThan ;
28
+ use Symfony \Component \Validator \Constraints \GreaterThanOrEqual ;
29
+ use Symfony \Component \Validator \Constraints \Length ;
30
+ use Symfony \Component \Validator \Constraints \LessThan ;
31
+ use Symfony \Component \Validator \Constraints \LessThanOrEqual ;
32
+ use Symfony \Component \Validator \Constraints \NotBlank ;
33
+ use Symfony \Component \Validator \Constraints \NotNull ;
34
+ use Symfony \Component \Validator \Constraints \Regex ;
35
+ use Symfony \Component \Validator \Constraints \Unique ;
36
+ use Symfony \Component \Validator \Validator \ValidatorInterface ;
24
37
25
38
/**
26
39
* Prepares Parameters documentation by reading its filter details and declaring an OpenApi parameter.
@@ -96,20 +109,28 @@ private function setDefaults(string $key, Parameter $parameter, string $resource
96
109
$ parameter = $ parameter ->withSchema ($ schema );
97
110
}
98
111
112
+ if (null === $ parameter ->getProperty () && ($ property = $ description [$ key ]['property ' ] ?? null )) {
113
+ $ parameter = $ parameter ->withProperty ($ property );
114
+ }
115
+
116
+ if (null === $ parameter ->getRequired () && ($ required = $ description [$ key ]['required ' ] ?? null )) {
117
+ $ parameter = $ parameter ->withRequired ($ required );
118
+ }
119
+
99
120
if (null === $ parameter ->getOpenApi () && $ openApi = $ description [$ key ]['openapi ' ] ?? null ) {
100
- if ($ openApi instanceof OpenApi \ Model \Parameter ) {
121
+ if ($ openApi instanceof OpenApiParameter ) {
101
122
$ parameter = $ parameter ->withOpenApi ($ openApi );
102
- }
103
-
104
- if ( \is_array ( $ openApi )) {
105
- $ parameter = $ parameter ->withOpenApi (new OpenApi \ Model \ Parameter (
123
+ } elseif ( \is_array ( $ openApi )) {
124
+ // @phpstan-ignore-next-line
125
+ $ schema = $ schema ?? $ openapi [ ' schema ' ] ?? [];
126
+ $ parameter = $ parameter ->withOpenApi (new OpenApiParameter (
106
127
$ key ,
107
128
$ parameter instanceof HeaderParameterInterface ? 'header ' : 'query ' ,
108
129
$ description [$ key ]['description ' ] ?? '' ,
109
130
$ description [$ key ]['required ' ] ?? $ openApi ['required ' ] ?? false ,
110
131
$ openApi ['deprecated ' ] ?? false ,
111
132
$ openApi ['allowEmptyValue ' ] ?? true ,
112
- $ schema ?? $ openApi [ ' schema ' ] ?? [] ,
133
+ $ schema ,
113
134
$ openApi ['style ' ] ?? null ,
114
135
$ openApi ['explode ' ] ?? ('array ' === ($ schema ['type ' ] ?? null )),
115
136
$ openApi ['allowReserved ' ] ?? false ,
@@ -121,6 +142,76 @@ private function setDefaults(string $key, Parameter $parameter, string $resource
121
142
}
122
143
}
123
144
145
+ $ schema = $ parameter ->getSchema () ?? $ parameter ->getOpenApi ()?->getSchema();
146
+
147
+ // Only add validation if the Symfony Validator is installed
148
+ if (interface_exists (ValidatorInterface::class) && !$ parameter ->getConstraints ()) {
149
+ $ parameter = $ this ->addSchemaValidation ($ parameter , $ schema , $ parameter ->getRequired () ?? $ description ['required ' ] ?? false , $ parameter ->getOpenApi ());
150
+ }
151
+
124
152
return $ parameter ;
125
153
}
154
+
155
+ private function addSchemaValidation (Parameter $ parameter , ?array $ schema = null , bool $ required = false , ?OpenApiParameter $ openApi = null ): Parameter
156
+ {
157
+ $ assertions = [];
158
+
159
+ if ($ required ) {
160
+ $ assertions [] = new NotNull (message: sprintf ('The parameter "%s" is required. ' , $ parameter ->getKey ()));
161
+ }
162
+
163
+ if (isset ($ schema ['exclusiveMinimum ' ])) {
164
+ $ assertions [] = new GreaterThan (value: $ schema ['exclusiveMinimum ' ]);
165
+ }
166
+
167
+ if (isset ($ schema ['exclusiveMaximum ' ])) {
168
+ $ assertions [] = new LessThan (value: $ schema ['exclusiveMaximum ' ]);
169
+ }
170
+
171
+ if (isset ($ schema ['minimum ' ])) {
172
+ $ assertions [] = new GreaterThanOrEqual (value: $ schema ['minimum ' ]);
173
+ }
174
+
175
+ if (isset ($ schema ['maximum ' ])) {
176
+ $ assertions [] = new LessThanOrEqual (value: $ schema ['maximum ' ]);
177
+ }
178
+
179
+ if (isset ($ schema ['pattern ' ])) {
180
+ $ assertions [] = new Regex ($ schema ['pattern ' ]);
181
+ }
182
+
183
+ if (isset ($ schema ['maxLength ' ]) || isset ($ schema ['minLength ' ])) {
184
+ $ assertions [] = new Length (min: $ schema ['minLength ' ] ?? null , max: $ schema ['maxLength ' ] ?? null );
185
+ }
186
+
187
+ if (isset ($ schema ['minItems ' ]) || isset ($ schema ['maxItems ' ])) {
188
+ $ assertions [] = new Count (min: $ schema ['minItems ' ] ?? null , max: $ schema ['maxItems ' ] ?? null );
189
+ }
190
+
191
+ if (isset ($ schema ['multipleOf ' ])) {
192
+ $ assertions [] = new DivisibleBy (value: $ schema ['multipleOf ' ]);
193
+ }
194
+
195
+ if ($ schema ['uniqueItems ' ] ?? false ) {
196
+ $ assertions [] = new Unique ();
197
+ }
198
+
199
+ if (isset ($ schema ['enum ' ])) {
200
+ $ assertions [] = new Choice (choices: $ schema ['enum ' ]);
201
+ }
202
+
203
+ if (false === $ openApi ?->getAllowEmptyValue()) {
204
+ $ assertions [] = new NotBlank (allowNull: !$ required );
205
+ }
206
+
207
+ if (!$ assertions ) {
208
+ return $ parameter ;
209
+ }
210
+
211
+ if (1 === \count ($ assertions )) {
212
+ return $ parameter ->withConstraints ($ assertions [0 ]);
213
+ }
214
+
215
+ return $ parameter ->withConstraints ($ assertions );
216
+ }
126
217
}
0 commit comments