Skip to content

Commit 1db2b2d

Browse files
committed
SearchFilter: Refactor code to reduce code duplication and makes it easier to add new strategies to classes inheriting from SearchFilter class
1 parent cfc05d1 commit 1db2b2d

File tree

2 files changed

+36
-47
lines changed

2 files changed

+36
-47
lines changed

src/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilter.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
use ApiPlatform\Core\Bridge\Doctrine\Common\Filter\SearchFilterTrait;
2020
use ApiPlatform\Core\Exception\InvalidArgumentException;
2121
use Doctrine\Common\Persistence\ManagerRegistry;
22-
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
2322
use Doctrine\ODM\MongoDB\Aggregation\Builder;
2423
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata as MongoDBClassMetadata;
2524
use Doctrine\ODM\MongoDB\Types\Type as MongoDbType;
@@ -116,8 +115,9 @@ protected function filterProperty(string $property, $value, Builder $aggregation
116115
}
117116

118117
$inValues = [];
118+
$type = $metadata->getTypeOfField($field);
119119
foreach ($values as $inValue) {
120-
$inValues[] = $this->addEqualityMatchStrategy($strategy, $field, $inValue, $caseSensitive, $metadata);
120+
$inValues[] = $this->addEqualityMatchStrategy($strategy, $inValue, $caseSensitive, $type);
121121
}
122122

123123
$aggregationBuilder
@@ -149,10 +149,15 @@ protected function filterProperty(string $property, $value, Builder $aggregation
149149
return;
150150
}
151151

152+
$inValues = [];
153+
foreach ($values as $inValue) {
154+
$inValues[] = $this->addEqualityMatchStrategy(self::STRATEGY_EXACT, $inValue, $caseSensitive, $doctrineTypeField);
155+
}
156+
152157
$aggregationBuilder
153158
->match()
154159
->field($matchField)
155-
->in($values);
160+
->in($inValues);
156161
}
157162

158163
/**
@@ -162,10 +167,8 @@ protected function filterProperty(string $property, $value, Builder $aggregation
162167
*
163168
* @return Regex|string
164169
*/
165-
private function addEqualityMatchStrategy(string $strategy, string $field, $value, bool $caseSensitive, ClassMetadata $metadata)
170+
private function addEqualityMatchStrategy(string $strategy, $value, bool $caseSensitive, string $type)
166171
{
167-
$type = $metadata->getTypeOfField($field);
168-
169172
switch ($strategy) {
170173
case MongoDbType::STRING !== $type:
171174
return MongoDbType::getType($type)->convertToDatabaseValue($value);

src/Bridge/Doctrine/Orm/Filter/SearchFilter.php

Lines changed: 27 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -112,26 +112,8 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB
112112
$caseSensitive = false;
113113
}
114114

115-
if (1 === \count($values)) {
116-
$this->addWhereByStrategy($strategy, $queryBuilder, $queryNameGenerator, $alias, $field, $doctrineTypeField, $values[0], $caseSensitive);
117-
118-
return;
119-
}
120-
121-
if (self::STRATEGY_EXACT !== $strategy) {
122-
$this->logger->notice('Invalid filter ignored', [
123-
'exception' => new InvalidArgumentException(sprintf('"%s" strategy selected for "%s" property, but only "%s" strategy supports multiple values', $strategy, $property, self::STRATEGY_EXACT)),
124-
]);
125-
126-
return;
127-
}
128-
129-
$wrapCase = $this->createWrapCase($caseSensitive);
130115
$valueParameter = $queryNameGenerator->generateParameterName($field);
131-
132-
$queryBuilder
133-
->andWhere(sprintf($wrapCase('%s.%s').' IN (:%s)', $alias, $field, $valueParameter))
134-
->setParameter($valueParameter, $caseSensitive ? $values : array_map('strtolower', $values));
116+
$this->addWhereByStrategy($strategy, $queryBuilder, $alias, $field, $doctrineTypeField, $values, $caseSensitive, $valueParameter);
135117
}
136118

137119
// metadata doesn't have the field, nor an association on the field
@@ -155,63 +137,67 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB
155137
return;
156138
}
157139

158-
$association = $field;
159-
$valueParameter = $queryNameGenerator->generateParameterName($association);
160-
if ($metadata->isCollectionValuedAssociation($association)) {
161-
$associationAlias = QueryBuilderHelper::addJoinOnce($queryBuilder, $queryNameGenerator, $alias, $association);
140+
$valueParameter = $queryNameGenerator->generateParameterName($field);
141+
if ($metadata->isCollectionValuedAssociation($field)) {
142+
$associationAlias = QueryBuilderHelper::addJoinOnce($queryBuilder, $queryNameGenerator, $alias, $field);
162143
$associationField = $associationFieldIdentifier;
163144
} else {
164145
$associationAlias = $alias;
165146
$associationField = $field;
166147
}
167148

168-
if (1 === \count($values)) {
169-
$queryBuilder
170-
->andWhere(sprintf('%s.%s = :%s', $associationAlias, $associationField, $valueParameter))
171-
->setParameter($valueParameter, $values[0], $doctrineTypeField);
172-
} else {
173-
$queryBuilder
174-
->andWhere(sprintf('%s.%s IN (:%s)', $associationAlias, $associationField, $valueParameter))
175-
->setParameter($valueParameter, $values, $doctrineTypeField);
176-
}
149+
$this->addWhereByStrategy(self::STRATEGY_EXACT, $queryBuilder, $associationAlias, $associationField, $doctrineTypeField, $values, $caseSensitive, $valueParameter);
177150
}
178151

179152
/**
180153
* Adds where clause according to the strategy.
181154
*
182155
* @throws InvalidArgumentException If strategy does not exist
183156
*/
184-
protected function addWhereByStrategy(string $strategy, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $alias, string $field, $fieldType, $value, bool $caseSensitive)
157+
protected function addWhereByStrategy(string $strategy, QueryBuilder $queryBuilder, string $alias, string $field, $fieldType, array $values, bool $caseSensitive, string $valueParameter)
185158
{
186159
$wrapCase = $this->createWrapCase($caseSensitive);
187-
$valueParameter = $queryNameGenerator->generateParameterName($field);
160+
161+
if (self::STRATEGY_EXACT !== $strategy && 1 !== \count($values)) {
162+
$this->logger->notice('Invalid filter ignored', [
163+
'exception' => new InvalidArgumentException(sprintf('"%s" strategy selected for "%s" property, but only "%s" strategy supports multiple values', $strategy, $field, self::STRATEGY_EXACT)),
164+
]);
165+
166+
return;
167+
}
188168

189169
switch ($strategy) {
190170
case null:
191171
case self::STRATEGY_EXACT:
192-
$queryBuilder
193-
->andWhere(sprintf($wrapCase('%s.%s').' = '.$wrapCase(':%s'), $alias, $field, $valueParameter))
194-
->setParameter($valueParameter, $value, $fieldType);
172+
if (1 === \count($values)) {
173+
$queryBuilder
174+
->andWhere(sprintf($wrapCase('%s.%s').' = '.$wrapCase(':%s'), $alias, $field, $valueParameter))
175+
->setParameter($valueParameter, $values[0], $fieldType);
176+
} else {
177+
$queryBuilder
178+
->andWhere(sprintf($wrapCase('%s.%s').' IN (:%s)', $alias, $field, $valueParameter))
179+
->setParameter($valueParameter, $caseSensitive ? $values : array_map('strtolower', $values));
180+
}
195181
break;
196182
case self::STRATEGY_PARTIAL:
197183
$queryBuilder
198184
->andWhere(sprintf($wrapCase('%s.%s').' LIKE '.$wrapCase('CONCAT(\'%%\', :%s, \'%%\')'), $alias, $field, $valueParameter))
199-
->setParameter($valueParameter, $value, $fieldType);
185+
->setParameter($valueParameter, $values[0], $fieldType);
200186
break;
201187
case self::STRATEGY_START:
202188
$queryBuilder
203189
->andWhere(sprintf($wrapCase('%s.%s').' LIKE '.$wrapCase('CONCAT(:%s, \'%%\')'), $alias, $field, $valueParameter))
204-
->setParameter($valueParameter, $value, $fieldType);
190+
->setParameter($valueParameter, $values[0], $fieldType);
205191
break;
206192
case self::STRATEGY_END:
207193
$queryBuilder
208194
->andWhere(sprintf($wrapCase('%s.%s').' LIKE '.$wrapCase('CONCAT(\'%%\', :%s)'), $alias, $field, $valueParameter))
209-
->setParameter($valueParameter, $value, $fieldType);
195+
->setParameter($valueParameter, $values[0], $fieldType);
210196
break;
211197
case self::STRATEGY_WORD_START:
212198
$queryBuilder
213199
->andWhere(sprintf($wrapCase('%1$s.%2$s').' LIKE '.$wrapCase('CONCAT(:%3$s, \'%%\')').' OR '.$wrapCase('%1$s.%2$s').' LIKE '.$wrapCase('CONCAT(\'%% \', :%3$s, \'%%\')'), $alias, $field, $valueParameter))
214-
->setParameter($valueParameter, $value, $fieldType);
200+
->setParameter($valueParameter, $values[0], $fieldType);
215201
break;
216202
default:
217203
throw new InvalidArgumentException(sprintf('strategy %s does not exist.', $strategy));

0 commit comments

Comments
 (0)