1414namespace ApiPlatform \Doctrine \Orm \Filter ;
1515
1616use ApiPlatform \Doctrine \Common \Filter \RangeFilterInterface ;
17- use ApiPlatform \Doctrine \Common \Filter \RangeFilterTrait ;
1817use ApiPlatform \Doctrine \Orm \Util \QueryNameGeneratorInterface ;
18+ use ApiPlatform \Metadata \BackwardCompatibleFilterDescriptionTrait ;
19+ use ApiPlatform \Metadata \JsonSchemaFilterInterface ;
1920use ApiPlatform \Metadata \OpenApiParameterFilterInterface ;
2021use ApiPlatform \Metadata \Operation ;
2122use ApiPlatform \Metadata \Parameter ;
2223use ApiPlatform \Metadata \QueryParameter ;
2324use ApiPlatform \OpenApi \Model \Parameter as OpenApiParameter ;
24- use Doctrine \ORM \Query \Expr \Join ;
2525use Doctrine \ORM \QueryBuilder ;
2626
2727/**
3434 * ```php
3535 * <?php
3636 * // api/src/Entity/Book.php
37- * use ApiPlatform\Metadata\ApiFilter;
3837 * use ApiPlatform\Metadata\ApiResource;
38+ * use ApiPlatform\Metadata\GetCollection;
39+ * use ApiPlatform\Metadata\QueryParameter;
3940 * use ApiPlatform\Doctrine\Orm\Filter\RangeFilter;
4041 *
4142 * #[ApiResource]
42- * #[ApiFilter(RangeFilter::class, properties: ['price'])]
43+ * #[GetCollection(
44+ * parameters: [
45+ * 'price' => new QueryParameter(filter: new RangeFilter())
46+ * ]
47+ * )]
4348 * class Book
4449 * {
4550 * // ...
109114 *
110115 * @author Lee Siong Chan <ahlee2326@me.com>
111116 */
112- final class RangeFilter extends AbstractFilter implements RangeFilterInterface, OpenApiParameterFilterInterface
117+ final class RangeFilter implements FilterInterface, RangeFilterInterface, JsonSchemaFilterInterface , OpenApiParameterFilterInterface
113118{
114- use RangeFilterTrait ;
119+ use BackwardCompatibleFilterDescriptionTrait ;
115120
116- /**
117- * {@inheritdoc}
118- */
119- protected function filterProperty (string $ property , mixed $ values , QueryBuilder $ queryBuilder , QueryNameGeneratorInterface $ queryNameGenerator , string $ resourceClass , ?Operation $ operation = null , array $ context = []): void
121+ public function apply (QueryBuilder $ queryBuilder , QueryNameGeneratorInterface $ queryNameGenerator , string $ resourceClass , ?Operation $ operation = null , array $ context = []): void
120122 {
121- if (
122- !\is_array ($ values )
123- || !$ this ->isPropertyEnabled ($ property , $ resourceClass )
124- || !$ this ->isPropertyMapped ($ property , $ resourceClass )
125- ) {
123+ $ parameter = $ context ['parameter ' ] ?? null ;
124+ if (!$ parameter ) {
126125 return ;
127126 }
128127
129- $ values = $ this -> normalizeValues ( $ values , $ property );
130- if (null === $ values ) {
128+ $ values = $ parameter -> getValue ( );
129+ if (! \is_array ( $ values) ) {
131130 return ;
132131 }
133132
133+ $ property = $ parameter ->getProperty ();
134134 $ alias = $ queryBuilder ->getRootAliases ()[0 ];
135- $ field = $ property ;
136-
137- if ($ this ->isPropertyNested ($ property , $ resourceClass )) {
138- [$ alias , $ field ] = $ this ->addJoinsForNestedProperty ($ property , $ alias , $ queryBuilder , $ queryNameGenerator , $ resourceClass , Join::INNER_JOIN );
139- }
140135
141136 foreach ($ values as $ operator => $ value ) {
142- $ this ->addWhere (
143- $ queryBuilder ,
144- $ queryNameGenerator ,
145- $ alias ,
146- $ field ,
147- $ operator ,
148- $ value
149- );
137+ $ this ->addWhere ($ queryBuilder , $ queryNameGenerator , $ alias , $ property , $ operator , $ value );
150138 }
151139 }
152140
153- /**
154- * Adds the where clause according to the operator.
155- */
156- protected function addWhere (QueryBuilder $ queryBuilder , QueryNameGeneratorInterface $ queryNameGenerator , string $ alias , string $ field , string $ operator , string $ value ): void
141+ private function addWhere (QueryBuilder $ queryBuilder , QueryNameGeneratorInterface $ queryNameGenerator , string $ alias , string $ field , string $ operator , string $ value ): void
157142 {
158143 $ valueParameter = $ queryNameGenerator ->generateParameterName ($ field );
159144
160145 switch ($ operator ) {
161146 case self ::PARAMETER_BETWEEN :
162147 $ rangeValue = explode ('.. ' , $ value , 2 );
163148
164- $ rangeValue = $ this ->normalizeBetweenValues ($ rangeValue );
165- if (null === $ rangeValue ) {
149+ if (2 !== \count ($ rangeValue )) {
150+ return ;
151+ }
152+
153+ if (!is_numeric ($ rangeValue [0 ]) || !is_numeric ($ rangeValue [1 ])) {
166154 return ;
167155 }
168156
157+ $ rangeValue = [$ rangeValue [0 ] + 0 , $ rangeValue [1 ] + 0 ];
158+
169159 if ($ rangeValue [0 ] === $ rangeValue [1 ]) {
170160 $ queryBuilder
171161 ->andWhere (\sprintf ('%s.%s = :%s ' , $ alias , $ field , $ valueParameter ))
@@ -181,52 +171,53 @@ protected function addWhere(QueryBuilder $queryBuilder, QueryNameGeneratorInterf
181171
182172 break ;
183173 case self ::PARAMETER_GREATER_THAN :
184- $ value = $ this ->normalizeValue ($ value , $ operator );
185- if (null === $ value ) {
174+ if (!is_numeric ($ value )) {
186175 return ;
187176 }
188177
189178 $ queryBuilder
190179 ->andWhere (\sprintf ('%s.%s > :%s ' , $ alias , $ field , $ valueParameter ))
191- ->setParameter ($ valueParameter , $ value );
180+ ->setParameter ($ valueParameter , $ value + 0 );
192181
193182 break ;
194183 case self ::PARAMETER_GREATER_THAN_OR_EQUAL :
195- $ value = $ this ->normalizeValue ($ value , $ operator );
196- if (null === $ value ) {
184+ if (!is_numeric ($ value )) {
197185 return ;
198186 }
199187
200188 $ queryBuilder
201189 ->andWhere (\sprintf ('%s.%s >= :%s ' , $ alias , $ field , $ valueParameter ))
202- ->setParameter ($ valueParameter , $ value );
190+ ->setParameter ($ valueParameter , $ value + 0 );
203191
204192 break ;
205193 case self ::PARAMETER_LESS_THAN :
206- $ value = $ this ->normalizeValue ($ value , $ operator );
207- if (null === $ value ) {
194+ if (!is_numeric ($ value )) {
208195 return ;
209196 }
210197
211198 $ queryBuilder
212199 ->andWhere (\sprintf ('%s.%s < :%s ' , $ alias , $ field , $ valueParameter ))
213- ->setParameter ($ valueParameter , $ value );
200+ ->setParameter ($ valueParameter , $ value + 0 );
214201
215202 break ;
216203 case self ::PARAMETER_LESS_THAN_OR_EQUAL :
217- $ value = $ this ->normalizeValue ($ value , $ operator );
218- if (null === $ value ) {
204+ if (!is_numeric ($ value )) {
219205 return ;
220206 }
221207
222208 $ queryBuilder
223209 ->andWhere (\sprintf ('%s.%s <= :%s ' , $ alias , $ field , $ valueParameter ))
224- ->setParameter ($ valueParameter , $ value );
210+ ->setParameter ($ valueParameter , $ value + 0 );
225211
226212 break ;
227213 }
228214 }
229215
216+ public function getSchema (Parameter $ parameter ): array
217+ {
218+ return ['type ' => 'number ' ];
219+ }
220+
230221 public function getOpenApiParameters (Parameter $ parameter ): array
231222 {
232223 $ in = $ parameter instanceof QueryParameter ? 'query ' : 'header ' ;
@@ -237,6 +228,7 @@ public function getOpenApiParameters(Parameter $parameter): array
237228 new OpenApiParameter (name: $ key .'[lt] ' , in: $ in ),
238229 new OpenApiParameter (name: $ key .'[gte] ' , in: $ in ),
239230 new OpenApiParameter (name: $ key .'[lte] ' , in: $ in ),
231+ new OpenApiParameter (name: $ key .'[between] ' , in: $ in ),
240232 ];
241233 }
242234}
0 commit comments