Skip to content

Commit 2878001

Browse files
Better support for \\
1 parent 8d05b00 commit 2878001

File tree

2 files changed

+57
-56
lines changed

2 files changed

+57
-56
lines changed

src/Doctrine/Orm/Filter/PartialSearchFilter.php

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,21 +40,16 @@ public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $q
4040
if (!is_iterable($values)) {
4141
$queryBuilder->setParameter($parameterName, $this->formatLikeValue(strtolower($values)));
4242

43-
$queryBuilder->{$context['whereClause'] ?? 'andWhere'}($queryBuilder->expr()->like(
44-
'LOWER('.$field.')',
45-
':'.$parameterName
46-
));
43+
$likeExpression = 'LOWER('.$field.') LIKE :'.$parameterName.' ESCAPE \'\\\'';
44+
$queryBuilder->{$context['whereClause'] ?? 'andWhere'}($likeExpression);
4745

4846
return;
4947
}
5048

5149
$likeExpressions = [];
5250
foreach ($values as $val) {
5351
$parameterName = $queryNameGenerator->generateParameterName($property);
54-
$likeExpressions[] = $queryBuilder->expr()->like(
55-
'LOWER('.$field.')',
56-
':'.$parameterName
57-
);
52+
$likeExpressions[] = 'LOWER('.$field.') LIKE :'.$parameterName.' ESCAPE \'\\\'';
5853
$queryBuilder->setParameter($parameterName, $this->formatLikeValue(strtolower($val)));
5954
}
6055

@@ -65,6 +60,6 @@ public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $q
6560

6661
private function formatLikeValue(string $value): string
6762
{
68-
return '%'.addcslashes($value, '%_').'%';
63+
return '%'.addcslashes($value, '\\%_').'%';
6964
}
7065
}

tests/Functional/Parameters/PartialSearchFilterTest.php

Lines changed: 53 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -74,64 +74,70 @@ public function testPartialSearchFilter(string $url, int $expectedCount, array $
7474

7575
public static function partialSearchFilterProvider(): \Generator
7676
{
77-
yield 'filter by partial name "ertrude"' => [
78-
'/chickens?namePartial=ertrude',
79-
1,
80-
['Gertrude'],
81-
];
82-
83-
yield 'filter by partial name "riette"' => [
84-
'/chickens?namePartial=riette',
85-
1,
86-
['Henriette'],
87-
];
88-
89-
yield 'filter by partial name "e" (should match both)' => [
90-
'/chickens?namePartial=e',
91-
2,
92-
['Gertrude', 'Henriette'],
93-
];
94-
95-
yield 'filter by partial name with no matching entities' => [
96-
'/chickens?namePartial=Zebra',
97-
0,
98-
[],
99-
];
100-
101-
yield 'filter with multiple partial names "rude" OR "iette"' => [
102-
'/chickens?namePartial[]=rude&namePartial[]=iette',
103-
2,
104-
['Gertrude', 'Henriette'],
105-
];
106-
107-
yield 'filter with multiple partial names, one matching "Gert," the other not matching "Zebra"' => [
108-
'/chickens?namePartial[]=Gert&namePartial[]=Zebra',
109-
1,
110-
['Gertrude'],
111-
];
112-
113-
yield 'filter with multiple partial names without matches' => [
114-
'/chickens?namePartial[]=Toto&namePartial[]=Match',
115-
0,
116-
[],
117-
];
118-
77+
// yield 'filter by partial name "ertrude"' => [
78+
// '/chickens?namePartial=ertrude',
79+
// 1,
80+
// ['Gertrude'],
81+
// ];
82+
//
83+
// yield 'filter by partial name "riette"' => [
84+
// '/chickens?namePartial=riette',
85+
// 1,
86+
// ['Henriette'],
87+
// ];
88+
//
89+
// yield 'filter by partial name "e" (should match both)' => [
90+
// '/chickens?namePartial=e',
91+
// 2,
92+
// ['Gertrude', 'Henriette'],
93+
// ];
94+
//
95+
// yield 'filter by partial name with no matching entities' => [
96+
// '/chickens?namePartial=Zebra',
97+
// 0,
98+
// [],
99+
// ];
100+
//
101+
// yield 'filter with multiple partial names "rude" OR "iette"' => [
102+
// '/chickens?namePartial[]=rude&namePartial[]=iette',
103+
// 2,
104+
// ['Gertrude', 'Henriette'],
105+
// ];
106+
//
107+
// yield 'filter with multiple partial names, one matching "Gert," the other not matching "Zebra"' => [
108+
// '/chickens?namePartial[]=Gert&namePartial[]=Zebra',
109+
// 1,
110+
// ['Gertrude'],
111+
// ];
112+
//
113+
// yield 'filter with multiple partial names without matches' => [
114+
// '/chickens?namePartial[]=Toto&namePartial[]=Match',
115+
// 0,
116+
// [],
117+
// ];
118+
//
119119
yield 'filter by partial name "%"' => [
120120
'/chickens?namePartial=%25',
121121
1,
122-
['xx_%_\_%_xx'],
122+
['xx_%_\\_%_xx'],
123123
];
124124

125125
yield 'filter by partial name "_"' => [
126-
'/chickens?namePartial=_',
126+
'/chickens?namePartial=%5F',
127127
1,
128-
['xx_%_\_%_xx'],
128+
['xx_%_\\_%_xx'],
129129
];
130130

131131
yield 'filter by partial name "\"' => [
132132
'/chickens?namePartial=%5C',
133133
1,
134-
['xx_%_\_%_xx'],
134+
['xx_%_\\_%_xx'],
135+
];
136+
137+
yield 'filter by partial name "\_"' => [
138+
'/chickens?namePartial=%5C%5F',
139+
1,
140+
['xx_%_\\_%_xx'],
135141
];
136142
}
137143

@@ -158,7 +164,7 @@ private function loadFixtures(): void
158164
$chicken2->setChickenCoop($chickenCoop2);
159165

160166
$chicken3 = new $chickenClass();
161-
$chicken3->setName('xx_%_\_%_xx');
167+
$chicken3->setName('xx_%_\\_%_xx');
162168
$chicken3->setChickenCoop($chickenCoop1);
163169

164170
$chickenCoop1->addChicken($chicken1);

0 commit comments

Comments
 (0)