From 7fac5214af8f39b05665685e52e335f65e3c0a35 Mon Sep 17 00:00:00 2001 From: David Cook Date: Thu, 24 Oct 2024 01:33:44 +0000 Subject: [PATCH] Bug 14007: Filter search result values to remove OpacHiddenItems values This change filters the values from the OpacHiddenItems syspref out of their corresponding search results facets. Note: This does not mean that all values from hidden items are filtered out of facets. Rather, it just means that facet data that matches OpacHiddenItems is filtered out. This is an imperfect fix, but it is a practical fix that has been requested by more than one library. Test plan: 0. Apply the patch and koha-plack --restart kohadev 1. Go to http://localhost:8081/cgi-bin/koha/catalogue/detail.pl?biblionumber=29 2. Add an item with an item type of "Maps" 3. Go to http://localhost:8081/cgi-bin/koha/admin/preferences.pl?op=search&searchfield=OpacHiddenItems 4. Fill in OpacHiddenItems with the following: itype: ['MP'] 5. Go to http://localhost:8080/cgi-bin/koha/opac-search.pl?idx=&q=test&weight_search=1 6. Note that "Maps" does not appear in the "Item types" facet 7. Go to http://localhost:8081/cgi-bin/koha/catalogue/search.pl?q=test 8. Note that "Maps" does appear in the "Item types" facet 9. ***Repeat this test plan using both Elasticsearch and Zebra indexing*** 10. prove -v t/Koha/SearchEngine/Search.t --- Koha/SearchEngine/Elasticsearch/Search.pm | 8 ++- Koha/SearchEngine/Search.pm | 50 +++++++++++++++ Koha/SearchEngine/Zebra/Search.pm | 9 ++- t/Koha/SearchEngine/Search.t | 75 ++++++++++++++++++++++- 4 files changed, 138 insertions(+), 4 deletions(-) diff --git a/Koha/SearchEngine/Elasticsearch/Search.pm b/Koha/SearchEngine/Elasticsearch/Search.pm index 42326e3573..9696e1457a 100644 --- a/Koha/SearchEngine/Elasticsearch/Search.pm +++ b/Koha/SearchEngine/Elasticsearch/Search.pm @@ -183,7 +183,13 @@ sub search_compat { my %result; $result{biblioserver}{hits} = $hits->{'total'}; $result{biblioserver}{RECORDS} = \@records; - return (undef, \%result, $self->_convert_facets($results->{aggregations})); + + my $facets = $self->_convert_facets( $results->{aggregations} ); + if ( C4::Context->interface eq 'opac' ) { + my $rules = C4::Context->yaml_preference('OpacHiddenItems'); + $facets = Koha::SearchEngine::Search->post_filter_opac_facets( { facets => $facets, rules => $rules } ); + } + return (undef, \%result, $facets); } =head2 search_auth_compat diff --git a/Koha/SearchEngine/Search.pm b/Koha/SearchEngine/Search.pm index 578ae8979c..b3a1230f97 100644 --- a/Koha/SearchEngine/Search.pm +++ b/Koha/SearchEngine/Search.pm @@ -179,4 +179,54 @@ sub pagination_bar { } +=head2 post_filter_opac_facets + + if ( C4::Context->interface eq 'opac' ) { + my $rules = C4::Context->yaml_preference('OpacHiddenItems'); + $facets = Koha::SearchEngine::Search->post_filter_facets({ facets => $facets, rules => $rules }); + } + +=cut + +sub post_filter_opac_facets { + my ( $class, $args ) = @_; + my $facets = $args->{facets}; + my $rules = $args->{rules}; + if ( $rules && $facets ) { + + #Build a hashmap of the rules to provide efficient lookups + my $rule_map = {}; + my @keys = keys %$rules; + foreach my $key (@keys) { + $rule_map->{$key} = {}; + foreach my $rule_value ( @{ $rules->{$key} } ) { + $rule_map->{$key}->{$rule_value} = 1; + } + } + + #Iterate through the facets + foreach my $facet_type (@$facets) { + my $type_link_value = $facet_type->{type_link_value}; + my $rule_map_by_type = $rule_map->{$type_link_value}; + + #If the facet type has a rule map, process the facets + if ($rule_map_by_type) { + + #Filter out any facet which has a value in the rule map + my @filtered_facets = (); + foreach my $facet ( @{ $facet_type->{facets} } ) { + my $facet_link_value = $facet->{facet_link_value}; + if ($facet_link_value) { + if ( !$rule_map_by_type->{$facet_link_value} ) { + push( @filtered_facets, $facet ); + } + } + } + $facet_type->{facets} = \@filtered_facets; + } + } + } + return $facets; +} + 1; diff --git a/Koha/SearchEngine/Zebra/Search.pm b/Koha/SearchEngine/Zebra/Search.pm index 1d504d384f..990471a690 100644 --- a/Koha/SearchEngine/Zebra/Search.pm +++ b/Koha/SearchEngine/Zebra/Search.pm @@ -60,9 +60,14 @@ This passes straight through to C4::Search::getRecords. =cut sub search_compat { - shift; # get rid of $self + shift; # get rid of $self - return C4::Search::getRecords(@_); + my ( $error, $results_hashref, $facets ) = C4::Search::getRecords(@_); + if ( C4::Context->interface eq 'opac' ) { + my $rules = C4::Context->yaml_preference('OpacHiddenItems'); + $facets = Koha::SearchEngine::Search->post_filter_opac_facets( { facets => $facets, rules => $rules } ); + } + return ( $error, $results_hashref, $facets ); } =head2 simple_search_compat diff --git a/t/Koha/SearchEngine/Search.t b/t/Koha/SearchEngine/Search.t index 9dba9f3202..cf34a6f55a 100755 --- a/t/Koha/SearchEngine/Search.t +++ b/t/Koha/SearchEngine/Search.t @@ -17,7 +17,7 @@ use Modern::Perl; -use Test::More tests => 1; +use Test::More tests => 2; use Test::Exception; use t::lib::Mocks; @@ -85,3 +85,76 @@ subtest "pagination_bar tests" => sub { is( @$PAGE_NUMBERS, 20, "If past first ten pages we show 20 pages" ); }; + +subtest "post_filter_opac_facets" => sub { + plan tests => 4; + + my $facets = _get_mock_facet_data(); + my $rules = { 'itype' => ['MP'] }; + + my $filtered_facets = Koha::SearchEngine::Search->post_filter_opac_facets( { facets => $facets, rules => $rules } ); + is( scalar @$filtered_facets, 2, 'Facet type length the same' ); + is( scalar @{ $filtered_facets->[0]->{facets} }, 3, 'author facet length the same' ); + is( scalar @{ $filtered_facets->[1]->{facets} }, 1, 'itype facet has been filtered' ); + is( $filtered_facets->[1]->{facets}->[0]->{facet_link_value}, 'BK', 'correct itype facet has been filtered' ); +}; + +sub _get_mock_facet_data { + my $facets = [ + { + 'type_label_Authors' => 1, + 'facets' => [ + { + 'facet_link_value' => 'Farley, David', + 'type_link_value' => 'author', + 'facet_title_value' => 'Farley, David', + 'facet_count' => 1, + 'facet_label_value' => 'Farley, David' + }, + { + 'facet_label_value' => 'Humble, Jez', + 'facet_count' => 1, + 'facet_title_value' => 'Humble, Jez', + 'type_link_value' => 'author', + 'facet_link_value' => 'Humble, Jez' + }, + { + 'facet_count' => 1, + 'facet_title_value' => 'Martin, Robert C.', + 'facet_label_value' => 'Martin, Robert C.', + 'type_link_value' => 'author', + 'facet_link_value' => 'Martin, Robert C.' + } + ], + 'av_cat' => '', + 'order' => 1, + 'label' => 'Authors', + 'type_id' => 'author_id', + 'type_link_value' => 'author' + }, + { + 'type_label_Item types' => 1, + 'facets' => [ + { + 'type_link_value' => 'itype', + 'facet_link_value' => 'BK', + 'facet_count' => 4, + 'facet_title_value' => 'BK', + 'facet_label_value' => 'Books' + }, + { + 'facet_title_value' => 'MP', + 'facet_count' => 1, + 'facet_label_value' => 'Maps', + 'type_link_value' => 'itype', + 'facet_link_value' => 'MP' + } + ], + 'order' => 2, + 'av_cat' => undef, + 'type_id' => 'itype_id', + 'type_link_value' => 'itype', + 'label' => 'Item types' + } + ]; +} -- 2.39.2