X-Git-Url: http://koha-dev.rot13.org:8081/gitweb/?a=blobdiff_plain;f=C4%2FSearch.pm;h=04ce112a544b5117e0fe3f37fd29f4c6569c57f9;hb=5207699f98612193c47b3ef7a3a3b6da5444b859;hp=ab7cb5972188feb5dabb20bd302e08ae1dede1ca;hpb=499c694daf408571cc8370b4c20568336ba35cde;p=koha_fer diff --git a/C4/Search.pm b/C4/Search.pm index ab7cb59721..04ce112a54 100644 --- a/C4/Search.pm +++ b/C4/Search.pm @@ -31,8 +31,10 @@ use C4::Branch; use C4::Reserves; # CheckReserves use C4::Debug; use C4::Items; +use C4::Charset; use YAML; use URI::Escape; +use Business::ISBN; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $DEBUG); @@ -68,9 +70,8 @@ This module provides searching functions for Koha's bibliographic databases &NZgetRecords &AddSearchHistory &GetDistinctValues - &BiblioAddAuthorities + &enabled_staff_search_views ); -#FIXME: i had to add BiblioAddAuthorities here because in Biblios.pm it caused circular dependencies (C4::Search uses C4::Biblio, and BiblioAddAuthorities uses SimpleSearch from C4::Search) # make all your functions, whether exported or not; @@ -842,6 +843,7 @@ sub getIndexes{ 'Authority-Number', 'authtype', 'bc', + 'Bib-level', 'biblionumber', 'bio', 'biography', @@ -1071,15 +1073,14 @@ sub buildQuery { my $stopwords_removed; # flag to determine if stopwords have been removed - my $cclq; + my $cclq = 0; my $cclindexes = getIndexes(); - if( $query !~ /\s*ccl=/ ){ - for my $index (@$cclindexes){ - if($query =~ /($index)(,?\w)*[:=]/){ - $cclq = 1; - } + if ( $query !~ /\s*ccl=/ ) { + while ( !$cclq && $query =~ /(?:^|\W)([\w-]+)(,[\w-]+)*[:=]/g ) { + my $dx = lc($1); + $cclq = grep { lc($_) eq $dx } @$cclindexes; } - $query = "ccl=$query" if($cclq); + $query = "ccl=$query" if $cclq; } # for handling ccl, cql, pqf queries in diagnostic mode, skip the rest of the steps @@ -1413,11 +1414,16 @@ Format results in a form suitable for passing to the template # IMO this subroutine is pretty messy still -- it's responsible for # building the HTML output for the template sub searchResults { - my ( $search_context, $searchdesc, $hits, $results_per_page, $offset, $scan, @marcresults, $hidelostitems ) = @_; + my ( $search_context, $searchdesc, $hits, $results_per_page, $offset, $scan, $marcresults ) = @_; my $dbh = C4::Context->dbh; my @newresults; - $search_context = 'opac' unless $search_context eq 'opac' or $search_context eq 'intranet'; + $search_context = 'opac' if !$search_context || $search_context ne 'intranet'; + my ($is_opac, $hidelostitems); + if ($search_context eq 'opac') { + $hidelostitems = C4::Context->preference('hidelostitems'); + $is_opac = 1; + } #Build branchnames hash #find branchname @@ -1480,12 +1486,11 @@ sub searchResults { my $marcflavour = C4::Context->preference("marcflavour"); # We get the biblionumber position in MARC my ($bibliotag,$bibliosubf)=GetMarcFromKohaField('biblio.biblionumber',''); - my $fw; # loop through all of the records we've retrieved for ( my $i = $offset ; $i <= $times - 1 ; $i++ ) { - my $marcrecord = MARC::File::USMARC::decode( $marcresults[$i] ); - $fw = $scan + my $marcrecord = MARC::File::USMARC::decode( $marcresults->[$i] ); + my $fw = $scan ? undef : $bibliotag < 10 ? GetFrameworkCode($marcrecord->field($bibliotag)->data) @@ -1559,6 +1564,33 @@ 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);} + } + } + } + } + } # Setting item statuses for display my @available_items_loop; @@ -1576,18 +1608,18 @@ sub searchResults { my $other_count = 0; my $wthdrawn_count = 0; my $itemlost_count = 0; + my $hideatopac_count = 0; my $itembinding_count = 0; my $itemdamaged_count = 0; my $item_in_transit_count = 0; my $can_place_holds = 0; - my $item_onhold_count = 0; + my $item_onhold_count = 0; my $items_count = scalar(@fields); - my $maxitems = - ( C4::Context->preference('maxItemsinSearchResults') ) - ? C4::Context->preference('maxItemsinSearchResults') - 1 - : 1; + my $maxitems_pref = C4::Context->preference('maxItemsinSearchResults'); + my $maxitems = $maxitems_pref ? $maxitems_pref - 1 : 1; # loop through every item + my @hiddenitems; foreach my $field (@fields) { my $item; @@ -1597,9 +1629,11 @@ sub searchResults { } # Hidden items - my @items = ($item); - my (@hiddenitems) = GetHiddenItemnumbers(@items); - $item->{'hideatopac'} = 1 if (@hiddenitems); + if ($is_opac) { + my @hi = GetHiddenItemnumbers($item); + $item->{'hideatopac'} = @hi; + push @hiddenitems, @hi; + } my $hbranch = C4::Context->preference('HomeOrHoldingBranch') eq 'homebranch' ? 'homebranch' : 'holdingbranch'; my $otherbranch = C4::Context->preference('HomeOrHoldingBranch') eq 'homebranch' ? 'holdingbranch' : 'homebranch'; @@ -1646,7 +1680,7 @@ sub searchResults { my ($transfertfrom, $transfertto); # is item on the reserve shelf? - my $reservestatus = 0; + my $reservestatus = ''; my $reserveitem; unless ($item->{wthdrawn} @@ -1668,10 +1702,10 @@ sub searchResults { # should map transit status to record indexed in Zebra. # ($transfertwhen, $transfertfrom, $transfertto) = C4::Circulation::GetTransfers($item->{itemnumber}); - ($reservestatus, $reserveitem) = C4::Reserves::CheckReserves($item->{itemnumber}); + ($reservestatus, $reserveitem, undef) = C4::Reserves::CheckReserves($item->{itemnumber}); } - # item is withdrawn, lost or damaged + # item is withdrawn, lost, damaged, not for loan, reserved or in transit if ( $item->{wthdrawn} || $item->{itemlost} || $item->{damaged} @@ -1683,9 +1717,19 @@ sub searchResults { $wthdrawn_count++ if $item->{wthdrawn}; $itemlost_count++ if $item->{itemlost}; $itemdamaged_count++ if $item->{damaged}; + $hideatopac_count++ if $item->{hideatopac}; $item_in_transit_count++ if $transfertwhen ne ''; $item_onhold_count++ if $reservestatus eq 'Waiting'; $item->{status} = $item->{wthdrawn} . "-" . $item->{itemlost} . "-" . $item->{damaged} . "-" . $item->{notforloan}; + + # can place hold on item ? + if ((!$item->{damaged} || C4::Context->preference('AllowHoldsOnDamagedItems')) + && !$item->{itemlost} + && !$item->{withdrawn} + ) { + $can_place_holds = 1; + } + $other_count++; my $key = $prefix . $item->{status}; @@ -1712,11 +1756,11 @@ sub searchResults { } } } # notforloan, item level and biblioitem level + if ($items_count > 0) { + next if $is_opac && $hideatopac_count >= $items_count; + next if $hidelostitems && $itemlost_count >= $items_count; + } my ( $availableitemscount, $onloanitemscount, $otheritemscount ); - $maxitems = - ( C4::Context->preference('maxItemsinSearchResults') ) - ? C4::Context->preference('maxItemsinSearchResults') - 1 - : 1; for my $key ( sort keys %$onloan_items ) { (++$onloanitemscount > $maxitems) and last; push @onloan_items_loop, $onloan_items->{$key}; @@ -1734,13 +1778,11 @@ sub searchResults { use C4::Charset; SetUTF8Flag($marcrecord); $debug && warn $marcrecord->as_formatted; - if (!$scan && $search_context eq 'opac' && C4::Context->preference("OPACXSLTResultsDisplay")) { - # FIXME note that XSLTResultsDisplay (use of XSLT to format staff interface bib search results) - # is not implemented yet - $oldbiblio->{XSLTResultsRecord} = XSLTParse4Display($oldbiblio->{biblionumber}, $marcrecord, 'Results', - $search_context, 1); - # the last parameter tells Koha to clean up the problematic ampersand entities that Zebra outputs - + my $interface = $search_context eq 'opac' ? 'OPAC' : ''; + if (!$scan && C4::Context->preference($interface . "XSLTResultsDisplay")) { + $oldbiblio->{XSLTResultsRecord} = XSLTParse4Display($oldbiblio->{biblionumber}, $marcrecord, 'Results', + $search_context, 1, \@hiddenitems); + # 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 @@ -1767,8 +1809,8 @@ sub searchResults { $oldbiblio->{intransitcount} = $item_in_transit_count; $oldbiblio->{onholdcount} = $item_onhold_count; $oldbiblio->{orderedcount} = $ordered_count; - $oldbiblio->{isbn} =~ - s/-//g; # deleting - in isbn to enable amazon content + # deleting - in isbn to enable amazon content + $oldbiblio->{isbn} =~ s/-//g; if (C4::Context->preference("AlternateHoldingsField") && $items_count == 0) { my $fieldspec = C4::Context->preference("AlternateHoldingsField"); @@ -1798,10 +1840,7 @@ sub searchResults { $oldbiblio->{'alternateholdings_count'} = $alternateholdingscount; } - push( @newresults, $oldbiblio ) - if(not $hidelostitems - or (($items_count > $itemlost_count ) - && $hidelostitems)); + push( @newresults, $oldbiblio ); } return @newresults; @@ -2592,7 +2631,15 @@ $template->param ( MYLOOP => C4::Search::z3950_search_args($searchscalar) ) sub z3950_search_args { my $bibrec = shift; - $bibrec = { title => $bibrec } if !ref $bibrec; + my $isbn = Business::ISBN->new($bibrec); + + if (defined $isbn && $isbn->is_valid) + { + $bibrec = { isbn => $bibrec } if !ref $bibrec; + } + else { + $bibrec = { title => $bibrec } if !ref $bibrec; + } my $array = []; for my $field (qw/ lccn isbn issn title author dewey subject /) { @@ -2602,105 +2649,6 @@ sub z3950_search_args { return $array; } -=head2 BiblioAddAuthorities - -( $countlinked, $countcreated ) = BiblioAddAuthorities($record, $frameworkcode); - -this function finds the authorities linked to the biblio - * search in the authority DB for the same authid (in $9 of the biblio) - * search in the authority DB for the same 001 (in $3 of the biblio in UNIMARC) - * search in the authority DB for the same values (exactly) (in all subfields of the biblio) -OR adds a new authority record - -=over 2 - -=item C - - * $record is the MARC record in question (marc blob) - * $frameworkcode is the bibliographic framework to use (if it is "" it uses the default framework) - -=item C - - * $countlinked is the number of authorities records that are linked to this authority - * $countcreated - -=item C - * I had to add this to Search.pm (instead of the logical Biblio.pm) because of a circular dependency (this sub uses SimpleSearch, and Search.pm uses Biblio.pm) - -=back - -=cut - - -sub BiblioAddAuthorities{ - my ( $record, $frameworkcode ) = @_; - my $dbh=C4::Context->dbh; - my $query=$dbh->prepare(qq| -SELECT authtypecode,tagfield -FROM marc_subfield_structure -WHERE frameworkcode=? -AND (authtypecode IS NOT NULL AND authtypecode<>\"\")|); -# SELECT authtypecode,tagfield -# FROM marc_subfield_structure -# WHERE frameworkcode=? -# AND (authtypecode IS NOT NULL OR authtypecode<>\"\")|); - $query->execute($frameworkcode); - my ($countcreated,$countlinked); - while (my $data=$query->fetchrow_hashref){ - foreach my $field ($record->field($data->{tagfield})){ - next if ($field->subfield('3')||$field->subfield('9')); - # No authorities id in the tag. - # Search if there is any authorities to link to. - my $query='at='.$data->{authtypecode}.' '; - map {$query.= ' and he,ext="'.$_->[1].'"' if ($_->[0]=~/[A-z]/)} $field->subfields(); - my ($error, $results, $total_hits)=SimpleSearch( $query, undef, undef, [ "authorityserver" ] ); - # there is only 1 result - if ( $error ) { - warn "BIBLIOADDSAUTHORITIES: $error"; - return (0,0) ; - } - if ( @{$results} == 1 ) { - my $marcrecord = MARC::File::USMARC::decode($results->[0]); - $field->add_subfields('9'=>$marcrecord->field('001')->data); - $countlinked++; - } elsif ( @{$results} > 1 ) { - #More than One result - #This can comes out of a lack of a subfield. -# my $marcrecord = MARC::File::USMARC::decode($results->[0]); -# $record->field($data->{tagfield})->add_subfields('9'=>$marcrecord->field('001')->data); - $countlinked++; - } else { - #There are no results, build authority record, add it to Authorities, get authid and add it to 9 - ###NOTICE : This is only valid if a subfield is linked to one and only one authtypecode - ###NOTICE : This can be a problem. We should also look into other types and rejected forms. - my $authtypedata=C4::AuthoritiesMarc::GetAuthType($data->{authtypecode}); - next unless $authtypedata; - my $marcrecordauth=MARC::Record->new(); - my $authfield=MARC::Field->new($authtypedata->{auth_tag_to_report},'','',"a"=>"".$field->subfield('a')); - map { $authfield->add_subfields($_->[0]=>$_->[1]) if ($_->[0]=~/[A-z]/ && $_->[0] ne "a" )} $field->subfields(); - $marcrecordauth->insert_fields_ordered($authfield); - - # bug 2317: ensure new authority knows it's using UTF-8; currently - # only need to do this for MARC21, as MARC::Record->as_xml_record() handles - # automatically for UNIMARC (by not transcoding) - # FIXME: AddAuthority() instead should simply explicitly require that the MARC::Record - # use UTF-8, but as of 2008-08-05, did not want to introduce that kind - # of change to a core API just before the 3.0 release. - if (C4::Context->preference('marcflavour') eq 'MARC21') { - SetMarcUnicodeFlag($marcrecordauth, 'MARC21'); - } - -# warn "AUTH RECORD ADDED : ".$marcrecordauth->as_formatted; - - my $authid=AddAuthority($marcrecordauth,'',$data->{authtypecode}); - $countcreated++; - $field->add_subfields('9'=>$authid); - } - } - } - return ($countlinked,$countcreated); -} - =head2 GetDistinctValues($field); C<$field> is a reference to the fields array