Skip to content

Commit 5c6cf04

Browse files
committed
Support non-applicable filters
If the user submitted values do not make senses as filters, such as an empty string for a search term, then we can skip applying the filter by returning `null`.
1 parent 6657c14 commit 5c6cf04

File tree

11 files changed

+96
-33
lines changed

11 files changed

+96
-33
lines changed

src/Definition/Operator/AbstractOperator.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ abstract protected function getConfiguration(Types $types, LeafType $leafType):
5050
/**
5151
* Return the DQL condition to apply the filter
5252
*
53+
* In most cases a DQL condition should be returned as a string, but it might be useful to
54+
* return null if the filter is not applicable (eg: a search term with empty string).
55+
*
5356
* The query builder:
5457
*
5558
* - MUST NOT be used to apply the condition directly (with `*where()` methods). Instead the condition MUST
@@ -64,7 +67,7 @@ abstract protected function getConfiguration(Types $types, LeafType $leafType):
6467
* @param string $field the field for the entity on which to apply the filter
6568
* @param array $args all arguments specific to this operator as declared in its configuration
6669
*
67-
* @return string
70+
* @return null|string
6871
*/
69-
abstract public function getDqlCondition(UniqueNameFactory $uniqueNameFactory, ClassMetadata $metadata, QueryBuilder $queryBuilder, string $alias, string $field, array $args): string;
72+
abstract public function getDqlCondition(UniqueNameFactory $uniqueNameFactory, ClassMetadata $metadata, QueryBuilder $queryBuilder, string $alias, string $field, array $args): ?string;
7073
}

src/Definition/Operator/AbstractSimpleOperator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ final protected function getConfiguration(Types $types, LeafType $leafType): arr
3535
];
3636
}
3737

38-
final public function getDqlCondition(UniqueNameFactory $uniqueNameFactory, ClassMetadata $metadata, QueryBuilder $queryBuilder, string $alias, string $field, array $args): string
38+
final public function getDqlCondition(UniqueNameFactory $uniqueNameFactory, ClassMetadata $metadata, QueryBuilder $queryBuilder, string $alias, string $field, array $args): ?string
3939
{
4040
$param = $uniqueNameFactory->createParameterName();
4141
$queryBuilder->setParameter($param, $args['value']);

src/Definition/Operator/BetweenOperatorType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ protected function getConfiguration(Types $types, LeafType $leafType): array
3434
];
3535
}
3636

37-
public function getDqlCondition(UniqueNameFactory $uniqueNameFactory, ClassMetadata $metadata, QueryBuilder $queryBuilder, string $alias, string $field, array $args): string
37+
public function getDqlCondition(UniqueNameFactory $uniqueNameFactory, ClassMetadata $metadata, QueryBuilder $queryBuilder, string $alias, string $field, array $args): ?string
3838
{
3939
$from = $uniqueNameFactory->createParameterName();
4040
$to = $uniqueNameFactory->createParameterName();

src/Definition/Operator/ContainOperatorType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ protected function getConfiguration(Types $types, LeafType $leafType): array
3030
];
3131
}
3232

33-
public function getDqlCondition(UniqueNameFactory $uniqueNameFactory, ClassMetadata $metadata, QueryBuilder $queryBuilder, string $alias, string $field, array $args): string
33+
public function getDqlCondition(UniqueNameFactory $uniqueNameFactory, ClassMetadata $metadata, QueryBuilder $queryBuilder, string $alias, string $field, array $args): ?string
3434
{
3535
$values = $uniqueNameFactory->createParameterName();
3636
$queryBuilder->setParameter($values, $args['values']);

src/Definition/Operator/EmptyOperatorType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ protected function getConfiguration(Types $types, LeafType $leafType): array
2626
];
2727
}
2828

29-
public function getDqlCondition(UniqueNameFactory $uniqueNameFactory, ClassMetadata $metadata, QueryBuilder $queryBuilder, string $alias, string $field, array $args): string
29+
public function getDqlCondition(UniqueNameFactory $uniqueNameFactory, ClassMetadata $metadata, QueryBuilder $queryBuilder, string $alias, string $field, array $args): ?string
3030
{
3131
$not = $args['not'] ? 'NOT ' : '';
3232

src/Definition/Operator/InOperatorType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ protected function getConfiguration(Types $types, LeafType $leafType): array
3030
];
3131
}
3232

33-
public function getDqlCondition(UniqueNameFactory $uniqueNameFactory, ClassMetadata $metadata, QueryBuilder $queryBuilder, string $alias, string $field, array $args): string
33+
public function getDqlCondition(UniqueNameFactory $uniqueNameFactory, ClassMetadata $metadata, QueryBuilder $queryBuilder, string $alias, string $field, array $args): ?string
3434
{
3535
$values = $uniqueNameFactory->createParameterName();
3636
$queryBuilder->setParameter($values, $args['values']);

src/Definition/Operator/NullOperatorType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ protected function getConfiguration(Types $types, LeafType $leafType): array
2626
];
2727
}
2828

29-
public function getDqlCondition(UniqueNameFactory $uniqueNameFactory, ClassMetadata $metadata, QueryBuilder $queryBuilder, string $alias, string $field, array $args): string
29+
public function getDqlCondition(UniqueNameFactory $uniqueNameFactory, ClassMetadata $metadata, QueryBuilder $queryBuilder, string $alias, string $field, array $args): ?string
3030
{
3131
$not = $args['not'] ? 'NOT ' : '';
3232

src/Factory/FilteredQueryBuilderFactory.php

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -91,21 +91,14 @@ private function applyFilters(ClassMetadata $metadata, InputObjectType $type, ar
9191
/** @var AbstractOperator $operatorType */
9292
$operatorType = $operatorField->type;
9393

94-
$dqlConditions[] = $operatorType->getDqlCondition($this->uniqueNameFactory, $metadata, $queryBuilder, $alias, $field, $operatorConfig);
94+
$condition = $operatorType->getDqlCondition($this->uniqueNameFactory, $metadata, $queryBuilder, $alias, $field, $operatorConfig);
95+
if ($condition) {
96+
$dqlConditions[] = $condition;
97+
}
9598
}
9699
}
97100

98-
if ($conditions['fieldsLogic'] === 'AND') {
99-
$fieldsDql = $queryBuilder->expr()->andX(...$dqlConditions);
100-
} else {
101-
$fieldsDql = $queryBuilder->expr()->orX(...$dqlConditions);
102-
}
103-
104-
if ($conditions['conditionLogic'] === 'AND') {
105-
$queryBuilder->andWhere($fieldsDql);
106-
} else {
107-
$queryBuilder->orWhere($fieldsDql);
108-
}
101+
$this->applyDqlConditions($queryBuilder, $conditions, $dqlConditions);
109102
}
110103
}
111104

@@ -165,4 +158,30 @@ private function applySorting(string $className, array $sorting, QueryBuilder $q
165158
}
166159
}
167160
}
161+
162+
/**
163+
* Apply DQL conditions on the query builder
164+
*
165+
* @param QueryBuilder $queryBuilder
166+
* @param array $conditions
167+
* @param array $dqlConditions
168+
*/
169+
private function applyDqlConditions(QueryBuilder $queryBuilder, array $conditions, array $dqlConditions): void
170+
{
171+
if (!$dqlConditions) {
172+
return;
173+
}
174+
175+
if ($conditions['fieldsLogic'] === 'AND') {
176+
$fieldsDql = $queryBuilder->expr()->andX(...$dqlConditions);
177+
} else {
178+
$fieldsDql = $queryBuilder->expr()->orX(...$dqlConditions);
179+
}
180+
181+
if ($conditions['conditionLogic'] === 'AND') {
182+
$queryBuilder->andWhere($fieldsDql);
183+
} else {
184+
$queryBuilder->orWhere($fieldsDql);
185+
}
186+
}
168187
}

tests/Blog/Filtering/ModuloOperatorType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ protected function getConfiguration(Types $types, LeafType $leafType): array
2626
];
2727
}
2828

29-
public function getDqlCondition(UniqueNameFactory $uniqueNameFactory, ClassMetadata $metadata, QueryBuilder $queryBuilder, string $alias, string $field, array $args): string
29+
public function getDqlCondition(UniqueNameFactory $uniqueNameFactory, ClassMetadata $metadata, QueryBuilder $queryBuilder, string $alias, string $field, array $args): ?string
3030
{
3131
$param = $uniqueNameFactory->createParameterName();
3232
$queryBuilder->setParameter($param, $args['value']);

tests/Blog/Filtering/SearchOperatorType.php

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,18 @@ protected function getConfiguration(Types $types, LeafType $leafType): array
2626
];
2727
}
2828

29-
public function getDqlCondition(UniqueNameFactory $uniqueNameFactory, ClassMetadata $metadata, QueryBuilder $queryBuilder, string $alias, string $field, array $args): string
29+
public function getDqlCondition(UniqueNameFactory $uniqueNameFactory, ClassMetadata $metadata, QueryBuilder $queryBuilder, string $alias, string $field, array $args): ?string
3030
{
31-
$search = $args['term'];
32-
33-
$fields = [];
34-
35-
// Find all textual fields for the entity
36-
$textType = ['string', 'text'];
37-
foreach ($metadata->fieldMappings as $g) {
38-
if (in_array($g['type'], $textType, true)) {
39-
$fields[] = $alias . '.' . $g['fieldName'];
40-
}
31+
$words = preg_split('/[[:space:]]+/', $args['term'], -1, PREG_SPLIT_NO_EMPTY);
32+
if (!$words) {
33+
return null;
4134
}
4235

36+
$fields = $this->getSearchableFields($metadata, $alias);
37+
4338
// Build the WHERE clause
4439
$wordWheres = [];
45-
foreach (preg_split('/[[:space:]]+/', $search, -1, PREG_SPLIT_NO_EMPTY) as $i => $word) {
40+
foreach ($words as $word) {
4641
$parameterName = $uniqueNameFactory->createParameterName();
4742

4843
$fieldWheres = [];
@@ -58,4 +53,25 @@ public function getDqlCondition(UniqueNameFactory $uniqueNameFactory, ClassMetad
5853

5954
return '(' . implode(' AND ', $wordWheres) . ')';
6055
}
56+
57+
/**
58+
* Find all textual fields for the entity
59+
*
60+
* @param ClassMetadata $metadata
61+
* @param string $alias
62+
*
63+
* @return array
64+
*/
65+
private function getSearchableFields(ClassMetadata $metadata, string $alias): array
66+
{
67+
$fields = [];
68+
$textType = ['string', 'text'];
69+
foreach ($metadata->fieldMappings as $g) {
70+
if (in_array($g['type'], $textType, true)) {
71+
$fields[] = $alias . '.' . $g['fieldName'];
72+
}
73+
}
74+
75+
return $fields;
76+
}
6177
}

0 commit comments

Comments
 (0)