@@ -, +, @@ expected --- .../Elasticsearch/QueryBuilder.pm | 27 ++++++++++++++++--- .../SearchEngine/Elasticsearch/QueryBuilder.t | 16 ++++++++--- 2 files changed, 36 insertions(+), 7 deletions(-) --- a/Koha/SearchEngine/Elasticsearch/QueryBuilder.pm +++ a/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; } --- a/t/Koha/SearchEngine/Elasticsearch/QueryBuilder.t +++ a/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'); --