From 8829762ccdeafc69a2c9a701a06f98178e48921f Mon Sep 17 00:00:00 2001 From: Petro Vashchuk Date: Wed, 2 Jun 2021 17:58:01 +0300 Subject: [PATCH] Bug 28316: different QueryRegexEscapeOptions' values work as expected This patch ensures that the behavior with QueryRegexEscapeOptions set to values other than "Escape" still work as expected. It does so by storing the contents of regexes before escaping square and curly brackets and then restores the contents of regexes back to how it was before. Also this patch covers this with tests. --- .../Elasticsearch/QueryBuilder.pm | 27 ++++++++++++++++--- .../SearchEngine/Elasticsearch/QueryBuilder.t | 16 ++++++++--- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/Koha/SearchEngine/Elasticsearch/QueryBuilder.pm b/Koha/SearchEngine/Elasticsearch/QueryBuilder.pm index 1bff8a3cba..42e6aa7562 100644 --- a/Koha/SearchEngine/Elasticsearch/QueryBuilder.pm +++ b/Koha/SearchEngine/Elasticsearch/QueryBuilder.pm @@ -943,15 +943,34 @@ sub _clean_search_term { $term =~ s/(\s+)(:+)$lookahead/$1/g; $term =~ s/^://; + $term = $self->_query_regex_escape_process($term); + # replace all ranges with any square/curly brackets combinations to temporary substitutions (ex: "{a TO b]"" -> "~~LC~~a TO b~~RS~~") $term =~ s/(\{|\[)([^\s\[\]\{\}]+ TO [^\s\[\]\{\}]+)(\}|\])/'~~L'.($1 eq '[' ? 'S':'C').'~~'.$2.'~~R'.($3 eq ']' ? 'S':'C').'~~'/ge; - # screen all brackets with backslash - $term =~ s/([\{\}\[\]])/\\$1/g; + + # store the content of regex before escaping brackets: + my @saved_regexes; + my $rgx_i = 0; + while( + $term =~ s@( + (?_query_regex_escape_process($term); - return $term; } diff --git a/t/Koha/SearchEngine/Elasticsearch/QueryBuilder.t b/t/Koha/SearchEngine/Elasticsearch/QueryBuilder.t index 7175f63743..7579170f20 100755 --- a/t/Koha/SearchEngine/Elasticsearch/QueryBuilder.t +++ b/t/Koha/SearchEngine/Elasticsearch/QueryBuilder.t @@ -187,7 +187,7 @@ subtest '_split_query() tests' => sub { }; subtest '_clean_search_term() tests' => sub { - plan tests => 13; + plan tests => 15; my $qb; ok( @@ -219,12 +219,22 @@ subtest '_clean_search_term() tests' => sub { $res = $qb->_clean_search_term('test [123 TO 345]'); is($res, 'test [123 TO 345]', 'keep inculsive range untouched'); - $res = $qb->_clean_search_term('test [test TO TEST} [and] {123 TO 456]'); - is($res, 'test [test TO TEST} \[and\] {123 TO 456]', 'keep exclusive range untouched'); + $res = $qb->_clean_search_term('test [test TO TEST} ["[and] {123 TO 456]" "[balanced]"]'); + is($res, 'test [test TO TEST} \["[and] {123 TO 456]" "[balanced]"\]', 'keep exclusive range untouched'); $res = $qb->_clean_search_term('test[]test TO TEST] [ {123 to 345}}'); is($res, 'test\[\]test TO TEST\] \[ \{123 to 345\}\}', 'screen all square and curly brackets'); + t::lib::Mocks::mock_preference('QueryRegexEscapeOptions', 'escape'); + + $res = $qb->_clean_search_term('test inside regexps /this [a-z]/ and \/not [a-z]\/ and that [a-z] [a TO z]'); + is($res, 'test inside regexps \/this \[a-z\]\/ and \/not \[a-z\]\/ and that \[a-z\] [a TO z]', 'test inside regexps with QueryRegexEscapeOptions parameter set to escape'); + + t::lib::Mocks::mock_preference('QueryRegexEscapeOptions', 'dont_escape'); + + $res = $qb->_clean_search_term('test inside regexps /this [a-z]/ /this2 [a-z]/ [but] /this3 [a-z]/ and \/not [a-z]\/ and that [a-z] [a TO z]'); + is($res, 'test inside regexps /this [a-z]/ /this2 [a-z]/ \[but\] /this3 [a-z]/ and \/not \[a-z\]\/ and that \[a-z\] [a TO z]', 'test inside regexps with QueryRegexEscapeOptions parameter set to dont_escape'); + $res = $qb->_clean_search_term('ti:test AND kw:test'); is($res, 'title:test AND test', 'ti converted to title, kw converted to empty string, dangling colon removed with space preserved'); -- 2.31.1