4040use ApiPlatform \JsonSchema \SchemaFactoryInterface ;
4141use ApiPlatform \Laravel \ApiResource \Error ;
4242use ApiPlatform \Laravel \Controller \ApiPlatformController ;
43+ use ApiPlatform \Laravel \Eloquent \Extension \FilterQueryExtension ;
44+ use ApiPlatform \Laravel \Eloquent \Extension \QueryExtensionInterface ;
45+ use ApiPlatform \Laravel \Eloquent \Filter \FilterInterface as EloquentFilterInterface ;
46+ use ApiPlatform \Laravel \Eloquent \Filter \SearchFilter ;
4347use ApiPlatform \Laravel \Eloquent \Metadata \Factory \Property \EloquentAttributePropertyMetadataFactory ;
4448use ApiPlatform \Laravel \Eloquent \Metadata \Factory \Property \EloquentAttributePropertyNameCollectionFactory ;
4549use ApiPlatform \Laravel \Eloquent \Metadata \Factory \Property \EloquentPropertyMetadataFactory ;
6670use ApiPlatform \Laravel \State \SwaggerUiProcessor ;
6771use ApiPlatform \Laravel \State \ValidateProvider ;
6872use ApiPlatform \Metadata \Exception \NotExposedHttpException ;
73+ use ApiPlatform \Metadata \FilterInterface ;
6974use ApiPlatform \Metadata \IdentifiersExtractor ;
7075use ApiPlatform \Metadata \IdentifiersExtractorInterface ;
7176use ApiPlatform \Metadata \IriConverterInterface ;
9095use ApiPlatform \Metadata \Resource \Factory \LinkResourceMetadataCollectionFactory ;
9196use ApiPlatform \Metadata \Resource \Factory \NotExposedOperationResourceMetadataCollectionFactory ;
9297use ApiPlatform \Metadata \Resource \Factory \OperationNameResourceMetadataCollectionFactory ;
98+ use ApiPlatform \Metadata \Resource \Factory \ParameterResourceMetadataCollectionFactory ;
9399use ApiPlatform \Metadata \Resource \Factory \PhpDocResourceMetadataCollectionFactory ;
94100use ApiPlatform \Metadata \Resource \Factory \ResourceMetadataCollectionFactoryInterface ;
95101use ApiPlatform \Metadata \Resource \Factory \ResourceNameCollectionFactoryInterface ;
102108use ApiPlatform \OpenApi \Factory \OpenApiFactoryInterface ;
103109use ApiPlatform \OpenApi \Options ;
104110use ApiPlatform \OpenApi \Serializer \OpenApiNormalizer ;
111+ use ApiPlatform \Serializer \Filter \FilterInterface as SerializerFilterInterface ;
112+ use ApiPlatform \Serializer \Filter \PropertyFilter ;
105113use ApiPlatform \Serializer \ItemNormalizer ;
106114use ApiPlatform \Serializer \JsonEncoder ;
107115use ApiPlatform \Serializer \Mapping \Factory \ClassMetadataFactory as SerializerClassMetadataFactory ;
116+ use ApiPlatform \Serializer \Parameter \SerializerFilterParameterProvider ;
108117use ApiPlatform \Serializer \SerializerContextBuilder ;
109118use ApiPlatform \State \CallableProcessor ;
110119use ApiPlatform \State \CallableProvider ;
111120use ApiPlatform \State \Pagination \Pagination ;
112121use ApiPlatform \State \Pagination \PaginationOptions ;
122+ use ApiPlatform \State \ParameterProviderInterface ;
113123use ApiPlatform \State \Processor \AddLinkHeaderProcessor ;
114124use ApiPlatform \State \Processor \RespondProcessor ;
115125use ApiPlatform \State \Processor \SerializeProcessor ;
116126use ApiPlatform \State \Processor \WriteProcessor ;
117127use ApiPlatform \State \ProcessorInterface ;
118128use ApiPlatform \State \Provider \ContentNegotiationProvider ;
119129use ApiPlatform \State \Provider \DeserializeProvider ;
130+ use ApiPlatform \State \Provider \ParameterProvider ;
120131use ApiPlatform \State \Provider \ReadProvider ;
121132use ApiPlatform \State \ProviderInterface ;
122133use ApiPlatform \State \SerializerContextBuilderInterface ;
@@ -247,38 +258,42 @@ public function register(): void
247258 // TODO: add cached metadata factories
248259 $ this ->app ->singleton (ResourceMetadataCollectionFactoryInterface::class, function (Application $ app ) use ($ config ) {
249260 return new EloquentResourceCollectionMetadataFactory (
250- new AlternateUriResourceMetadataCollectionFactory (
251- new FiltersResourceMetadataCollectionFactory (
252- new FormatsResourceMetadataCollectionFactory (
253- new InputOutputResourceMetadataCollectionFactory (
254- new PhpDocResourceMetadataCollectionFactory (
255- new OperationNameResourceMetadataCollectionFactory (
256- new LinkResourceMetadataCollectionFactory (
257- $ app -> make (LinkFactoryInterface::class),
258- new UriTemplateResourceMetadataCollectionFactory (
261+ new ParameterResourceMetadataCollectionFactory (
262+ $ this -> app -> make (PropertyNameCollectionFactoryInterface::class),
263+ new AlternateUriResourceMetadataCollectionFactory (
264+ new FiltersResourceMetadataCollectionFactory (
265+ new FormatsResourceMetadataCollectionFactory (
266+ new InputOutputResourceMetadataCollectionFactory (
267+ new PhpDocResourceMetadataCollectionFactory (
268+ new OperationNameResourceMetadataCollectionFactory (
269+ new LinkResourceMetadataCollectionFactory (
259270 $ app ->make (LinkFactoryInterface::class),
260- $ app ->make (PathSegmentNameGeneratorInterface::class),
261- new NotExposedOperationResourceMetadataCollectionFactory (
271+ new UriTemplateResourceMetadataCollectionFactory (
262272 $ app ->make (LinkFactoryInterface::class),
263- new AttributesResourceMetadataCollectionFactory (
264- null ,
265- $ app ->make (LoggerInterface::class),
266- [
267- 'routePrefix ' => $ config ->get ('api-platform.routes.prefix ' ) ?? '/ ' ,
268- ],
269- false
273+ $ app ->make (PathSegmentNameGeneratorInterface::class),
274+ new NotExposedOperationResourceMetadataCollectionFactory (
275+ $ app ->make (LinkFactoryInterface::class),
276+ new AttributesResourceMetadataCollectionFactory (
277+ null ,
278+ $ app ->make (LoggerInterface::class),
279+ [
280+ 'routePrefix ' => $ config ->get ('api-platform.routes.prefix ' ) ?? '/ ' ,
281+ ],
282+ false
283+ )
270284 )
271285 )
272286 )
273287 )
274288 )
275- )
276- ),
277- $ config ->get ('api-platform.formats ' ),
278- $ config -> get ( ' api-platform.patch_formats ' ),
289+ ),
290+ $ config -> get ( ' api-platform.formats ' ),
291+ $ config ->get ('api-platform.patch_formats ' ),
292+ )
279293 )
280- )
281- ),
294+ ),
295+ $ app ->make (FilterInterface::class)
296+ )
282297 );
283298 });
284299
@@ -292,6 +307,22 @@ public function register(): void
292307
293308 $ this ->app ->bind (OperationMetadataFactoryInterface::class, OperationMetadataFactory::class);
294309
310+ $ this ->app ->tag ([SearchFilter::class], EloquentFilterInterface::class);
311+ $ this ->app ->tag ([SearchFilter::class, PropertyFilter::class], FilterInterface::class);
312+ $ this ->app ->singleton (FilterInterface::class, function (Application $ app ) {
313+ $ tagged = iterator_to_array ($ app ->tagged (FilterInterface::class));
314+
315+ return new ServiceLocator ($ tagged );
316+ });
317+
318+ $ this ->app ->bind (FilterQueryExtension::class, function (Application $ app ) {
319+ $ tagged = iterator_to_array ($ app ->tagged (EloquentFilterInterface::class));
320+
321+ return new FilterQueryExtension (new ServiceLocator ($ tagged ));
322+ });
323+
324+ $ this ->app ->tag ([FilterQueryExtension::class], QueryExtensionInterface::class);
325+
295326 $ this ->app ->singleton (ItemProvider::class, function (Application $ app ) {
296327 $ tagged = iterator_to_array ($ app ->tagged (LinksHandlerInterface::class));
297328
@@ -300,7 +331,7 @@ public function register(): void
300331 $ this ->app ->singleton (CollectionProvider::class, function (Application $ app ) {
301332 $ tagged = iterator_to_array ($ app ->tagged (LinksHandlerInterface::class));
302333
303- return new CollectionProvider ($ app ->make (Pagination::class), new LinksHandler ($ app ), new ServiceLocator ($ tagged ));
334+ return new CollectionProvider ($ app ->make (Pagination::class), new LinksHandler ($ app ), $ app -> tagged (QueryExtensionInterface::class), new ServiceLocator ($ tagged ));
304335 });
305336 $ this ->app ->tag ([ItemProvider::class, CollectionProvider::class], ProviderInterface::class);
306337
@@ -326,8 +357,24 @@ public function register(): void
326357 return new DeserializeProvider ($ app ->make (JsonApiProvider::class), $ app ->make (SerializerInterface::class), $ app ->make (SerializerContextBuilderInterface::class));
327358 });
328359
360+ $ this ->app ->tag ([PropertyFilter::class], SerializerFilterInterface::class);
361+
362+ $ this ->app ->singleton (SerializerFilterParameterProvider::class, function (Application $ app ) {
363+ $ tagged = iterator_to_array ($ app ->tagged (SerializerFilterInterface::class));
364+
365+ return new SerializerFilterParameterProvider (new ServiceLocator ($ tagged ));
366+ });
367+
368+ $ this ->app ->tag ([SerializerFilterParameterProvider::class], ParameterProviderInterface::class);
369+
370+ $ this ->app ->singleton (ParameterProvider::class, function (Application $ app ) {
371+ $ tagged = iterator_to_array ($ app ->tagged (ParameterProviderInterface::class));
372+
373+ return new ParameterProvider ($ app ->make (DeserializeProvider::class), new ServiceLocator ($ tagged ));
374+ });
375+
329376 $ this ->app ->singleton (AccessCheckerProvider::class, function (Application $ app ) {
330- return new AccessCheckerProvider ($ app ->make (DeserializeProvider ::class), $ app ->make (ResourceAccessCheckerInterface::class));
377+ return new AccessCheckerProvider ($ app ->make (ParameterProvider ::class), $ app ->make (ResourceAccessCheckerInterface::class));
331378 });
332379
333380 $ this ->app ->singleton (ContentNegotiationProvider::class, function (Application $ app ) use ($ config ) {
@@ -339,6 +386,7 @@ public function register(): void
339386 $ this ->app ->tag ([RemoveProcessor::class, PersistProcessor::class], ProcessorInterface::class);
340387 $ this ->app ->singleton (CallableProcessor::class, function (Application $ app ) {
341388 $ tagged = iterator_to_array ($ app ->tagged (ProcessorInterface::class));
389+ // TODO: tag SwaggerUiProcessor instead?
342390 $ tagged ['api_platform.swagger_ui.processor ' ] = $ app ->make (SwaggerUiProcessor::class);
343391
344392 return new CallableProcessor (new ServiceLocator ($ tagged ));
@@ -503,8 +551,6 @@ public function register(): void
503551 return new DocumentationAction ($ app ->make (ResourceNameCollectionFactoryInterface::class), $ config ->get ('api-platform.title ' ) ?? '' , $ config ->get ('api-platform.description ' ) ?? '' , $ config ->get ('api-platform.version ' ) ?? '' , $ app ->make (OpenApiFactoryInterface::class), $ app ->make (ProviderInterface::class), $ app ->make (ProcessorInterface::class), $ app ->make (Negotiator::class), $ config ->get ('api-platform.docs_formats ' ));
504552 });
505553
506- $ this ->app ->singleton (FilterLocator::class, FilterLocator::class);
507-
508554 $ this ->app ->singleton (EntrypointAction::class, function (Application $ app ) {
509555 return new EntrypointAction ($ app ->make (ResourceNameCollectionFactoryInterface::class), $ app ->make (ProviderInterface::class), $ app ->make (ProcessorInterface::class), ['jsonld ' => ['application/ld+json ' ]]);
510556 });
@@ -539,7 +585,7 @@ public function register(): void
539585 $ app ->make (PropertyNameCollectionFactoryInterface::class),
540586 $ app ->make (PropertyMetadataFactoryInterface::class),
541587 $ app ->make (SchemaFactoryInterface::class),
542- $ app ->make (FilterLocator ::class),
588+ $ app ->make (FilterInterface ::class),
543589 $ config ->get ('api-platform.formats ' ),
544590 null , // ?Options $openApiOptions = null,
545591 $ app ->make (PaginationOptions::class), // ?PaginationOptions $paginationOptions = null,
0 commit comments