Adding autotruncation
[koha.git] / C4 / Search.pm
index 8499c00..d78f407 100644 (file)
@@ -26,6 +26,7 @@ use C4::Search::PazPar2;
 use XML::Simple;
 use C4::Dates qw(format_date);
 use C4::XSLT;
+use C4::Branch;
 
 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $DEBUG);
 
@@ -53,44 +54,16 @@ This module provides searching functions for Koha's bibliographic databases
 
 @ISA    = qw(Exporter);
 @EXPORT = qw(
-  &findseealso
   &FindDuplicate
   &SimpleSearch
   &searchResults
   &getRecords
   &buildQuery
   &NZgetRecords
-  &ModBiblios
 );
 
 # make all your functions, whether exported or not;
 
-=head2 findseealso($dbh,$fields);
-
-C<$dbh> is a link to the DB handler.
-
-use C4::Context;
-my $dbh =C4::Context->dbh;
-
-C<$fields> is a reference to the fields array
-
-This function modifies the @$fields array and adds related fields to search on.
-
-FIXME: this function is probably deprecated in Koha 3
-
-=cut
-
-sub findseealso {
-    my ( $dbh, $fields ) = @_;
-    my $tagslib = GetMarcStructure(1);
-    for ( my $i = 0 ; $i <= $#{$fields} ; $i++ ) {
-        my ($tag)      = substr( @$fields[$i], 1, 3 );
-        my ($subfield) = substr( @$fields[$i], 4, 1 );
-        @$fields[$i] .= ',' . $tagslib->{$tag}->{$subfield}->{seealso}
-          if ( $tagslib->{$tag}->{$subfield}->{seealso} );
-    }
-}
-
 =head2 FindDuplicate
 
 ($biblionumber,$biblionumber,$title) = FindDuplicate($record);
@@ -224,7 +197,7 @@ sub SimpleSearch {
         my $search_result =
           (      $result->{hits}
               && $result->{hits} > 0 ? $result->{'RECORDS'} : [] );
-        return ( undef, $search_result, scalar($search_result) );
+        return ( undef, $search_result, scalar($result->{hits}) );
     }
     else {
         # FIXME hardcoded value. See catalog/search.pl & opac-search.pl too.
@@ -347,40 +320,21 @@ sub getRecords {
 
         # Check if we've got a query_type defined, if so, use it
         eval {
-            if ($query_type)
-            {
-                if ( $query_type =~ /^ccl/ ) {
-                    $query_to_use =~
-                      s/\:/\=/g;    # change : to = last minute (FIXME)
-                    $results[$i] =
-                      $zconns[$i]->search(
-                        new ZOOM::Query::CCL2RPN( $query_to_use, $zconns[$i] )
-                      );
-                }
-                elsif ( $query_type =~ /^cql/ ) {
-                    $results[$i] =
-                      $zconns[$i]->search(
-                        new ZOOM::Query::CQL( $query_to_use, $zconns[$i] ) );
-                }
-                elsif ( $query_type =~ /^pqf/ ) {
-                    $results[$i] =
-                      $zconns[$i]->search(
-                        new ZOOM::Query::PQF( $query_to_use, $zconns[$i] ) );
-                }
-            }
-            else {
-                if ($scan) {
-                    $results[$i] =
-                      $zconns[$i]->scan(
-                        new ZOOM::Query::CCL2RPN( $query_to_use, $zconns[$i] )
-                      );
-                }
-                else {
-                    $results[$i] =
-                      $zconns[$i]->search(
-                        new ZOOM::Query::CCL2RPN( $query_to_use, $zconns[$i] )
-                      );
+            if ($query_type) {
+                if ($query_type =~ /^ccl/) {
+                    $query_to_use =~ s/\:/\=/g;    # change : to = last minute (FIXME)
+                    $results[$i] = $zconns[$i]->search(new ZOOM::Query::CCL2RPN($query_to_use, $zconns[$i]));
+                } elsif ($query_type =~ /^cql/) {
+                    $results[$i] = $zconns[$i]->search(new ZOOM::Query::CQL($query_to_use, $zconns[$i]));
+                } elsif ($query_type =~ /^pqf/) {
+                    $results[$i] = $zconns[$i]->search(new ZOOM::Query::PQF($query_to_use, $zconns[$i]));
+                } else {
+                    warn "Unknown query_type '$query_type'.  Results undetermined.";
                 }
+            } elsif ($scan) {
+                    $results[$i] = $zconns[$i]->scan(  new ZOOM::Query::CCL2RPN($query_to_use, $zconns[$i]));
+            } else {
+                    $results[$i] = $zconns[$i]->search(new ZOOM::Query::CCL2RPN($query_to_use, $zconns[$i]));
             }
         };
         if ($@) {
@@ -427,6 +381,9 @@ sub getRecords {
             elsif ( $sort eq "title_za" ) {
                 $sort_by .= "1=4 >i ";
             }
+            else {
+                warn "Ignoring unrecognized sort '$sort' requested" if $sort_by;
+            }
         }
         if ($sort_by) {
             if ( $results[$i]->sort( "yaz", $sort_by ) < 0 ) {
@@ -525,15 +482,15 @@ sub getRecords {
             if ( $servers[ $i - 1 ] =~ /biblioserver/ ) {
                 for my $link_value (
                     sort { $facets_counter->{$b} <=> $facets_counter->{$a} }
-                    keys %$facets_counter )
+                        keys %$facets_counter )
                 {
                     my $expandable;
                     my $number_of_facets;
                     my @this_facets_array;
                     for my $one_facet (
                         sort {
-                            $facets_counter->{$link_value}
-                              ->{$b} <=> $facets_counter->{$link_value}->{$a}
+                             $facets_counter->{$link_value}->{$b}
+                         <=> $facets_counter->{$link_value}->{$a}
                         } keys %{ $facets_counter->{$link_value} }
                       )
                     {
@@ -559,21 +516,14 @@ sub getRecords {
                                   $branches->{$one_facet}->{'branchname'};
                             }
 
-                # but we're down with the whole label being in the link's title.
-                            my $facet_title_value = $one_facet;
-
-                            push @this_facets_array,
-                              (
-                                {
-                                    facet_count =>
-                                      $facets_counter->{$link_value}
-                                      ->{$one_facet},
-                                    facet_label_value => $facet_label_value,
-                                    facet_title_value => $facet_title_value,
-                                    facet_link_value  => $facet_link_value,
-                                    type_link_value   => $link_value,
-                                },
-                              );
+                            # 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,
+                            };
                         }
                     }
 
@@ -583,17 +533,14 @@ sub getRecords {
                           if ( ( $number_of_facets > 6 )
                             && ( $expanded_facet ne $link_value ) );
                     }
-                    push @facets_loop,
-                      (
-                        {
-                            type_link_value => $link_value,
-                            type_id         => $link_value . "_id",
-                            "type_label_" . $facets_info->{$link_value}->{'label_value'} => 1, 
-                            facets     => \@this_facets_array,
-                            expandable => $expandable,
-                            expand     => $link_value,
-                        }
-                      ) unless ( ($facets_info->{$link_value}->{'label_value'} =~ /Libraries/) and (C4::Context->preference('singleBranchMode')) );
+                    push @facets_loop, {
+                        type_link_value => $link_value,
+                        type_id         => $link_value . "_id",
+                        "type_label_" . $facets_info->{$link_value}->{'label_value'} => 1, 
+                        facets     => \@this_facets_array,
+                        expandable => $expandable,
+                        expand     => $link_value,
+                    } unless ( ($facets_info->{$link_value}->{'label_value'} =~ /Libraries/) and (C4::Context->preference('singleBranchMode')) );
                 }
             }
         }
@@ -686,19 +633,16 @@ sub _remove_stopwords {
 #       we use IsAlpha unicode definition, to deal correctly with diacritics.
 #       otherwise, a French word like "leçon" woudl be split into "le" "çon", "le"
 #       is a stopword, we'd get "çon" and wouldn't find anything...
-        foreach ( keys %{ C4::Context->stopwords } ) {
-            next if ( $_ =~ /(and|or|not)/ );    # don't remove operators
-            if ( $operand =~
-                /(\P{IsAlpha}$_\P{IsAlpha}|^$_\P{IsAlpha}|\P{IsAlpha}$_$|^$_$)/ )
-            {
-                $operand =~ s/\P{IsAlpha}$_\P{IsAlpha}/ /gi;
-                $operand =~ s/^$_\P{IsAlpha}/ /gi;
-                $operand =~ s/\P{IsAlpha}$_$/ /gi;
-                               $operand =~ s/$1//gi;
-                push @stopwords_removed, $_;
-            }
-        }
-    }
+               foreach ( keys %{ C4::Context->stopwords } ) {
+                       next if ( $_ =~ /(and|or|not)/ );    # don't remove operators
+                       if ( my ($matched) = ($operand =~
+                               /(\P{IsAlnum}\Q$_\E\P{IsAlnum}|^\Q$_\E\P{IsAlnum}|\P{IsAlnum}\Q$_\E$|^\Q$_\E$)/gi) )
+                       {
+                               $operand =~ s/\Q$matched\E/ /gi;
+                               push @stopwords_removed, $_;
+                       }
+               }
+       }
     return ( $operand, \@stopwords_removed );
 }
 
@@ -850,11 +794,11 @@ sub buildQuery {
     warn "---------\nEnter buildQuery\n---------" if $DEBUG;
 
     # dereference
-    my @operators = @$operators if $operators;
-    my @indexes   = @$indexes   if $indexes;
-    my @operands  = @$operands  if $operands;
-    my @limits    = @$limits    if $limits;
-    my @sort_by   = @$sort_by   if $sort_by;
+    my @operators = $operators ? @$operators : ();
+    my @indexes   = $indexes   ? @$indexes   : ();
+    my @operands  = $operands  ? @$operands  : ();
+    my @limits    = $limits    ? @$limits    : ();
+    my @sort_by   = $sort_by   ? @$sort_by   : ();
 
     my $stemming         = C4::Context->preference("QueryStemming")        || 0;
     my $auto_truncation  = C4::Context->preference("QueryAutoTruncate")    || 0;
@@ -886,13 +830,13 @@ sub buildQuery {
 # for handling ccl, cql, pqf queries in diagnostic mode, skip the rest of the steps
 # DIAGNOSTIC ONLY!!
     if ( $query =~ /^ccl=/ ) {
-        return ( undef, $', $', $', $', '', '', '', '', 'ccl' );
+        return ( undef, $', $', "q=ccl=$'", $', '', '', '', '', 'ccl' );
     }
     if ( $query =~ /^cql=/ ) {
-        return ( undef, $', $', $', $', '', '', '', '', 'cql' );
+        return ( undef, $', $', "q=cql=$'", $', '', '', '', '', 'cql' );
     }
     if ( $query =~ /^pqf=/ ) {
-        return ( undef, $', $', $', $', '', '', '', '', 'pqf' );
+        return ( undef, $', $', "q=pqf=$'", $', '', '', '', '', 'pqf' );
     }
 
     # pass nested queries directly
@@ -976,6 +920,14 @@ sub buildQuery {
                       if ( $stopwords_removed && $DEBUG );
                 }
 
+                if ($auto_truncation){
+                                       #FIXME only valid with LTR scripts
+                                       $operand=join(" ",map{ 
+                                                                                       "$_*" 
+                                                                            }split (/\s+/,$operand));
+                       warn $operand if $DEBUG;
+                               }
+
                 # Detect Truncation
                 my $truncated_operand;
                 my( $nontruncated, $righttruncated, $lefttruncated,
@@ -995,29 +947,23 @@ sub buildQuery {
                     $indexes_set = 1;
                     undef $weight_fields;
                     my $previous_truncation_operand;
-                    if ( scalar(@$nontruncated) > 0 ) {
+                    if (scalar @$nontruncated) {
                         $truncated_operand .= "$index_plus @$nontruncated ";
                         $previous_truncation_operand = 1;
                     }
-                    if ( scalar(@$righttruncated) > 0 ) {
-                        $truncated_operand .= "and "
-                          if $previous_truncation_operand;
-                        $truncated_operand .=
-                          "$index_plus_comma" . "rtrn:@$righttruncated ";
+                    if (scalar @$righttruncated) {
+                        $truncated_operand .= "and " if $previous_truncation_operand;
+                        $truncated_operand .= $index_plus_comma . "rtrn:@$righttruncated ";
                         $previous_truncation_operand = 1;
                     }
-                    if ( scalar(@$lefttruncated) > 0 ) {
-                        $truncated_operand .= "and "
-                          if $previous_truncation_operand;
-                        $truncated_operand .=
-                          "$index_plus_comma" . "ltrn:@$lefttruncated ";
+                    if (scalar @$lefttruncated) {
+                        $truncated_operand .= "and " if $previous_truncation_operand;
+                        $truncated_operand .= $index_plus_comma . "ltrn:@$lefttruncated ";
                         $previous_truncation_operand = 1;
                     }
-                    if ( scalar(@$rightlefttruncated) > 0 ) {
-                        $truncated_operand .= "and "
-                          if $previous_truncation_operand;
-                        $truncated_operand .=
-                          "$index_plus_comma" . "rltrn:@$rightlefttruncated ";
+                    if (scalar @$rightlefttruncated) {
+                        $truncated_operand .= "and " if $previous_truncation_operand;
+                        $truncated_operand .= $index_plus_comma . "rltrn:@$rightlefttruncated ";
                         $previous_truncation_operand = 1;
                     }
                 }
@@ -1026,18 +972,19 @@ sub buildQuery {
 
                 # Handle Stemming
                 my $stemmed_operand;
-                $stemmed_operand = _build_stemmed_operand($operand)
-                  if $stemming;
+                $stemmed_operand = _build_stemmed_operand($operand) if $stemming;
+
                 warn "STEMMED OPERAND: >$stemmed_operand<" if $DEBUG;
 
                 # Handle Field Weighting
                 my $weighted_operand;
-                $weighted_operand =
-                  _build_weighted_query( $operand, $stemmed_operand, $index )
-                  if $weight_fields;
+                if ($weight_fields) {
+                    $weighted_operand = _build_weighted_query( $operand, $stemmed_operand, $index );
+                    $operand = $weighted_operand;
+                    $indexes_set = 1;
+                }
+
                 warn "FIELD WEIGHTED OPERAND: >$weighted_operand<" if $DEBUG;
-                $operand = $weighted_operand if $weight_fields;
-                $indexes_set = 1 if $weight_fields;
 
                 # If there's a previous operand, we need to add an operator
                 if ($previous_operand) {
@@ -1108,12 +1055,20 @@ sub buildQuery {
 
         # Regular old limits
         else {
-            if ($this_limit){
-                $limit .= " and " if $limit || $query;
-                $limit      .= "$this_limit";
-                $limit_cgi  .= "&limit=$this_limit";
+            $limit .= " and " if $limit || $query;
+            $limit      .= "$this_limit";
+            $limit_cgi  .= "&limit=$this_limit";
+            if ($this_limit =~ /^branch:(.+)/) {
+                my $branchcode = $1;
+                my $branchname = GetBranchName($branchcode);
+                if (defined $branchname) {
+                    $limit_desc .= " branch:$branchname";
+                } else {
+                    $limit_desc .= " $this_limit";
+                }
+            } else {
                 $limit_desc .= " $this_limit";
-            }      
+            }
         }
     }
     if ($group_OR_limits) {
@@ -1129,15 +1084,15 @@ sub buildQuery {
     $query =~ s/:/=/g;
     $limit =~ s/:/=/g;
     for ( $query, $query_desc, $limit, $limit_desc ) {
-        $_ =~ s/  / /g;    # remove extra spaces
-        $_ =~ s/^ //g;     # remove any beginning spaces
-        $_ =~ s/ $//g;     # remove any ending spaces
-        $_ =~ s/==/=/g;    # remove double == from query
+        s/  / /g;    # remove extra spaces
+        s/^ //g;     # remove any beginning spaces
+        s/ $//g;     # remove any ending spaces
+        s/==/=/g;    # remove double == from query
     }
     $query_cgi =~ s/^&//; # remove unnecessary & from beginning of the query cgi
 
     for ($query_cgi,$simple_query) {
-        $_ =~ s/"//g;
+        s/"//g;
     }
     # append the limit to the query
     $query .= " " . $limit;
@@ -1250,11 +1205,11 @@ sub searchResults {
         # add imageurl to itemtype if there is one
         $oldbiblio->{imageurl} = getitemtypeimagelocation( 'opac', $itemtypes{ $oldbiblio->{itemtype} }->{imageurl} );
 
-        $oldbiblio->{'authorised_value_images'}  = C4::Items::get_authorised_value_images( C4::Biblio::get_biblio_authorised_values( $oldbiblio->{'biblionumber'} ) );
+        $oldbiblio->{'authorised_value_images'}  = C4::Items::get_authorised_value_images( C4::Biblio::get_biblio_authorised_values( $oldbiblio->{'biblionumber'}, $marcrecord ) );
         (my $aisbn) = $oldbiblio->{isbn} =~ /([\d-]*[X]*)/;
         $aisbn =~ s/-//g;
         $oldbiblio->{amazonisbn} = $aisbn;
-               $oldbiblio->{description} = $itemtypes{ $oldbiblio->{itemtype} }->{description};
+       $oldbiblio->{description} = $itemtypes{ $oldbiblio->{itemtype} }->{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} ) {
@@ -1292,6 +1247,7 @@ s/\[(.?.?.?.?)$tagsubf(.*?)]/$1$subfieldvalue$2\[$1$tagsubf$2]/g;
         # save an author with no <span> tag, for the <a href=search.pl?q=<!--tmpl_var name="author"-->> link
         $oldbiblio->{'author_nospan'} = $oldbiblio->{'author'};
         $oldbiblio->{'title_nospan'} = $oldbiblio->{'title'};
+        $oldbiblio->{'subtitle_nospan'} = $oldbiblio->{'subtitle'};
         # Add search-term highlighting to the whole record where they match using <span>s
         if (C4::Context->preference("OpacHighlightedWords")){
             my $searchhighlightblob;
@@ -1336,15 +1292,18 @@ s/\[(.?.?.?.?)$tagsubf(.*?)]/$1$subfieldvalue$2\[$1$tagsubf$2]/g;
         # Setting item statuses for display
         my @available_items_loop;
         my @onloan_items_loop;
+        my @notforloan_items_loop;
         my @other_items_loop;
 
         my $available_items;
         my $onloan_items;
+        my $notforloan_items;
         my $other_items;
 
         my $ordered_count         = 0;
         my $available_count       = 0;
         my $onloan_count          = 0;
+        my $notforloan_count      = 0;
         my $longoverdue_count     = 0;
         my $other_count           = 0;
         my $wthdrawn_count        = 0;
@@ -1376,12 +1335,14 @@ s/\[(.?.?.?.?)$tagsubf(.*?)]/$1$subfieldvalue$2\[$1$tagsubf$2]/g;
             elsif ($item->{$otherbranch}) {    # Last resort
                 $item->{'branchname'} = $branches{$item->{$otherbranch}}; 
             }
-
+            
+            ($item->{'reserved'}) = C4::Reserves::CheckReserves($item->{itemnumber});
+            
                        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
-            if ( $item->{onloan} ) {
+            if ( $item->{onloan} or $item->{reserved} ) {
                 $onloan_count++;
-                               my $key = $prefix . $item->{due_date};
+                               my $key = $prefix . $item->{onloan} . $item->{barcode};
                                $onloan_items->{$key}->{due_date} = format_date($item->{onloan});
                                $onloan_items->{$key}->{count}++ if $item->{$hbranch};
                                $onloan_items->{$key}->{branchname} = $item->{branchname};
@@ -1436,6 +1397,7 @@ s/\[(.?.?.?.?)$tagsubf(.*?)]/$1$subfieldvalue$2\[$1$tagsubf$2]/g;
                     || $item->{itemlost}
                     || $item->{damaged}
                     || $item->{notforloan} 
+                    || $item->{reserved}
                     || ($transfertwhen ne ''))
                 {
                     $wthdrawn_count++        if $item->{wthdrawn};
@@ -1443,18 +1405,36 @@ s/\[(.?.?.?.?)$tagsubf(.*?)]/$1$subfieldvalue$2\[$1$tagsubf$2]/g;
                     $itemdamaged_count++     if $item->{damaged};
                     $item_in_transit_count++ if $transfertwhen ne '';
                     $item->{status} = $item->{wthdrawn} . "-" . $item->{itemlost} . "-" . $item->{damaged} . "-" . $item->{notforloan};
-                    $other_count++;
 
                                        my $key = $prefix . $item->{status};
+                                       
                                        foreach (qw(wthdrawn itemlost damaged branchname itemcallnumber)) {
-                       $other_items->{$key}->{$_} = $item->{$_};
+                                           if($item->{notforloan} == 1){
+                                               $notforloan_items->{$key}->{$_} = $item->{$_};
+                                           }else{
+                          $other_items->{$key}->{$_} = $item->{$_};
+                                           }
                                        }
-                    $other_items->{$key}->{intransit} = ($transfertwhen ne '') ? 1 : 0;
-                                       $other_items->{$key}->{notforloan} = GetAuthorisedValueDesc('','',$item->{notforloan},'','',$notforloan_authorised_value) if $notforloan_authorised_value;
-                                       $other_items->{$key}->{count}++ if $item->{$hbranch};
-                                       $other_items->{$key}->{location} = $shelflocations->{ $item->{location} };
-                                       $other_items->{$key}->{imageurl} = getitemtypeimagelocation( 'opac', $itemtypes{ $item->{itype} }->{imageurl} );
-                                       $other_items->{$key}->{barcode} = $item->{barcode};
+                                       if($item->{notforloan} == 1){
+                        $notforloan_count++;
+
+                        $notforloan_items->{$key}->{intransit} = ($transfertwhen ne '') ? 1 : 0;
+                                       $notforloan_items->{$key}->{notforloan} = GetAuthorisedValueDesc('','',$item->{notforloan},'','',$notforloan_authorised_value) if $notforloan_authorised_value;
+                                       $notforloan_items->{$key}->{count}++ if $item->{$hbranch};
+                                       $notforloan_items->{$key}->{location} = $shelflocations->{ $item->{location} };
+                                       $notforloan_items->{$key}->{imageurl} = getitemtypeimagelocation( 'opac', $itemtypes{ $item->{itype} }->{imageurl} );
+                                       $notforloan_items->{$key}->{barcode} = $item->{barcode};
+                    }else{
+                        $other_count++;
+                                       
+                        $other_items->{$key}->{intransit} = ($transfertwhen ne '') ? 1 : 0;
+                                       $other_items->{$key}->{notforloan} = GetAuthorisedValueDesc('','',$item->{notforloan},'','',$notforloan_authorised_value) if $notforloan_authorised_value;
+                                       $other_items->{$key}->{count}++ if $item->{$hbranch};
+                                       $other_items->{$key}->{location} = $shelflocations->{ $item->{location} };
+                                       $other_items->{$key}->{imageurl} = getitemtypeimagelocation( 'opac', $itemtypes{ $item->{itype} }->{imageurl} );
+                                       $other_items->{$key}->{barcode} = $item->{barcode};
+                    }
+
                 }
                 # item is available
                 else {
@@ -1469,7 +1449,7 @@ s/\[(.?.?.?.?)$tagsubf(.*?)]/$1$subfieldvalue$2\[$1$tagsubf$2]/g;
                 }
             }
         }    # notforloan, item level and biblioitem level
-        my ( $availableitemscount, $onloanitemscount, $otheritemscount );
+        my ( $availableitemscount, $onloanitemscount, $notforloanitemscount,$otheritemscount );
         $maxitems =
           ( C4::Context->preference('maxItemsinSearchResults') )
           ? C4::Context->preference('maxItemsinSearchResults') - 1
@@ -1482,6 +1462,10 @@ s/\[(.?.?.?.?)$tagsubf(.*?)]/$1$subfieldvalue$2\[$1$tagsubf$2]/g;
             (++$otheritemscount > $maxitems) and last;
             push @other_items_loop, $other_items->{$key};
         }
+        for my $key ( sort keys %$notforloan_items ) {
+            (++$notforloanitemscount > $maxitems) and last;
+            push @notforloan_items_loop, $notforloan_items->{$key};
+        }
         for my $key ( sort keys %$available_items ) {
             (++$availableitemscount > $maxitems) and last;
             push @available_items_loop, $available_items->{$key}
@@ -1489,23 +1473,24 @@ s/\[(.?.?.?.?)$tagsubf(.*?)]/$1$subfieldvalue$2\[$1$tagsubf$2]/g;
 
         # XSLT processing of some stuff
         if (C4::Context->preference("XSLTResultsDisplay") && !$scan) {
-            my $newxmlrecord = XSLTParse4Display($oldbiblio->{biblionumber},C4::Context->config('opachtdocs')."/prog/en/xslt/MARC21slim2OPACResults.xsl");
-            $oldbiblio->{XSLTResultsRecord} = $newxmlrecord;
+            $oldbiblio->{XSLTResultsRecord} = XSLTParse4Display(
+                $oldbiblio->{biblionumber}, $marcrecord, 'Results' );
         }
 
         # last check for norequest : if itemtype is notforloan, it can't be reserved either, whatever the items
-        $can_place_holds = 0
-          if $itemtypes{ $oldbiblio->{itemtype} }->{notforloan};
+        $can_place_holds = 0 if $itemtypes{ $oldbiblio->{itemtype} }->{notforloan};
         $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->{notforloan_items_loop}= \@notforloan_items_loop;
         $oldbiblio->{onloan_items_loop}    = \@onloan_items_loop;
         $oldbiblio->{other_items_loop}     = \@other_items_loop;
         $oldbiblio->{availablecount}       = $available_count;
         $oldbiblio->{availableplural}      = 1 if $available_count > 1;
         $oldbiblio->{onloancount}          = $onloan_count;
         $oldbiblio->{onloanplural}         = 1 if $onloan_count > 1;
+        $oldbiblio->{notforloancount}      = $notforloan_count;
         $oldbiblio->{othercount}           = $other_count;
         $oldbiblio->{otherplural}          = 1 if $other_count > 1;
         $oldbiblio->{wthdrawncount}        = $wthdrawn_count;
@@ -1701,16 +1686,15 @@ sub NZanalyse {
         $left = 'subject'          if $left =~ '^su$';
         $left = 'koha-Auth-Number' if $left =~ '^an$';
         $left = 'keyword'          if $left =~ '^kw$';
+        $left = 'itemtype'         if $left =~ '^mc$'; # Fix for Bug 2599 - Search limits not working for NoZebra 
         warn "handling leaf... left:$left operator:$operator right:$right" if $DEBUG;
+        my $dbh = C4::Context->dbh;
         if ( $operator && $left ne 'keyword' ) {
-
             #do a specific search
-            my $dbh = C4::Context->dbh;
             $operator = 'LIKE' if $operator eq '=' and $right =~ /%/;
-            my $sth =
-              $dbh->prepare(
+            my $sth = $dbh->prepare(
 "SELECT biblionumbers,value FROM nozebra WHERE server=? AND indexname=? AND value $operator ?"
-              );
+            );
             warn "$left / $operator / $right\n" if $DEBUG;
 
             # split each word, query the DB and build the biblionumbers result
@@ -1738,20 +1722,16 @@ sub NZanalyse {
                 if ($results) {
                     warn "NZAND" if $DEBUG;
                     $results = NZoperatorAND($biblionumbers,$results);
-                }
-                else {
+                } else {
                     $results = $biblionumbers;
                 }
             }
         }
         else {
-
       #do a complete search (all indexes), if index='kw' do complete search too.
-            my $dbh = C4::Context->dbh;
-            my $sth =
-              $dbh->prepare(
+            my $sth = $dbh->prepare(
 "SELECT biblionumbers FROM nozebra WHERE server=? AND value LIKE ?"
-              );
+            );
 
             # split each word, query the DB and build the biblionumbers result
             foreach ( split / /, $string ) {
@@ -1864,7 +1844,7 @@ sub NZorder {
             my $popularity = $sth->fetchrow || 0;
 
 # hint : the key is popularity.title because we can have
-# many results with the same popularity. In this cas, sub-ordering is done by title
+# many results with the same popularity. In this case, sub-ordering is done by title
 # we also have biblionumber to avoid bug for 2 biblios with the same title & popularity
 # (un-frequent, I agree, but we won't forget anything that way ;-)
             $popularity{ sprintf( "%10d", $popularity ) . $title
@@ -2125,130 +2105,6 @@ sub NZorder {
     }
 }
 
-=head2 ModBiblios
-
-($countchanged,$listunchanged) = ModBiblios($listbiblios, $tagsubfield,$initvalue,$targetvalue,$test);
-
-this function changes all the values $initvalue in subfield $tag$subfield in any record in $listbiblios
-test parameter if set donot perform change to records in database.
-
-=over 2
-
-=item C<input arg:>
-
-    * $listbiblios is an array ref to marcrecords to be changed
-    * $tagsubfield is the reference of the subfield to change.
-    * $initvalue is the value to search the record for
-    * $targetvalue is the value to set the subfield to
-    * $test is to be set only not to perform changes in database.
-
-=item C<Output arg:>
-    * $countchanged counts all the changes performed.
-    * $listunchanged contains the list of all the biblionumbers of records unchanged.
-
-=item C<usage in the script:>
-
-=back
-
-my ($countchanged, $listunchanged) = EditBiblios($results->{RECORD}, $tagsubfield,$initvalue,$targetvalue);;
-#If one wants to display unchanged records, you should get biblios foreach @$listunchanged 
-$template->param(countchanged => $countchanged, loopunchanged=>$listunchanged);
-
-=cut
-
-sub ModBiblios {
-    my ( $listbiblios, $tagsubfield, $initvalue, $targetvalue, $test ) = @_;
-    my $countmatched;
-    my @unmatched;
-    my ( $tag, $subfield ) = ( $1, $2 )
-      if ( $tagsubfield =~ /^(\d{1,3})([a-z0-9A-Z@])?$/ );
-    if ( ( length($tag) < 3 ) && $subfield =~ /0-9/ ) {
-        $tag = $tag . $subfield;
-        undef $subfield;
-    }
-    my ( $bntag,   $bnsubf )   = GetMarcFromKohaField('biblio.biblionumber','');
-    my ( $itemtag, $itemsubf ) = GetMarcFromKohaField('items.itemnumber','');
-    if ($tag eq $itemtag) {
-        # do not allow the embedded item tag to be 
-        # edited from here
-        warn "Attempting to edit item tag via C4::Search::ModBiblios -- not allowed";
-        return (0, []);
-    }
-    foreach my $usmarc (@$listbiblios) {
-        my $record;
-        $record = eval { MARC::Record->new_from_usmarc($usmarc) };
-        my $biblionumber;
-        if ($@) {
-
-            # usmarc is not a valid usmarc May be a biblionumber
-            # FIXME - sorry, please let's figure out whether
-            #         this function is to be passed a list of
-            #         record numbers or a list of MARC::Record
-            #         objects.  The former is probably better
-            #         because the MARC records supplied by Zebra
-            #         may be not current.
-            $record       = GetMarcBiblio($usmarc);
-            $biblionumber = $usmarc;
-        }
-        else {
-            if ( $bntag >= 010 ) {
-                $biblionumber = $record->subfield( $bntag, $bnsubf );
-            }
-            else {
-                $biblionumber = $record->field($bntag)->data;
-            }
-        }
-
-        #GetBiblionumber is to be written.
-        #Could be replaced by TransformMarcToKoha (But Would be longer)
-        if ( $record->field($tag) ) {
-            my $modify = 0;
-            foreach my $field ( $record->field($tag) ) {
-                if ($subfield) {
-                    if (
-                        $field->delete_subfield(
-                            'code'  => $subfield,
-                            'match' => qr($initvalue)
-                        )
-                      )
-                    {
-                        $countmatched++;
-                        $modify = 1;
-                        $field->update( $subfield, $targetvalue )
-                          if ($targetvalue);
-                    }
-                }
-                else {
-                    if ( $tag >= 010 ) {
-                        if ( $field->delete_field($field) ) {
-                            $countmatched++;
-                            $modify = 1;
-                        }
-                    }
-                    else {
-                        $field->data = $targetvalue
-                          if ( $field->data =~ qr($initvalue) );
-                    }
-                }
-            }
-
-            #       warn $record->as_formatted;
-            if ($modify) {
-                ModBiblio( $record, $biblionumber,
-                    GetFrameworkCode($biblionumber) )
-                  unless ($test);
-            }
-            else {
-                push @unmatched, $biblionumber;
-            }
-        }
-        else {
-            push @unmatched, $biblionumber;
-        }
-    }
-    return ( $countmatched, \@unmatched );
-}
-
 END { }    # module clean-up code here (global destructor)
 
 1;