diff --git a/src/Traits/SearchTrait.php b/src/Traits/SearchTrait.php index 64145a0..b878912 100644 --- a/src/Traits/SearchTrait.php +++ b/src/Traits/SearchTrait.php @@ -282,7 +282,10 @@ protected function getQuerySearchCallback(string $field, string $mask): Closure { return function ($query) use ($field, $mask) { $databaseDriver = config('database.default'); - $value = str_replace('{{ value }}', $this->filter['query'], $mask); + $value = ($databaseDriver === 'pgsql') + ? pg_escape_string($this->filter['query']) + : addslashes($this->filter['query']); + $value = str_replace('{{ value }}', $value, $mask); $operator = ($databaseDriver === 'pgsql') ? 'ilike' : 'like'; diff --git a/tests/SearchTraitTest.php b/tests/SearchTraitTest.php index 50007ec..d089b5b 100644 --- a/tests/SearchTraitTest.php +++ b/tests/SearchTraitTest.php @@ -188,7 +188,7 @@ public function testSearchQueryWithQuery() $this->testRepositoryClass ->searchQuery([ - 'query' => 'search_string' + 'query' => 'search_\'string' ]) ->filterByQuery(['query_field', 'another_query_field']) ->getSearchResults(); @@ -204,7 +204,7 @@ public function testSearchQueryWithMaskedQuery() $this->testRepositoryClass ->searchQuery([ - 'query' => 'search_string' + 'query' => 'search_\'string' ]) ->filterByQuery(['query_field', 'another_query_field'], "'%' || unaccent('{{ value }}') || '%'") ->getSearchResults(); diff --git a/tests/support/Traits/SqlMockTrait.php b/tests/support/Traits/SqlMockTrait.php index 48f96ea..2cf2181 100644 --- a/tests/support/Traits/SqlMockTrait.php +++ b/tests/support/Traits/SqlMockTrait.php @@ -309,13 +309,13 @@ protected function mockGetSearchResultWithQuery(array $selectResult): void { $this->mockSelectWithAggregate( "select count(*) as aggregate from `test_models` " - . "where ((`query_field` like '%search_string%') or (`another_query_field` like '%search_string%')) " - . "and `test_models`.`deleted_at` is null" + . "where ((`query_field` like '%search_\'string%') or (`another_query_field` like '%search_\'string%')) " + . 'and `test_models`.`deleted_at` is null' ); $this->mockSelect( - "select * from `test_models` where ((`query_field` like '%search_string%') " - . "or (`another_query_field` like '%search_string%')) and `test_models`.`deleted_at` is null " + "select * from `test_models` where ((`query_field` like '%search_\'string%') " + . "or (`another_query_field` like '%search_\'string%')) and `test_models`.`deleted_at` is null " . "order by `id` asc limit 15 offset 0", $selectResult ); @@ -325,15 +325,15 @@ protected function mockGetSearchResultWithCustomQuery(array $selectResult): void { $this->mockSelectWithAggregate( 'select count(*) as aggregate from "test_models" ' - . 'where (("query_field"::text ilike \'%\' || unaccent(\'search_string\') || \'%\') ' - . 'or ("another_query_field"::text ilike \'%\' || unaccent(\'search_string\') || \'%\')) ' + . 'where (("query_field"::text ilike \'%\' || unaccent(\'search_\'\'string\') || \'%\') ' + . 'or ("another_query_field"::text ilike \'%\' || unaccent(\'search_\'\'string\') || \'%\')) ' . 'and "test_models"."deleted_at" is null' ); $this->mockSelect( 'select * from "test_models" ' - . 'where (("query_field"::text ilike \'%\' || unaccent(\'search_string\') || \'%\') ' - . 'or ("another_query_field"::text ilike \'%\' || unaccent(\'search_string\') || \'%\')) ' + . 'where (("query_field"::text ilike \'%\' || unaccent(\'search_\'\'string\') || \'%\') ' + . 'or ("another_query_field"::text ilike \'%\' || unaccent(\'search_\'\'string\') || \'%\')) ' . 'and "test_models"."deleted_at" is null order by "id" asc limit 15 offset 0', $selectResult );