|
diff --git a/lib/C4/Search.pm b/lib/C4/Search.pm |
|
index e2de365..34012ff 100644 |
|
--- a/lib/C4/Search.pm |
|
+++ b/lib/C4/Search.pm |
|
@@ -55,6 +55,7 @@ BEGIN { |
|
new_record_from_zebra |
|
z3950_search_args |
|
getIndexes |
|
+ GetFacets |
|
); |
|
} |
|
|
|
diff --git a/lib/Koha/Z3950Responder.pm b/lib/Koha/Z3950Responder.pm |
|
index 3e1f1d2..c560d84 100644 |
|
--- a/lib/Koha/Z3950Responder.pm |
|
+++ b/lib/Koha/Z3950Responder.pm |
|
@@ -187,6 +187,10 @@ sub search_handler { |
|
if $SearchEngine ne C4::Context->preference('SearchEngine'); |
|
|
|
$args->{HANDLE}->search_handler($args); |
|
+ |
|
+ my $facets_counter = $args->{HANDLE}->{resultsets}->{default}->{facets_counter}; |
|
+ my $facets_response = my_facets_response($args->{INPUTFACETS}, $facets_counter); |
|
+ $args->{OUTPUTFACETS} = $facets_response; |
|
} |
|
|
|
=head3 fetch_handler |
|
@@ -213,4 +217,119 @@ sub close_handler { |
|
$args->{HANDLE}->close_handler( $args ); |
|
} |
|
|
|
+=head3 my_facets_response |
|
+ |
|
+This subroutine is called from the search handler. It takes a |
|
+Net::Z3950::FacetList array as input, and returns an array of |
|
+the same type. |
|
+ |
|
+For more information on facets in a Z39.50/SRU context, see these links: |
|
+https://docs.oasis-open.org/search-ws/searchRetrieve/v1.0/os/part3-sru2.0/searchRetrieve-v1.0-os-part3-sru2.0.html#_Toc324162452 |
|
+https://metacpan.org/dist/Net-Z3950-SimpleServer/view/SimpleServer.pm#Facets |
|
+https://software.indexdata.com/yaz/doc/facets.html |
|
+ |
|
+The code for this function was inspired by the sample `ztest.pl` |
|
+program that ships with the Net::Z3950::SimpleServer distribution, |
|
+and was adapted to suit Koha's facet configuration. |
|
+ |
|
+=cut |
|
+ |
|
+sub my_facets_response { |
|
+ my $facets_request = shift; |
|
+ my $facets_counter = shift; |
|
+ |
|
+ # Generate facets response. We use $facets_request as basis. |
|
+ my $zfacetlist = []; |
|
+ bless $zfacetlist, 'Net::Z3950::FacetList'; |
|
+ my $i = 0; |
|
+ foreach my $x (@$facets_request) { |
|
+ my $facetname = "unknown"; |
|
+ my $sortorder = 0; |
|
+ my $limit = 5; |
|
+ my $offset = 1; |
|
+ foreach my $attr (@{$x->{'attributes'}}) { |
|
+ my $type = $attr->{'attributeType'}; |
|
+ my $value = $attr->{'attributeValue'}; |
|
+ if ($type == 1) { $facetname = $value; } |
|
+ if ($type == 2) { $sortorder = $value; } # FIXME not implemented yet |
|
+ if ($type == 3) { $limit = $value; } |
|
+ if ($type == 4) { $offset = $value; } # FIXME not implemented yet |
|
+ } |
|
+ if ( $facetname ne 'unknown' ) { |
|
+ my $zfacetfield = {}; |
|
+ bless $zfacetfield, 'Net::Z3950::FacetField'; |
|
+ if ($limit > 0) { |
|
+ $zfacetlist->[$i++] = $zfacetfield; |
|
+ } |
|
+ my $zattributes = []; |
|
+ bless $zattributes, 'Net::Z3950::RPN::Attributes'; |
|
+ $zfacetfield->{'attributes'} = $zattributes; |
|
+ my $zattribute = {}; |
|
+ bless $zattribute, 'Net::Z3950::RPN::Attribute'; |
|
+ $zattribute->{'attributeType'} = 1; |
|
+ $zattribute->{'attributeValue'} = $facetname; |
|
+ $zattributes->[0] = $zattribute; |
|
+ my $zfacetterms = []; |
|
+ bless $zfacetterms, 'Net::Z3950::FacetTerms'; |
|
+ $zfacetfield->{'terms'} = $zfacetterms; |
|
+ } |
|
+ foreach my $key_idx ( @$facets_counter ) { |
|
+ if ( $key_idx->{type_link_value} eq $facetname ) { |
|
+ my $facets_count = scalar @{ $key_idx->{facets} }; |
|
+ my $j = 0; |
|
+ foreach my $data ( @{ $key_idx->{facets} } ) { |
|
+ if ( $j < $limit ) { |
|
+ my $term_value = $data->{facet_label_value}; |
|
+ my $term_count = $data->{facet_count}; |
|
+ my $zfacetfield = {}; |
|
+ bless $zfacetfield, 'Net::Z3950::FacetField'; |
|
+ if ($limit > 0) { |
|
+ $zfacetlist->[$i++] = $zfacetfield; |
|
+ } |
|
+ my $zfacetterms = []; |
|
+ bless $zfacetterms, 'Net::Z3950::FacetTerms'; |
|
+ $zfacetfield->{'terms'} = $zfacetterms; |
|
+ my $zfacetterm = {}; |
|
+ bless $zfacetterm, 'Net::Z3950::FacetTerm'; |
|
+ $zfacetterm->{'term'} = $term_value; |
|
+ $zfacetterm->{'count'} = $term_count; |
|
+ $zfacetterms->[$j++] = $zfacetterm; |
|
+ } |
|
+ } |
|
+ } |
|
+ if ( $facetname eq 'unknown' ) { |
|
+ my $zfacetfield = {}; |
|
+ bless $zfacetfield, 'Net::Z3950::FacetField'; |
|
+ if ($limit > 0) { |
|
+ $zfacetlist->[$i++] = $zfacetfield; |
|
+ } |
|
+ my $zattributes = []; |
|
+ bless $zattributes, 'Net::Z3950::RPN::Attributes'; |
|
+ $zfacetfield->{'attributes'} = $zattributes; |
|
+ my $zattribute = {}; |
|
+ bless $zattribute, 'Net::Z3950::RPN::Attribute'; |
|
+ $zattribute->{'attributeType'} = 1; |
|
+ $zattribute->{'attributeValue'} = $key_idx->{type_link_value}; |
|
+ $zattributes->[0] = $zattribute; |
|
+ my $zfacetterms = []; |
|
+ bless $zfacetterms, 'Net::Z3950::FacetTerms'; |
|
+ $zfacetfield->{'terms'} = $zfacetterms; |
|
+ my $k = 0; |
|
+ foreach my $data ( @{ $key_idx->{facets} } ) { |
|
+ if ( $k < $limit ) { |
|
+ my $term_value = $data->{facet_label_value}; |
|
+ my $term_count = $data->{facet_count}; |
|
+ my $zfacetterm = {}; |
|
+ bless $zfacetterm, 'Net::Z3950::FacetTerm'; |
|
+ $zfacetterm->{'term'} = $term_value; |
|
+ $zfacetterm->{'count'} = $term_count; |
|
+ $zfacetterms->[$k++] = $zfacetterm; |
|
+ } |
|
+ } |
|
+ } |
|
+ } |
|
+ } |
|
+ return $zfacetlist; |
|
+} |
|
+ |
|
1; |
|
diff --git a/lib/Koha/Z3950Responder/ZebraSession.pm b/lib/Koha/Z3950Responder/ZebraSession.pm |
|
index 302472b..2459eca 100644 |
|
--- a/lib/Koha/Z3950Responder/ZebraSession.pm |
|
+++ b/lib/Koha/Z3950Responder/ZebraSession.pm |
|
@@ -25,6 +25,9 @@ use Koha::Logger; |
|
|
|
use ZOOM; |
|
|
|
+use C4::Search qw( GetFacets ); |
|
+use C4::Koha qw( getFacets ); |
|
+ |
|
=head1 NAME |
|
|
|
Koha::Z3950Responder::ZebraSession |
|
@@ -60,6 +63,9 @@ sub start_search { |
|
|
|
$results = $connection->search_pqf( $args->{QUERY} ); |
|
|
|
+ my $elementSetName = $results->option( 'elementSetName' ); |
|
+ $results->option( elementSetName => $elementSetName ); |
|
+ |
|
$self->log_debug(' retry successful') if ($in_retry); |
|
}; |
|
if ($@) { |
|
@@ -75,12 +81,97 @@ sub start_search { |
|
} |
|
|
|
my $hits = $results ? $results->size() : -1; |
|
+ |
|
+ my $facets_counter = {}; |
|
+ my $facets_info = {}; |
|
+ my $facets = getFacets(); |
|
+ my @facets_loop; |
|
+ |
|
+ $facets_counter = GetFacets( $results ); |
|
+ |
|
+ for my $facet ( @$facets ) { |
|
+ $facets_info->{ $facet->{ idx } }->{ label_value } = $facet->{ label }; |
|
+ } |
|
+ |
|
+ my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search_with_localization->unblessed } }; |
|
+ my $branches = Koha::Libraries->search( {}, { order_by => ['branchname'] } )->unblessed; |
|
+ |
|
+ for my $link_value ( sort { $a cmp $b } keys %$facets_counter ) { |
|
+ my @this_facets_array; |
|
+ for my $one_facet ( sort { $facets_counter->{$link_value}->{$b} <=> |
|
+ $facets_counter->{$link_value}->{$a} |
|
+ } keys %{ $facets_counter->{$link_value} } ) { |
|
+ my $facet_label_value = $one_facet; |
|
+ |
|
+ # if it's a branch, label by the name, not the code |
|
+ if ( $link_value =~ /branch/ ) { |
|
+ if ( defined $branches |
|
+ && ref($branches) eq "HASH" |
|
+ && defined $branches->{$one_facet} |
|
+ && ref( $branches->{$one_facet} ) eq "HASH" ) { |
|
+ $facet_label_value = $branches->{$one_facet}->{'branchname'}; |
|
+ } else { |
|
+ $facet_label_value = "*"; |
|
+ } |
|
+ } |
|
+ |
|
+ # if it's an itemtype, label by the name, not the code |
|
+ if ( $link_value =~ /itype/ ) { |
|
+ if ( defined $itemtypes |
|
+ && ref($itemtypes) eq "HASH" |
|
+ && defined $itemtypes->{$one_facet} |
|
+ && ref( $itemtypes->{$one_facet} ) eq "HASH" ) { |
|
+ $facet_label_value = $itemtypes->{$one_facet}->{translated_description}; |
|
+ } |
|
+ } |
|
+ |
|
+ # if it's a location code, use the name instead of the code |
|
+ if ( $link_value =~ /location/ ) { |
|
+ my $av = Koha::AuthorisedValues->search({ category => 'LOC', authorised_value => $one_facet }); |
|
+ $facet_label_value = $av->count ? $av->next->opac_description : ''; |
|
+ } |
|
+ |
|
+ # if it's a collection code, use the name instead of the code |
|
+ if ( $link_value =~ /ccode/ ) { |
|
+ my $av = Koha::AuthorisedValues->search({ category => 'CCODE', authorised_value => $one_facet }); |
|
+ $facet_label_value = $av->count ? $av->next->opac_description : ''; |
|
+ } |
|
+ |
|
+ push @this_facets_array, { |
|
+ facet_count => $facets_counter->{$link_value}->{$one_facet}, |
|
+ facet_label_value => $facet_label_value, |
|
+ type_link_value => $link_value, |
|
+ } if ($facet_label_value); |
|
+ } |
|
+ |
|
+ push @facets_loop, { |
|
+ type_link_value => $link_value, |
|
+ type_id => $link_value . "_id", |
|
+ facets => \@this_facets_array, |
|
+ } unless ( ( $facets_info->{$link_value}->{'label_value'} =~ /Libraries/ ) |
|
+ and ( Koha::Libraries->search->count == 1 ) ); |
|
+ } |
|
+ |
|
+ # This sorts the facets into alphabetical order |
|
+ if (@facets_loop) { |
|
+ foreach my $f (@facets_loop) { |
|
+ if( C4::Context->preference('FacetOrder') eq 'Alphabetical' ) { |
|
+ $f->{facets} = |
|
+ [ sort { uc($a->{facet_label_value}) cmp |
|
+ uc($b->{facet_label_value}) |
|
+ } @{ $f->{facets} } |
|
+ ]; |
|
+ } |
|
+ } |
|
+ } |
|
+ |
|
my $resultset = { |
|
database => $database, |
|
connection => $connection, |
|
results => $results, |
|
query => $args->{QUERY}, |
|
- hits => $hits |
|
+ hits => $hits, |
|
+ facets_counter => \@facets_loop, |
|
}; |
|
|
|
return ( $resultset, $hits ); |