@@ -261,12 +261,26 @@ private function collectPaths(ApiResource $resource, ResourceMetadataCollection
261261 }
262262 }
263263
264+ $ entityClass = $ this ->getFilterClass ($ operation );
264265 $ openapiParameters = $ openapiOperation ->getParameters ();
265266 foreach ($ operation ->getParameters () ?? [] as $ key => $ p ) {
266267 if (false === $ p ->getOpenApi ()) {
267268 continue ;
268269 }
269270
271+ if (($ f = $ p ->getFilter ()) && \is_string ($ f ) && $ this ->filterLocator && $ this ->filterLocator ->has ($ f )) {
272+ $ filter = $ this ->filterLocator ->get ($ f );
273+ foreach ($ filter ->getDescription ($ entityClass ) as $ name => $ description ) {
274+ if ($ prop = $ p ->getProperty ()) {
275+ $ name = str_replace ($ prop , $ key , $ name );
276+ }
277+
278+ $ openapiParameters [] = $ this ->getFilterParameter ($ name , $ description , $ operation ->getShortName (), $ f );
279+ }
280+
281+ continue ;
282+ }
283+
270284 $ in = $ p instanceof HeaderParameterInterface ? 'header ' : 'query ' ;
271285 $ defaultParameter = new Parameter ($ key , $ in , $ p ->getDescription () ?? "$ resourceShortName $ key " , $ p ->getRequired () ?? false , false , false , $ p ->getSchema () ?? ['type ' => 'string ' ]);
272286
@@ -557,57 +571,98 @@ private function getLinks(ResourceMetadataCollection $resourceMetadataCollection
557571 private function getFiltersParameters (CollectionOperationInterface |HttpOperation $ operation ): array
558572 {
559573 $ parameters = [];
560-
561574 $ resourceFilters = $ operation ->getFilters ();
575+ $ entityClass = $ this ->getFilterClass ($ operation );
576+
562577 foreach ($ resourceFilters ?? [] as $ filterId ) {
563578 if (!$ this ->filterLocator ->has ($ filterId )) {
564579 continue ;
565580 }
566581
567582 $ filter = $ this ->filterLocator ->get ($ filterId );
568- $ entityClass = $ operation ->getClass ();
569- if ($ options = $ operation ->getStateOptions ()) {
570- if ($ options instanceof DoctrineOptions && $ options ->getEntityClass ()) {
571- $ entityClass = $ options ->getEntityClass ();
572- }
583+ foreach ($ filter ->getDescription ($ entityClass ) as $ name => $ description ) {
584+ $ parameters [] = $ this ->getFilterParameter ($ name , $ description , $ operation ->getShortName (), $ filterId );
585+ }
586+ }
573587
574- if ($ options instanceof DoctrineODMOptions && $ options ->getDocumentClass ()) {
575- $ entityClass = $ options ->getDocumentClass ();
576- }
588+ return $ parameters ;
589+ }
590+
591+ private function getFilterClass (HttpOperation $ operation ): ?string
592+ {
593+ $ entityClass = $ operation ->getClass ();
594+ if ($ options = $ operation ->getStateOptions ()) {
595+ if ($ options instanceof DoctrineOptions && $ options ->getEntityClass ()) {
596+ return $ options ->getEntityClass ();
577597 }
578598
579- foreach ($ filter ->getDescription ($ entityClass ) as $ name => $ data ) {
580- $ schema = $ data ['schema ' ] ?? [];
599+ if ($ options instanceof DoctrineODMOptions && $ options ->getDocumentClass ()) {
600+ return $ options ->getDocumentClass ();
601+ }
602+ }
581603
582- if (isset ($ data ['type ' ]) && \in_array ($ data ['type ' ] ?? null , Type::$ builtinTypes , true ) && !isset ($ schema ['type ' ])) {
583- $ schema += $ this ->getType (new Type ($ data ['type ' ], false , null , $ data ['is_collection ' ] ?? false ));
584- }
604+ return $ entityClass ;
605+ }
585606
586- if (!isset ($ schema ['type ' ])) {
587- $ schema ['type ' ] = 'string ' ;
588- }
607+ private function getFilterParameter (string $ name , array $ description , string $ shortName , string $ filter ): Parameter
608+ {
609+ if (isset ($ description ['swagger ' ])) {
610+ trigger_deprecation ('api-platform/core ' , '4.0 ' , \sprintf ('Using the "swagger" field of the %s::getDescription() (%s) is deprecated. ' , $ filter , $ shortName ));
611+ }
589612
590- $ style = 'array ' === ($ schema ['type ' ] ?? null ) && \in_array (
591- $ data ['type ' ],
592- [Type::BUILTIN_TYPE_ARRAY , Type::BUILTIN_TYPE_OBJECT ],
593- true
594- ) ? 'deepObject ' : 'form ' ;
613+ if (!isset ($ description ['openapi ' ]) || $ description ['openapi ' ] instanceof Parameter) {
614+ $ schema = $ description ['schema ' ] ?? [];
595615
596- $ parameter = isset ($ data ['openapi ' ]) && $ data ['openapi ' ] instanceof Parameter ? $ data ['openapi ' ] : new Parameter (in: 'query ' , name: $ name , style: $ style , explode: $ data ['is_collection ' ] ?? false );
616+ if (isset ($ description ['type ' ]) && \in_array ($ description ['type ' ], Type::$ builtinTypes , true ) && !isset ($ schema ['type ' ])) {
617+ $ schema += $ this ->getType (new Type ($ description ['type ' ], false , null , $ description ['is_collection ' ] ?? false ));
618+ }
597619
598- if ('' === $ parameter -> getDescription () && ( $ description = $ data [ ' description ' ] ?? '' )) {
599- $ parameter = $ parameter -> withDescription ( $ description ) ;
600- }
620+ if (! isset ( $ schema [ ' type ' ] )) {
621+ $ schema [ ' type ' ] = ' string ' ;
622+ }
601623
602- if (false === $ parameter ->getRequired () && false !== ($ required = $ data ['required ' ] ?? false )) {
603- $ parameter = $ parameter ->withRequired ($ required );
604- }
624+ $ style = 'array ' === ($ schema ['type ' ] ?? null ) && \in_array (
625+ $ description ['type ' ],
626+ [Type::BUILTIN_TYPE_ARRAY , Type::BUILTIN_TYPE_OBJECT ],
627+ true
628+ ) ? 'deepObject ' : 'form ' ;
629+
630+ $ parameter = isset ($ description ['openapi ' ]) && $ description ['openapi ' ] instanceof Parameter ? $ description ['openapi ' ] : new Parameter (in: 'query ' , name: $ name , style: $ style , explode: $ description ['is_collection ' ] ?? false );
631+
632+ if ('' === $ parameter ->getDescription () && ($ str = $ description ['description ' ] ?? '' )) {
633+ $ parameter = $ parameter ->withDescription ($ str );
634+ }
605635
606- $ parameters [] = $ parameter ->withSchema ($ schema );
636+ if (false === $ parameter ->getRequired () && false !== ($ required = $ description ['required ' ] ?? false )) {
637+ $ parameter = $ parameter ->withRequired ($ required );
607638 }
639+
640+ return $ parameter ->withSchema ($ schema );
608641 }
609642
610- return $ parameters ;
643+ trigger_deprecation ('api-platform/core ' , '4.0 ' , \sprintf ('Not using "%s" on the "openapi" field of the %s::getDescription() (%s) is deprecated. ' , Parameter::class, $ filter , $ shortName ));
644+ $ schema = $ description ['schema ' ] ?? (\in_array ($ description ['type ' ], Type::$ builtinTypes , true ) ? $ this ->getType (new Type ($ description ['type ' ], false , null , $ description ['is_collection ' ] ?? false )) : ['type ' => 'string ' ]);
645+
646+ return new Parameter (
647+ $ name ,
648+ 'query ' ,
649+ $ description ['description ' ] ?? '' ,
650+ $ description ['required ' ] ?? false ,
651+ $ description ['openapi ' ]['deprecated ' ] ?? false ,
652+ $ description ['openapi ' ]['allowEmptyValue ' ] ?? true ,
653+ $ schema ,
654+ 'array ' === $ schema ['type ' ] && \in_array (
655+ $ description ['type ' ],
656+ [Type::BUILTIN_TYPE_ARRAY , Type::BUILTIN_TYPE_OBJECT ],
657+ true
658+ ) ? 'deepObject ' : 'form ' ,
659+ $ description ['openapi ' ]['explode ' ] ?? ('array ' === $ schema ['type ' ]),
660+ $ description ['openapi ' ]['allowReserved ' ] ?? false ,
661+ $ description ['openapi ' ]['example ' ] ?? null ,
662+ isset (
663+ $ description ['openapi ' ]['examples ' ]
664+ ) ? new \ArrayObject ($ description ['openapi ' ]['examples ' ]) : null
665+ );
611666 }
612667
613668 private function getPaginationParameters (CollectionOperationInterface |HttpOperation $ operation ): array
0 commit comments