From 23c6007b37e8aaf52fd0c04962863155d1aecc6c Mon Sep 17 00:00:00 2001 From: Janusz Kaczmarek Date: Wed, 4 Mar 2026 16:06:19 +0000 Subject: [PATCH] Bug 28884: ElasticSearch: Question mark in title search returns no results MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test plan: ========== 1. Have a ktd instance with Elasticsearch enabled. 2. In standard ktd installation there is a record with a title "Typical girls? : the story of the Slits." (with question mark attached to a word) - biblio # 229. We will try to find it. 3. Go to advanced search (OPAC or intranet) and try a *title* search with: Typical girls? the story of the Slits You should get no results. From the main page try a ccl-style search: ti:Typical girls? the story of the Slits You should get no results too. 4. Apply the patch ; updatedatabase ; restart_all. 5. Put ? in OpacElasticsearchEscapeCharacters and/or ElasticsearchEscapeCharacters system preference. 4. Repeat the searches from p. 3. You should get the record if a system preference was set for the given interface. Sponsored-by: Pontificia Università di San Tommaso d'Aquino (Angelicum) --- .../Elasticsearch/QueryBuilder.pm | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Koha/SearchEngine/Elasticsearch/QueryBuilder.pm b/Koha/SearchEngine/Elasticsearch/QueryBuilder.pm index ad339ae7e4..898fcd9956 100644 --- a/Koha/SearchEngine/Elasticsearch/QueryBuilder.pm +++ b/Koha/SearchEngine/Elasticsearch/QueryBuilder.pm @@ -1026,6 +1026,9 @@ sub clean_search_term { $term = $self->_convert_index_strings_freeform($term); + # escape special characters + $term = $self->_escape_special_characters($term); + # Remove unbalanced quotes my $unquoted = $term; my $count = ( $unquoted =~ tr/"/ / ); @@ -1114,6 +1117,30 @@ sub clean_search_term { return $term; } +=head2 _escape_special_characters + + $term = $self->_escape_special_characters($term); + +Escapes characters in $term according to "ElasticsearchEscapeCharacters" / +"OpacElasticsearchEscapeCharacters" system preference setting. + +=cut + +sub _escape_special_characters { + my ( $self, $term ) = @_; + my $characters_to_escape; + if ( C4::Context->interface eq 'opac' ) { + $characters_to_escape = C4::Context->preference('OpacElasticsearchEscapeCharacters'); + } else { + $characters_to_escape = C4::Context->preference('ElasticsearchEscapeCharacters'); + } + if ($characters_to_escape) { + $characters_to_escape =~ s/\s+//g; + $term =~ s/[\Q$characters_to_escape\E]/\\$&/g if $characters_to_escape; + } + return $term; +} + =head2 _query_regex_escape_process my $query = $self->_query_regex_escape_process($query); -- 2.39.5