Skip to content

Commit 70e2893

Browse files
jpierrontalanpoulain
authored andcommitted
SearchFilter: Refactor code to reduce code duplication and makes it easier to add new strategies to classes inheriting from SearchFilter class
1 parent cecd948 commit 70e2893

File tree

3 files changed

+43
-59
lines changed

3 files changed

+43
-59
lines changed

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

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,17 @@ protected function filterProperty(string $property, $value, Builder $aggregation
8787
[$matchField, $field, $associations] = $this->addLookupsForNestedProperty($property, $aggregationBuilder, $resourceClass);
8888
}
8989

90-
/**
91-
* @var MongoDBClassMetadata
92-
*/
93-
$metadata = $this->getNestedMetadata($resourceClass, $associations);
94-
9590
$caseSensitive = true;
91+
$strategy = $this->properties[$property] ?? self::STRATEGY_EXACT;
92+
93+
// prefixing the strategy with i makes it case insensitive
94+
if (0 === strpos($strategy, 'i')) {
95+
$strategy = substr($strategy, 1);
96+
$caseSensitive = false;
97+
}
98+
99+
/** @var MongoDBClassMetadata */
100+
$metadata = $this->getNestedMetadata($resourceClass, $associations);
96101

97102
if ($metadata->hasField($field) && !$metadata->hasAssociation($field)) {
98103
if ('id' === $field) {
@@ -107,23 +112,9 @@ protected function filterProperty(string $property, $value, Builder $aggregation
107112
return;
108113
}
109114

110-
$strategy = $this->properties[$property] ?? self::STRATEGY_EXACT;
115+
$this->addEqualityMatchStrategy($strategy, $aggregationBuilder, $field, $matchField, $values, $caseSensitive, $metadata);
111116

112-
// prefixing the strategy with i makes it case insensitive
113-
if (0 === strpos($strategy, 'i')) {
114-
$strategy = substr($strategy, 1);
115-
$caseSensitive = false;
116-
}
117-
118-
$inValues = [];
119-
foreach ($values as $inValue) {
120-
$inValues[] = $this->addEqualityMatchStrategy($strategy, $field, $inValue, $caseSensitive, $metadata);
121-
}
122-
123-
$aggregationBuilder
124-
->match()
125-
->field($matchField)
126-
->in($inValues);
117+
return;
127118
}
128119

129120
// metadata doesn't have the field, nor an association on the field
@@ -132,7 +123,6 @@ protected function filterProperty(string $property, $value, Builder $aggregation
132123
}
133124

134125
$values = array_map([$this, 'getIdFromValue'], $values);
135-
$associationFieldIdentifier = 'id';
136126
$doctrineTypeField = $this->getDoctrineFieldType($property, $resourceClass);
137127

138128
if (null !== $this->identifiersExtractor) {
@@ -149,23 +139,39 @@ protected function filterProperty(string $property, $value, Builder $aggregation
149139
return;
150140
}
151141

142+
$this->addEqualityMatchStrategy($strategy, $aggregationBuilder, $field, $matchField, $values, $caseSensitive, $metadata);
143+
}
144+
145+
/**
146+
* Add equality match stage according to the strategy.
147+
*/
148+
private function addEqualityMatchStrategy(string $strategy, Builder $aggregationBuilder, string $field, string $matchField, $values, bool $caseSensitive, ClassMetadata $metadata): void
149+
{
150+
$inValues = [];
151+
foreach ($values as $inValue) {
152+
$inValues[] = $this->getEqualityMatchStrategyValue($strategy, $field, $inValue, $caseSensitive, $metadata);
153+
}
154+
152155
$aggregationBuilder
153156
->match()
154157
->field($matchField)
155-
->in($values);
158+
->in($inValues);
156159
}
157160

158161
/**
159-
* Add equality match stage according to the strategy.
162+
* Get equality match value according to the strategy.
160163
*
161164
* @throws InvalidArgumentException If strategy does not exist
162165
*
163166
* @return Regex|string
164167
*/
165-
private function addEqualityMatchStrategy(string $strategy, string $field, $value, bool $caseSensitive, ClassMetadata $metadata)
168+
private function getEqualityMatchStrategyValue(string $strategy, string $field, $value, bool $caseSensitive, ClassMetadata $metadata)
166169
{
167170
$type = $metadata->getTypeOfField($field);
168171

172+
if (!MongoDbType::hasType($type)) {
173+
return $value;
174+
}
169175
if (MongoDbType::STRING !== $type) {
170176
return MongoDbType::getType($type)->convertToDatabaseValue($value);
171177
}

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

Lines changed: 10 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,15 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB
9191
[$alias, $field, $associations] = $this->addJoinsForNestedProperty($property, $alias, $queryBuilder, $queryNameGenerator, $resourceClass);
9292
}
9393

94+
$caseSensitive = true;
95+
$strategy = $this->properties[$property] ?? self::STRATEGY_EXACT;
96+
97+
// prefixing the strategy with i makes it case insensitive
98+
if (0 === strpos($strategy, 'i')) {
99+
$strategy = substr($strategy, 1);
100+
$caseSensitive = false;
101+
}
102+
94103
$metadata = $this->getNestedMetadata($resourceClass, $associations);
95104

96105
if ($metadata->hasField($field)) {
@@ -106,15 +115,6 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB
106115
return;
107116
}
108117

109-
$caseSensitive = true;
110-
$strategy = $this->properties[$property] ?? self::STRATEGY_EXACT;
111-
112-
// prefixing the strategy with i makes it case insensitive
113-
if (0 === strpos($strategy, 'i')) {
114-
$strategy = substr($strategy, 1);
115-
$caseSensitive = false;
116-
}
117-
118118
$this->addWhereByStrategy($strategy, $queryBuilder, $queryNameGenerator, $alias, $field, $values, $caseSensitive, $metadata);
119119

120120
return;
@@ -145,34 +145,12 @@ protected function filterProperty(string $property, $value, QueryBuilder $queryB
145145

146146
$associationAlias = $alias;
147147
$associationField = $field;
148-
$valueParameter = $queryNameGenerator->generateParameterName($associationField);
149148
if ($metadata->isCollectionValuedAssociation($associationField)) {
150149
$associationAlias = QueryBuilderHelper::addJoinOnce($queryBuilder, $queryNameGenerator, $alias, $associationField);
151150
$associationField = $associationFieldIdentifier;
152151
}
153152

154-
$type = $metadata->getTypeOfField($associationField);
155-
156-
if (1 === \count($values)) {
157-
$queryBuilder
158-
->andWhere($queryBuilder->expr()->eq($associationAlias.'.'.$associationField, ':'.$valueParameter))
159-
->setParameter($valueParameter, $values[0], $type);
160-
161-
return;
162-
}
163-
164-
$parameters = $queryBuilder->getParameters();
165-
$inQuery = [];
166-
167-
foreach ($values as $val) {
168-
$inQuery[] = ':'.$valueParameter;
169-
$parameters->add(new Parameter($valueParameter, $val, $type));
170-
$valueParameter = $queryNameGenerator->generateParameterName($associationField);
171-
}
172-
173-
$queryBuilder
174-
->andWhere($associationAlias.'.'.$associationField.' IN ('.implode(', ', $inQuery).')')
175-
->setParameters($parameters);
153+
$this->addWhereByStrategy($strategy, $queryBuilder, $queryNameGenerator, $associationAlias, $associationField, $values, $caseSensitive, $metadata);
176154
}
177155

178156
/**

tests/Bridge/Doctrine/Orm/Filter/SearchFilterTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -543,11 +543,11 @@ public function provideApplyTestData(): array
543543
$filterFactory,
544544
],
545545
'mixed IRI and entity ID values for relations' => [
546-
sprintf('SELECT %s FROM %s %1$s INNER JOIN %1$s.relatedDummies relatedDummies_a1 WHERE %1$s.relatedDummy IN (:relatedDummy_p1, :relatedDummy_p2) AND relatedDummies_a1.id = :relatedDummies_p4', $this->alias, Dummy::class),
546+
sprintf('SELECT %s FROM %s %1$s INNER JOIN %1$s.relatedDummies relatedDummies_a1 WHERE %1$s.relatedDummy IN (:relatedDummy_p1, :relatedDummy_p2) AND relatedDummies_a1.id = :id_p4', $this->alias, Dummy::class),
547547
[
548548
'relatedDummy_p1' => 1,
549549
'relatedDummy_p2' => 2,
550-
'relatedDummies_p4' => 1,
550+
'id_p4' => 1,
551551
],
552552
$filterFactory,
553553
],

0 commit comments

Comments
 (0)