18
18
use ApiPlatform \Doctrine \Odm \State \Options as ODMOptions ;
19
19
use ApiPlatform \Doctrine \Orm \State \Options ;
20
20
use ApiPlatform \Metadata \FilterInterface ;
21
+ use ApiPlatform \Metadata \Parameter ;
22
+ use ApiPlatform \Metadata \Parameters ;
23
+ use ApiPlatform \Metadata \QueryParameterInterface ;
21
24
use ApiPlatform \Metadata \Resource \Factory \ResourceMetadataCollectionFactoryInterface ;
22
25
use ApiPlatform \Metadata \ResourceClassResolverInterface ;
23
26
use ApiPlatform \Serializer \CacheableSupportsMethodInterface ;
@@ -97,8 +100,10 @@ public function normalize(mixed $object, ?string $format = null, array $context
97
100
}
98
101
$ resourceClass = $ this ->resourceClassResolver ->getResourceClass ($ object , $ context ['resource_class ' ]);
99
102
$ operation = $ context ['operation ' ] ?? $ this ->resourceMetadataCollectionFactory ->create ($ resourceClass )->getOperation ($ context ['operation_name ' ] ?? null );
103
+
104
+ $ parameters = $ operation ->getParameters ();
100
105
$ resourceFilters = $ operation ->getFilters ();
101
- if (!$ resourceFilters ) {
106
+ if (!$ resourceFilters && ! $ parameters ) {
102
107
return $ data ;
103
108
}
104
109
@@ -123,8 +128,8 @@ public function normalize(mixed $object, ?string $format = null, array $context
123
128
}
124
129
}
125
130
126
- if ($ currentFilters ) {
127
- $ data ['hydra:search ' ] = $ this ->getSearch ($ resourceClass , $ requestParts , $ currentFilters );
131
+ if ($ currentFilters || ( $ parameters && \count ( $ parameters )) ) {
132
+ $ data ['hydra:search ' ] = $ this ->getSearch ($ resourceClass , $ requestParts , $ currentFilters, $ parameters );
128
133
}
129
134
130
135
return $ data ;
@@ -144,8 +149,9 @@ public function setNormalizer(NormalizerInterface $normalizer): void
144
149
* Returns the content of the Hydra search property.
145
150
*
146
151
* @param LegacyFilterInterface[]|FilterInterface[] $filters
152
+ * @param array<string, Parameter> $parameters
147
153
*/
148
- private function getSearch (string $ resourceClass , array $ parts , array $ filters ): array
154
+ private function getSearch (string $ resourceClass , array $ parts , array $ filters, array | Parameters | null $ parameters ): array
149
155
{
150
156
$ variables = [];
151
157
$ mapping = [];
@@ -156,6 +162,45 @@ private function getSearch(string $resourceClass, array $parts, array $filters):
156
162
}
157
163
}
158
164
165
+ foreach ($ parameters ?? [] as $ key => $ parameter ) {
166
+ // Each IriTemplateMapping maps a variable used in the template to a property
167
+ if (!$ parameter instanceof QueryParameterInterface) {
168
+ continue ;
169
+ }
170
+
171
+ if (!($ property = $ parameter ->getProperty ()) && ($ filterId = $ parameter ->getFilter ()) && ($ filter = $ this ->getFilter ($ filterId ))) {
172
+ foreach ($ filter ->getDescription ($ resourceClass ) as $ variable => $ description ) {
173
+ // This is a practice induced by PHP and is not necessary when implementing URI template
174
+ if (str_ends_with ((string ) $ variable , '[] ' )) {
175
+ continue ;
176
+ }
177
+
178
+ // :property is a pattern allowed when defining parameters
179
+ $ k = str_replace (':property ' , $ description ['property ' ], $ key );
180
+ $ variable = str_replace ($ description ['property ' ], $ k , $ variable );
181
+ $ variables [] = $ variable ;
182
+ $ m = ['@type ' => 'IriTemplateMapping ' , 'variable ' => $ variable , 'property ' => $ description ['property ' ], 'required ' => $ description ['required ' ]];
183
+ if (null !== ($ required = $ parameter ->getRequired ())) {
184
+ $ m ['required ' ] = $ required ;
185
+ }
186
+ $ mapping [] = $ m ;
187
+ }
188
+
189
+ continue ;
190
+ }
191
+
192
+ if (!$ property ) {
193
+ continue ;
194
+ }
195
+
196
+ $ m = ['@type ' => 'IriTemplateMapping ' , 'variable ' => $ key , 'property ' => $ property ];
197
+ $ variables [] = $ key ;
198
+ if (null !== ($ required = $ parameter ->getRequired ())) {
199
+ $ m ['required ' ] = $ required ;
200
+ }
201
+ $ mapping [] = $ m ;
202
+ }
203
+
159
204
return ['@type ' => 'hydra:IriTemplate ' , 'hydra:template ' => sprintf ('%s{?%s} ' , $ parts ['path ' ], implode (', ' , $ variables )), 'hydra:variableRepresentation ' => 'BasicRepresentation ' , 'hydra:mapping ' => $ mapping ];
160
205
}
161
206
0 commit comments