From 10d30532157bc342135654e85e3494e4033f3f9b Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 1 Jun 2023 14:02:58 +0200 Subject: [PATCH] FilterProcessor: Escape literal percent signs fixes #71 --- src/Compat/FilterProcessor.php | 6 +++-- tests/FilterProcessorTest.php | 41 ++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 tests/FilterProcessorTest.php diff --git a/src/Compat/FilterProcessor.php b/src/Compat/FilterProcessor.php index 7d779d7..cbf044e 100644 --- a/src/Compat/FilterProcessor.php +++ b/src/Compat/FilterProcessor.php @@ -79,9 +79,11 @@ public static function assemblePredicate(Filter\Condition $filter) if ($expression === '*') { return ["$column IS " . ($filter instanceof Filter\Like ? 'NOT ' : '') . 'NULL']; } elseif ($filter instanceof Filter\Unlike) { - return ["($column NOT LIKE ? OR $column IS NULL)" => str_replace('*', '%', $expression)]; + return [ + "($column NOT LIKE ? OR $column IS NULL)" => str_replace(['%', '*'], ['\\%', '%'], $expression) + ]; } else { - return ["$column LIKE ?" => str_replace('*', '%', $expression)]; + return ["$column LIKE ?" => str_replace(['%', '*'], ['\\%', '%'], $expression)]; } } elseif ($filter instanceof Filter\Unequal || $filter instanceof Filter\Unlike) { return ["($column != ? OR $column IS NULL)" => $expression]; diff --git a/tests/FilterProcessorTest.php b/tests/FilterProcessorTest.php new file mode 100644 index 0000000..e68e572 --- /dev/null +++ b/tests/FilterProcessorTest.php @@ -0,0 +1,41 @@ +assertSame( + ['foo IS NOT NULL'], + FilterProcessor::assemblePredicate(Filter::like('foo', '*')) + ); + $this->assertSame( + ['foo LIKE ?' => '%bar%'], + FilterProcessor::assemblePredicate(Filter::like('foo', '*bar*')) + ); + $this->assertSame( + ['foo LIKE ?' => '%\\%%'], + FilterProcessor::assemblePredicate(Filter::like('foo', '*%*')) + ); + } + + public function testUnlikeToSql() + { + $this->assertSame( + ['foo IS NULL'], + FilterProcessor::assemblePredicate(Filter::unlike('foo', '*')) + ); + $this->assertSame( + ['(foo NOT LIKE ? OR foo IS NULL)' => '%bar%'], + FilterProcessor::assemblePredicate(Filter::unlike('foo', '*bar*')) + ); + $this->assertSame( + ['(foo NOT LIKE ? OR foo IS NULL)' => '%\\%%'], + FilterProcessor::assemblePredicate(Filter::unlike('foo', '*%*')) + ); + } +}