X-Git-Url: http://koha-dev.rot13.org:8081/gitweb/?a=blobdiff_plain;f=C4%2FSearch.pm;h=5d6816557498bb66df5285d271c0ae1dd80c7d41;hb=86a0a7d80b71908582dfc40c981734c5828112fc;hp=998e8e3504fc6cb58d56da567280f26a3bdcd4c9;hpb=167c74bfd386287783e101989b804077b1020369;p=srvgit diff --git a/C4/Search.pm b/C4/Search.pm index 998e8e3504..5d68165574 100644 --- a/C4/Search.pm +++ b/C4/Search.pm @@ -15,8 +15,7 @@ package C4::Search; # You should have received a copy of the GNU General Public License # along with Koha; if not, see . -use strict; -#use warnings; FIXME - Bug 2505 +use Modern::Perl; require Exporter; use C4::Context; use C4::Biblio; # GetMarcFromKohaField, GetBiblioData @@ -26,13 +25,14 @@ use Koha::Libraries; use Lingua::Stem; use C4::Search::PazPar2; use XML::Simple; -use C4::Members qw(GetHideLostItemsPreference); use C4::XSLT; use C4::Reserves; # GetReserveStatus use C4::Debug; use C4::Charset; use Koha::AuthorisedValues; +use Koha::ItemTypes; use Koha::Libraries; +use Koha::Patrons; use YAML; use URI::Escape; use Business::ISBN; @@ -160,7 +160,7 @@ sub FindDuplicate { =head2 SimpleSearch -( $error, $results, $total_hits ) = SimpleSearch( $query, $offset, $max_results, [@servers] ); +( $error, $results, $total_hits ) = SimpleSearch( $query, $offset, $max_results, [@servers], [%options] ); This function provides a simple search API on the bibliographic catalog @@ -172,6 +172,7 @@ This function provides a simple search API on the bibliographic catalog * @servers is optional. Defaults to biblioserver as found in koha-conf.xml * $offset - If present, represents the number of records at the beginning to omit. Defaults to 0 * $max_results - if present, determines the maximum number of records to fetch. undef is All. defaults to undef. + * %options is optional. (e.g. "skip_normalize" allows you to skip changing : to = ) =item C @@ -221,7 +222,7 @@ $template->param(result=>\@results); =cut sub SimpleSearch { - my ( $query, $offset, $max_results, $servers ) = @_; + my ( $query, $offset, $max_results, $servers, %options ) = @_; return ( 'No query entered', undef, undef ) unless $query; # FIXME hardcoded value. See catalog/search.pl & opac-search.pl too. @@ -243,12 +244,12 @@ sub SimpleSearch { eval { $zconns[$i] = C4::Context->Zconn( $servers[$i], 1 ); if ($QParser) { - $query =~ s/=/:/g; + $query =~ s/=/:/g unless $options{skip_normalize}; $QParser->parse( $query ); $query = $QParser->target_syntax($servers[$i]); $zoom_queries[$i] = new ZOOM::Query::PQF( $query, $zconns[$i]); } else { - $query =~ s/:/=/g; + $query =~ s/:/=/g unless $options{skip_normalize}; $zoom_queries[$i] = new ZOOM::Query::CCL2RPN( $query, $zconns[$i]); } $tmpresults[$i] = $zconns[$i]->search( $zoom_queries[$i] ); @@ -310,26 +311,27 @@ sub SimpleSearch { ( undef, $results_hashref, \@facets_loop ) = getRecords ( $koha_query, $simple_query, $sort_by_ref, $servers_ref, - $results_per_page, $offset, $expanded_facet, $branches,$itemtypes, - $query_type, $scan + $results_per_page, $offset, $branches, $itemtypes, + $query_type, $scan, $opac ); The all singing, all dancing, multi-server, asynchronous, scanning, searching, record nabbing, facet-building -See verbse embedded documentation. +See verbose embedded documentation. =cut sub getRecords { my ( $koha_query, $simple_query, $sort_by_ref, $servers_ref, - $results_per_page, $offset, $expanded_facet, $branches, - $itemtypes, $query_type, $scan, $opac + $results_per_page, $offset, $branches, $itemtypes, + $query_type, $scan, $opac ) = @_; my @servers = @$servers_ref; my @sort_by = @$sort_by_ref; + $offset = 0 if $offset < 0; # Initialize variables for the ZOOM connection and results object my $zconn; @@ -513,8 +515,6 @@ sub getRecords { keys %$facets_counter ) { - my $expandable; - my $number_of_facets; my @this_facets_array; for my $one_facet ( sort { @@ -524,87 +524,80 @@ sub getRecords { } keys %{ $facets_counter->{$link_value} } ) { - $number_of_facets++; - if ( ( $number_of_facets <= 5 ) - || ( $expanded_facet eq $link_value ) - || ( $facets_info->{$link_value}->{'expanded'} ) - ) - { - # Sanitize the link value : parenthesis, question and exclamation mark will cause errors with CCL - my $facet_link_value = $one_facet; - $facet_link_value =~ s/[()!?¡¿؟]/ /g; - - # fix the length that will display in the label, - my $facet_label_value = $one_facet; - my $facet_max_length = C4::Context->preference( - 'FacetLabelTruncationLength') - || 20; - $facet_label_value = - substr( $one_facet, 0, $facet_max_length ) - . "..." - if length($facet_label_value) > - $facet_max_length; - - # 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 = "*"; - } + my $facet_link_value = $one_facet; + $facet_link_value =~ s/[()!?¡¿؟]/ /g; + + # fix the length that will display in the label, + my $facet_label_value = $one_facet; + my $facet_max_length = C4::Context->preference( + 'FacetLabelTruncationLength') + || 20; + $facet_label_value = + substr( $one_facet, 0, $facet_max_length ) + . "..." + if length($facet_label_value) > + $facet_max_length; + + # 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'}; } - - # if it's a 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}; - } + else { + $facet_label_value = "*"; } + } - # also, if it's a location code, use the name instead of the code - if ( $link_value =~ /location/ ) { - # TODO Retrieve all authorised values at once, instead of 1 query per entry - my $av = Koha::AuthorisedValues->search({ category => 'LOC', authorised_value => $one_facet }); - $facet_label_value = $av->count ? $av->next->opac_description : ''; + # if it's a 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}; } + } - # but we're down with the whole label being in the link's title. - push @this_facets_array, - { - facet_count => - $facets_counter->{$link_value} - ->{$one_facet}, - facet_label_value => $facet_label_value, - facet_title_value => $one_facet, - facet_link_value => $facet_link_value, - type_link_value => $link_value, - } - if ($facet_label_value); + # also, if it's a location code, use the name instead of the code + if ( $link_value =~ /location/ ) { + # TODO Retrieve all authorised values at once, instead of 1 query per entry + my $av = Koha::AuthorisedValues->search({ category => 'LOC', authorised_value => $one_facet }); + $facet_label_value = $av->count ? $av->next->opac_description : ''; } - } - # handle expanded option - unless ( $facets_info->{$link_value}->{'expanded'} ) { - $expandable = 1 - if ( ( $number_of_facets > 5 ) - && ( $expanded_facet ne $link_value ) ); + # also, if it's a collection code, use the name instead of the code + if ( $link_value =~ /ccode/ ) { + # TODO Retrieve all authorised values at once, instead of 1 query per entry + my $av = Koha::AuthorisedValues->search({ category => 'CCODE', authorised_value => $one_facet }); + $facet_label_value = $av->count ? $av->next->opac_description : ''; + } + + # but we're down with the whole label being in the link's title. + push @this_facets_array, + { + facet_count => + $facets_counter->{$link_value} + ->{$one_facet}, + facet_label_value => $facet_label_value, + facet_title_value => $one_facet, + facet_link_value => $facet_link_value, + type_link_value => $link_value, + } + if ($facet_label_value); } + push @facets_loop, { type_link_value => $link_value, @@ -613,8 +606,6 @@ sub getRecords { . $facets_info->{$link_value}->{'label_value'} => 1, facets => \@this_facets_array, - expandable => $expandable, - expand => $link_value, } unless ( ( @@ -644,11 +635,9 @@ sub GetFacets { my $rs = shift; my $facets; - my $indexing_mode = C4::Context->config('zebra_bib_index_mode') // 'dom'; my $use_zebra_facets = C4::Context->config('use_zebra_facets') // 0; - if ( $indexing_mode eq 'dom' && - $use_zebra_facets ) { + if ( $use_zebra_facets ) { $facets = _get_facets_from_zebra( $rs ); } else { $facets = _get_facets_from_records( $rs ); @@ -844,7 +833,6 @@ sub _get_facets_info { for my $facet ( @$facets ) { $facets_info->{ $facet->{ idx } }->{ label_value } = $facet->{ label }; - $facets_info->{ $facet->{ idx } }->{ expanded } = $facet->{ expanded }; } return $facets_info; @@ -853,8 +841,8 @@ sub _get_facets_info { sub pazGetRecords { my ( $koha_query, $simple_query, $sort_by_ref, $servers_ref, - $results_per_page, $offset, $expanded_facet, $branches, - $query_type, $scan + $results_per_page, $offset, $branches, $query_type, + $scan ) = @_; #NOTE: Parameter $branches is not used here ! @@ -960,6 +948,9 @@ sub _build_stemmed_operand { require Lingua::Stem::Snowball ; my $stemmed_operand=q{}; + # Stemmer needs language + return $operand unless $lang; + # If operand contains a digit, it is almost certainly an identifier, and should # not be stemmed. This is particularly relevant for ISBNs and ISSNs, which # can contain the letter "X" - for example, _build_stemmend_operand would reduce @@ -1078,6 +1069,8 @@ sub getIndexes{ 'an', 'Any', 'at', + 'arl', + 'arp', 'au', 'aub', 'aud', @@ -1332,7 +1325,7 @@ sub _handle_exploding_index { ( $operators, $operands, $indexes, $limits, $sort_by, $scan, $lang ) = - buildQuery ( $operators, $operands, $indexes, $limits, $sort_by, $scan, $lang); + parseQuery ( $operators, $operands, $indexes, $limits, $sort_by, $scan, $lang); Shim function to ease the transition from buildQuery to a new QueryParser. This function is called at the beginning of buildQuery, and modifies @@ -1478,12 +1471,12 @@ sub buildQuery { @limits = grep {!/^$/} @limits; my $original_q = $q; # without available part unless ( grep { /^available$/ } @limits ) { - $q =~ s| and \( \( allrecords,AlwaysMatches:'' not onloan,AlwaysMatches:''\) and \(lost,st-numeric=0\) \)||; + $q =~ s| and \( \(allrecords,AlwaysMatches=''\) and \(not-onloan-count,st-numeric >= 1\) and \(lost,st-numeric=0\) \)||; $original_q = $q; } if ( @limits ) { if ( grep { /^available$/ } @limits ) { - $q .= q| and ( ( allrecords,AlwaysMatches:'' not onloan,AlwaysMatches:'') and (lost,st-numeric=0) )|; + $q .= q| and ( (allrecords,AlwaysMatches='') and (not-onloan-count,st-numeric >= 1) and (lost,st-numeric=0) )|; delete $limits['available']; } $q .= ' and '.join(' and ', @limits) if @limits; @@ -1529,7 +1522,7 @@ sub buildQuery { for ( my $i = 0 ; $i <= @operands ; $i++ ) { # COMBINE OPERANDS, INDEXES AND OPERATORS - if ( $operands[$i] ) { + if ( ($operands[$i] // '') ne '' ) { $operands[$i]=~s/^\s+//; # A flag to determine whether or not to add the index to the query @@ -1570,7 +1563,7 @@ sub buildQuery { $stemming = $auto_truncation = $weight_fields = $fuzzy_enabled = 0; } # ISBN,ISSN,Standard Number, don't need special treatment - elsif ( $index eq 'nb' || $index eq 'ns' ) { + elsif ( $index eq 'nb' || $index eq 'ns' || $index eq 'hi' ) { ( $stemming, $auto_truncation, $weight_fields, $fuzzy_enabled @@ -1674,7 +1667,7 @@ sub buildQuery { query_desc => $query_desc, operator => ($operators[ $i - 1 ]) ? $operators[ $i - 1 ] : '', parsed_operand => $operand, - original_operand => ($operands[$i]) ? $operands[$i] : '', + original_operand => $operands[$i] // '', index => $index, index_plus => $index_plus, indexes_set => $indexes_set, @@ -1697,7 +1690,7 @@ sub buildQuery { ## In English: ## all records not indexed in the onloan register (zebra) and all records with a value of lost equal to 0 $availability_limit .= -"( ( allrecords,AlwaysMatches='' not onloan,AlwaysMatches='') and (lost,st-numeric=0) )"; #or ( allrecords,AlwaysMatches='' not lost,AlwaysMatches='')) )"; +"( (allrecords,AlwaysMatches='') and (not-onloan-count,st-numeric >= 1) and (lost,st-numeric=0) )"; $limit_cgi .= "&limit=available"; $limit_desc .= ""; } @@ -1845,9 +1838,9 @@ sub searchResults { require C4::Items; - $search_context = 'opac' if !$search_context || $search_context ne 'intranet'; + $search_context->{'interface'} = 'opac' if !$search_context->{'interface'} || $search_context->{'interface'} ne 'intranet'; my ($is_opac, $hidelostitems); - if ($search_context eq 'opac') { + if ($search_context->{'interface'} eq 'opac') { $hidelostitems = C4::Context->preference('hidelostitems'); $is_opac = 1; } @@ -1862,21 +1855,22 @@ sub searchResults { { map { $_->{authorised_value} => $_->{lib} } Koha::AuthorisedValues->get_descriptions_by_koha_field( { frameworkcode => '', kohafield => 'items.location' } ) }; # get notforloan authorised value list (see $shelflocations FIXME) - my $av = Koha::MarcSubfieldStructures->search({ frameworkcode => '', kohafield => 'items.notforloan', authorised_value => { not => undef } }); + my $av = Koha::MarcSubfieldStructures->search({ frameworkcode => '', kohafield => 'items.notforloan', authorised_value => [ -and => {'!=' => undef }, {'!=' => ''}] }); my $notforloan_authorised_value = $av->count ? $av->next->authorised_value : undef; #Get itemtype hash - my %itemtypes = %{ GetItemTypes() }; + my $itemtypes = Koha::ItemTypes->search_with_localization; + my %itemtypes = map { $_->{itemtype} => $_ } @{ $itemtypes->unblessed }; #search item field code - my ($itemtag, undef) = &GetMarcFromKohaField( "items.itemnumber", "" ); + my ($itemtag, undef) = &GetMarcFromKohaField( "items.itemnumber" ); ## find column names of items related to MARC my %subfieldstosearch; my @columns = Koha::Database->new()->schema()->resultset('Item')->result_source->columns; for my $column ( @columns ) { my ( $tagfield, $tagsubfield ) = - &GetMarcFromKohaField( "items." . $column, "" ); + &GetMarcFromKohaField( "items." . $column ); if ( defined $tagsubfield ) { $subfieldstosearch{$column} = $tagsubfield; } @@ -1893,15 +1887,28 @@ sub searchResults { my $marcflavour = C4::Context->preference("marcflavour"); # We get the biblionumber position in MARC - my ($bibliotag,$bibliosubf)=GetMarcFromKohaField('biblio.biblionumber',''); + my ($bibliotag,$bibliosubf)=GetMarcFromKohaField( 'biblio.biblionumber' ); # set stuff for XSLT processing here once, not later again for every record we retrieved - my $interface = $search_context eq 'opac' ? 'OPAC' : ''; - my $xslsyspref = $interface . "XSLTResultsDisplay"; - my $xslfile = C4::Context->preference($xslsyspref); + my $xslfile; + my $xslsyspref; + if( $is_opac ){ + $xslsyspref = "OPACXSLTResultsDisplay"; + $xslfile = C4::Context->preference( $xslsyspref ); + } else { + $xslsyspref = "XSLTResultsDisplay"; + $xslfile = C4::Context->preference( $xslsyspref ) || "default"; + } my $lang = $xslfile ? C4::Languages::getlanguage() : undef; my $sysxml = $xslfile ? C4::XSLT::get_xslt_sysprefs() : undef; + my $userenv = C4::Context->userenv; + my $logged_in_user + = ( defined $userenv and $userenv->{number} ) + ? Koha::Patrons->find( $userenv->{number} ) + : undef; + my $patron_category_hide_lost_items = ($logged_in_user) ? $logged_in_user->category->hidelostitems : 0; + # loop through all of the records we've retrieved for ( my $i = $offset ; $i <= $times - 1 ; $i++ ) { @@ -1930,11 +1937,10 @@ sub searchResults { SetUTF8Flag($marcrecord); my $oldbiblio = TransformMarcToKoha( $marcrecord, $fw ); - $oldbiblio->{subtitle} = GetRecordValue('subtitle', $marcrecord, $fw); $oldbiblio->{result_number} = $i + 1; # add imageurl to itemtype if there is one - $oldbiblio->{imageurl} = getitemtypeimagelocation( $search_context, $itemtypes{ $oldbiblio->{itemtype} }->{imageurl} ); + $oldbiblio->{imageurl} = getitemtypeimagelocation( $search_context->{'interface'}, $itemtypes{ $oldbiblio->{itemtype} }->{imageurl} ); $oldbiblio->{normalized_upc} = GetNormalizedUPC( $marcrecord,$marcflavour); $oldbiblio->{normalized_ean} = GetNormalizedEAN( $marcrecord,$marcflavour); @@ -1946,8 +1952,9 @@ sub searchResults { $oldbiblio->{edition} = $oldbiblio->{editionstatement}; $oldbiblio->{description} = $itemtypes{ $oldbiblio->{itemtype} }->{translated_description}; # Build summary if there is one (the summary is defined in the itemtypes table) - # FIXME: is this used anywhere, I think it can be commented out? -- JF - if ( $itemtypes{ $oldbiblio->{itemtype} }->{summary} ) { + + # FIXME: this is only used in the deprecated non-XLST opac results + if ( !$xslfile && $is_opac && $itemtypes{ $oldbiblio->{itemtype} }->{summary} ) { my $summary = $itemtypes{ $oldbiblio->{itemtype} }->{summary}; my @fields = $marcrecord->fields(); @@ -1993,27 +2000,31 @@ sub searchResults { # Pull out the items fields my @fields = $marcrecord->field($itemtag); my $marcflavor = C4::Context->preference("marcflavour"); + # adding linked items that belong to host records - my $analyticsfield = '773'; - if ($marcflavor eq 'MARC21' || $marcflavor eq 'NORMARC') { - $analyticsfield = '773'; - } elsif ($marcflavor eq 'UNIMARC') { - $analyticsfield = '461'; - } - foreach my $hostfield ( $marcrecord->field($analyticsfield)) { - my $hostbiblionumber = $hostfield->subfield("0"); - my $linkeditemnumber = $hostfield->subfield("9"); - if(!$hostbiblionumber eq undef){ - my $hostbiblio = GetMarcBiblio($hostbiblionumber, 1); - my ($itemfield, undef) = GetMarcFromKohaField( 'items.itemnumber', GetFrameworkCode($hostbiblionumber) ); - if(!$hostbiblio eq undef){ - my @hostitems = $hostbiblio->field($itemfield); - foreach my $hostitem (@hostitems){ - if ($hostitem->subfield("9") eq $linkeditemnumber){ - my $linkeditem =$hostitem; - # append linked items if they exist - if (!$linkeditem eq undef){ - push (@fields, $linkeditem);} + if ( C4::Context->preference('EasyAnalyticalRecords') ) { + my $analyticsfield = '773'; + if ($marcflavor eq 'MARC21' || $marcflavor eq 'NORMARC') { + $analyticsfield = '773'; + } elsif ($marcflavor eq 'UNIMARC') { + $analyticsfield = '461'; + } + foreach my $hostfield ( $marcrecord->field($analyticsfield)) { + my $hostbiblionumber = $hostfield->subfield("0"); + my $linkeditemnumber = $hostfield->subfield("9"); + if( $hostbiblionumber ) { + my $hostbiblio = GetMarcBiblio({ + biblionumber => $hostbiblionumber, + embed_items => 1 }); + my ($itemfield, undef) = GetMarcFromKohaField( 'items.itemnumber' ); + if( $hostbiblio ) { + my @hostitems = $hostbiblio->field($itemfield); + foreach my $hostitem (@hostitems){ + if ($hostitem->subfield("9") eq $linkeditemnumber){ + my $linkeditem =$hostitem; + # append linked items if they exist + push @fields, $linkeditem if $linkeditem; + } } } } @@ -2066,7 +2077,7 @@ sub searchResults { next; } # hidden based on OpacHiddenItems syspref - my @hi = C4::Items::GetHiddenItemnumbers($item); + my @hi = C4::Items::GetHiddenItemnumbers({ items=> [ $item ], borcat => $search_context->{category} }); if (scalar @hi) { push @hiddenitems, @hi; $hideatopac_count++; @@ -2087,20 +2098,20 @@ sub searchResults { my $prefix = $item->{$hbranch} . '--' . $item->{location} . $item->{itype} . $item->{itemcallnumber}; # For each grouping of items (onloan, available, unavailable), we build a key to store relevant info about that item - my $userenv = C4::Context->userenv; if ( $item->{onloan} - && !( C4::Members::GetHideLostItemsPreference( $userenv->{'number'} ) && $item->{itemlost} ) ) + and $logged_in_user + and !( $patron_category_hide_lost_items and $item->{itemlost} ) ) { $onloan_count++; my $key = $prefix . $item->{onloan} . $item->{barcode}; - $onloan_items->{$key}->{due_date} = output_pref( { str => $item->{onloan}, dateonly => 1 } ); + $onloan_items->{$key}->{due_date} = $item->{onloan}; $onloan_items->{$key}->{count}++ if $item->{$hbranch}; $onloan_items->{$key}->{branchname} = $item->{branchname}; $onloan_items->{$key}->{location} = $shelflocations->{ $item->{location} }; $onloan_items->{$key}->{itemcallnumber} = $item->{itemcallnumber}; $onloan_items->{$key}->{description} = $item->{description}; $onloan_items->{$key}->{imageurl} = - getitemtypeimagelocation( $search_context, $itemtypes{ $item->{itype} }->{imageurl} ); + getitemtypeimagelocation( $search_context->{'interface'}, $itemtypes{ $item->{itype} }->{imageurl} ); # if something's checked out and lost, mark it as 'long overdue' if ( $item->{itemlost} ) { @@ -2190,21 +2201,21 @@ sub searchResults { $other_items->{$key}->{intransit} = ( $transfertwhen ne '' ) ? 1 : 0; $other_items->{$key}->{onhold} = ($reservestatus) ? 1 : 0; $other_items->{$key}->{notforloan} = GetAuthorisedValueDesc('','',$item->{notforloan},'','',$notforloan_authorised_value) if $notforloan_authorised_value and $item->{notforloan}; - $other_items->{$key}->{count}++ if $item->{$hbranch}; - $other_items->{$key}->{location} = $shelflocations->{ $item->{location} }; - $other_items->{$key}->{description} = $item->{description}; - $other_items->{$key}->{imageurl} = getitemtypeimagelocation( $search_context, $itemtypes{ $item->{itype} }->{imageurl} ); + $other_items->{$key}->{count}++ if $item->{$hbranch}; + $other_items->{$key}->{location} = $shelflocations->{ $item->{location} }; + $other_items->{$key}->{description} = $item->{description}; + $other_items->{$key}->{imageurl} = getitemtypeimagelocation( $search_context->{'interface'}, $itemtypes{ $item->{itype} }->{imageurl} ); } # item is available else { $can_place_holds = 1; $available_count++; - $available_items->{$prefix}->{count}++ if $item->{$hbranch}; - foreach (qw(branchname itemcallnumber description)) { - $available_items->{$prefix}->{$_} = $item->{$_}; - } - $available_items->{$prefix}->{location} = $shelflocations->{ $item->{location} }; - $available_items->{$prefix}->{imageurl} = getitemtypeimagelocation( $search_context, $itemtypes{ $item->{itype} }->{imageurl} ); + $available_items->{$prefix}->{count}++ if $item->{$hbranch}; + foreach (qw(branchname itemcallnumber description)) { + $available_items->{$prefix}->{$_} = $item->{$_}; + } + $available_items->{$prefix}->{location} = $shelflocations->{ $item->{location} }; + $available_items->{$prefix}->{imageurl} = getitemtypeimagelocation( $search_context->{'interface'}, $itemtypes{ $item->{itype} }->{imageurl} ); } } } # notforloan, item level and biblioitem level @@ -2232,7 +2243,6 @@ sub searchResults { # we fetched the sysprefs already before the loop through all retrieved record! if (!$scan && $xslfile) { $oldbiblio->{XSLTResultsRecord} = XSLTParse4Display($oldbiblio->{biblionumber}, $marcrecord, $xslsyspref, 1, \@hiddenitems, $sysxml, $xslfile, $lang); - # the last parameter tells Koha to clean up the problematic ampersand entities that Zebra outputs } # if biblio level itypes are used and itemtype is notforloan, it can't be reserved either @@ -2242,7 +2252,6 @@ sub searchResults { } } $oldbiblio->{norequests} = 1 unless $can_place_holds; - $oldbiblio->{itemsplural} = 1 if $items_count > 1; $oldbiblio->{items_count} = $items_count; $oldbiblio->{available_items_loop} = \@available_items_loop; $oldbiblio->{onloan_items_loop} = \@onloan_items_loop; @@ -2289,6 +2298,8 @@ sub searchResults { $oldbiblio->{'alternateholdings_count'} = $alternateholdingscount; } + $oldbiblio->{biblio_object} = Koha::Biblios->find( $oldbiblio->{biblionumber} ); + push( @newresults, $oldbiblio ); } @@ -2499,7 +2510,7 @@ sub new_record_from_zebra { # Set the default indexing modes my $search_engine = C4::Context->preference("SearchEngine"); if ($search_engine eq 'Elasticsearch') { - return $raw_data; + return ref $raw_data eq 'MARC::Record' ? $raw_data : MARC::Record->new_from_xml( $raw_data, 'UTF-8' ); } my $index_mode = ( $server eq 'biblioserver' ) ? C4::Context->config('zebra_bib_index_mode') // 'dom'