X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=C4%2FSearch.pm;h=8a62a40882a8f38baaa11119d6f2130082e7feb5;hb=3dd5fccccc4c50778cc80052d5f750cc6a423874;hp=8f3410f46481a5c0ed7cd9120b2ed9b36336d2cd;hpb=3037ff9e81149615f94d3c4ff0e5b4c5240f3ce9;p=koha.git diff --git a/C4/Search.pm b/C4/Search.pm index 8f3410f464..8a62a40882 100644 --- a/C4/Search.pm +++ b/C4/Search.pm @@ -27,6 +27,8 @@ use XML::Simple; use C4::Dates qw(format_date); use C4::XSLT; use C4::Branch; +use C4::Debug; +use YAML; use URI::Escape; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $DEBUG); @@ -58,6 +60,7 @@ This module provides searching functions for Koha's bibliographic databases &FindDuplicate &SimpleSearch &searchResults + &SearchAcquisitions &getRecords &buildQuery &NZgetRecords @@ -633,10 +636,12 @@ 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 + $debug && warn "$_ Dump($operand)"; if ( my ($matched) = ($operand =~ - /(\P{IsAlnum}\Q$_\E\P{IsAlnum}|^\Q$_\E\P{IsAlnum}|\P{IsAlnum}\Q$_\E$|^\Q$_\E$)/gi) ) + /([^\X\p{isAlnum}]\Q$_\E[^\X\p{isAlnum}]|[^\X\p{isAlnum}]\Q$_\E$|^\Q$_\E[^\X\p{isAlnum}])/gi)) { $operand =~ s/\Q$matched\E/ /gi; push @stopwords_removed, $_; @@ -996,9 +1001,10 @@ sub buildQuery { # no stemming/weight/fuzzy in NoZebra if ( C4::Context->preference("NoZebra") ) { - $stemming = 0; - $weight_fields = 0; - $fuzzy_enabled = 0; + $stemming = 0; + $weight_fields = 0; + $fuzzy_enabled = 0; + $auto_truncation = 0; } my $query = $operands[0]; @@ -1016,10 +1022,10 @@ sub buildQuery { my $stopwords_removed; # flag to determine if stopwords have been removed my $cclq; - my $indexes = getIndexes(); + my $cclindexes = getIndexes(); if( $query !~ /\s*ccl=/ ){ - for my $index (@$indexes){ - if($query =~ /($index)(,?\w)*:/){ + for my $index (@$cclindexes){ + if($query =~ /($index)(,?\w)*[:=]/){ $cclq = 1; } } @@ -1125,11 +1131,13 @@ sub buildQuery { } if ($auto_truncation){ - #FIXME only valid with LTR scripts - $operand=join(" ",map{ - "$_*" - }split (/\s+/,$operand)); - warn $operand if $DEBUG; + unless ( $index =~ /(st-|phr|ext)/ ) { + #FIXME only valid with LTR scripts + $operand=join(" ",map{ + (index($_,"*")>0?"$_":"$_*") + }split (/\s+/,$operand)); + warn $operand if $DEBUG; + } } # Detect Truncation @@ -1392,16 +1400,20 @@ sub searchResults { # We get the biblionumber position in MARC my ($bibliotag,$bibliosubf)=GetMarcFromKohaField('biblio.biblionumber',''); - my $fw; + 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] ); - - if ($bibliotag<10){ - $fw = GetFrameworkCode($marcrecord->field($bibliotag)->data); - }else{ - $fw = GetFrameworkCode($marcrecord->subfield($bibliotag,$bibliosubf)); + my $biblionumber; + + if(not $scan){ + if ($bibliotag<10){ + $biblionumber = $marcrecord->field($bibliotag) ? $marcrecord->field($bibliotag)->data : undef; + }else{ + $biblionumber = $marcrecord->subfield($bibliotag,$bibliosubf); + } + $fw = (defined $biblionumber) ? GetFrameworkCode($biblionumber) : ''; } my $oldbiblio = TransformMarcToKoha( $dbh, $marcrecord, $fw ); @@ -1428,33 +1440,49 @@ sub searchResults { if ( $itemtypes{ $oldbiblio->{itemtype} }->{summary} ) { my $summary = $itemtypes{ $oldbiblio->{itemtype} }->{summary}; my @fields = $marcrecord->fields(); - foreach my $field (@fields) { - my $tag = $field->tag(); - my $tagvalue = $field->as_string(); - if (! utf8::is_utf8($tagvalue)) { - utf8::decode($tagvalue); + + my $newsummary; + foreach my $line ( "$summary\n" =~ /(.*)\n/g ){ + my $tags = {}; + foreach my $tag ( $line =~ /\[(\d{3}[\w|\d])\]/ ) { + $tag =~ /(.{3})(.)/; + if($marcrecord->field($1)){ + my @abc = $marcrecord->field($1)->subfield($2); + $tags->{$tag} = $#abc + 1 ; + } } - - $summary =~ - s/\[(.?.?.?.?)$tag\*(.*?)]/$1$tagvalue$2\[$1$tag$2]/g; - unless ( $tag < 10 ) { - my @subf = $field->subfields; - for my $i ( 0 .. $#subf ) { - my $subfieldcode = $subf[$i][0]; - my $subfieldvalue = $subf[$i][1]; - if (! utf8::is_utf8($subfieldvalue)) { - utf8::decode($subfieldvalue); + + # We catch how many times to repeat this line + my $max = 0; + foreach my $tag (keys(%$tags)){ + $max = $tags->{$tag} if($tags->{$tag} > $max); + } + + # we replace, and repeat each line + for (my $i = 0 ; $i < $max ; $i++){ + my $newline = $line; + + foreach my $tag ( $newline =~ /\[(\d{3}[\w|\d])\]/g ) { + $tag =~ /(.{3})(.)/; + + if($marcrecord->field($1)){ + my @repl = $marcrecord->field($1)->subfield($2); + my $subfieldvalue = $repl[$i]; + + if (! utf8::is_utf8($subfieldvalue)) { + utf8::decode($subfieldvalue); + } + + $newline =~ s/\[$tag\]/$subfieldvalue/g; } - my $tagsubf = $tag . $subfieldcode; - $summary =~ -s/\[(.?.?.?.?)$tagsubf(.*?)]/$1$subfieldvalue$2\[$1$tagsubf$2]/g; } + $newsummary .= "$newline\n"; } } - # FIXME: yuk - $summary =~ s/\[(.*?)]//g; - $summary =~ s/\n//g; - $oldbiblio->{summary} = $summary; + + $newsummary =~ s/\[(.*?)]//g; + $newsummary =~ s/\n//g; + $oldbiblio->{summary} = $newsummary; } # Pull out the items fields @@ -1521,6 +1549,7 @@ s/\[(.?.?.?.?)$tagsubf(.*?)]/$1$subfieldvalue$2\[$1$tagsubf$2]/g; $onloan_items->{$key}->{itemcallnumber} = $item->{itemcallnumber}; $onloan_items->{$key}->{imageurl} = getitemtypeimagelocation( 'opac', $itemtypes{ $item->{itype} }->{imageurl} ); $onloan_items->{$key}->{barcode} = $item->{barcode}; + $onloan_items->{$key}->{reserved} = $item->{reserved}; # if something's checked out and lost, mark it as 'long overdue' if ( $item->{itemlost} ) { $onloan_items->{$prefix}->{longoverdue}++; @@ -1676,6 +1705,95 @@ s/\[(.?.?.?.?)$tagsubf(.*?)]/$1$subfieldvalue$2\[$1$tagsubf$2]/g; return @newresults; } +=head2 SearchAcquisitions + Search for acquisitions +=cut + +sub SearchAcquisitions{ + my ($datebegin, $dateend, $itemtypes,$criteria, $orderby) = @_; + + my $dbh=C4::Context->dbh; + # Variable initialization + my $str=qq| + SELECT marcxml + FROM biblio + LEFT JOIN biblioitems ON biblioitems.biblionumber=biblio.biblionumber + LEFT JOIN items ON items.biblionumber=biblio.biblionumber + WHERE dateaccessioned BETWEEN ? AND ? + |; + + my (@params,@loopcriteria); + + push @params, $datebegin->output("iso"); + push @params, $dateend->output("iso"); + + if (scalar(@$itemtypes)>0 and $criteria ne "itemtype" ){ + if(C4::Context->preference("item-level_itypes")){ + $str .= "AND items.itype IN (?".( ',?' x scalar @$itemtypes - 1 ).") "; + }else{ + $str .= "AND biblioitems.itemtype IN (?".( ',?' x scalar @$itemtypes - 1 ).") "; + } + push @params, @$itemtypes; + } + + if ($criteria =~/itemtype/){ + if(C4::Context->preference("item-level_itypes")){ + $str .= "AND items.itype=? "; + }else{ + $str .= "AND biblioitems.itemtype=? "; + } + + if(scalar(@$itemtypes) == 0){ + my $itypes = GetItemTypes(); + for my $key (keys %$itypes){ + push @$itemtypes, $key; + } + } + + @loopcriteria= @$itemtypes; + }elsif ($criteria=~/itemcallnumber/){ + $str .= "AND (items.itemcallnumber LIKE CONCAT(?,'%') + OR items.itemcallnumber is NULL + OR items.itemcallnumber = '')"; + + @loopcriteria = ("AA".."ZZ", "") unless (scalar(@loopcriteria)>0); + }else { + $str .= "AND biblio.title LIKE CONCAT(?,'%') "; + @loopcriteria = ("A".."z") unless (scalar(@loopcriteria)>0); + } + + if ($orderby =~ /date_desc/){ + $str.=" ORDER BY dateaccessioned DESC"; + } else { + $str.=" ORDER BY title"; + } + + my $qdataacquisitions=$dbh->prepare($str); + + my @loopacquisitions; + foreach my $value(@loopcriteria){ + push @params,$value; + my %cell; + $cell{"title"}=$value; + $cell{"titlecode"}=$value; + + eval{$qdataacquisitions->execute(@params);}; + + if ($@){ warn "recentacquisitions Error :$@";} + else { + my @loopdata; + while (my $data=$qdataacquisitions->fetchrow_hashref){ + push @loopdata, {"summary"=>GetBiblioSummary( $data->{'marcxml'} ) }; + } + $cell{"loopdata"}=\@loopdata; + } + push @loopacquisitions,\%cell if (scalar(@{$cell{loopdata}})>0); + pop @params; + } + $qdataacquisitions->finish; + return \@loopacquisitions; +} + #---------------------------------------------------------------------- # # Non-Zebra GetRecords# @@ -1905,7 +2023,7 @@ sub NZanalyse { ); # split each word, query the DB and build the biblionumbers result - foreach ( split / /, $string ) { + foreach ( split (/ /, $string )) { next if C4::Context->stopwords->{ uc($_) }; # skip if stopword warn "search on all indexes on $_" if $DEBUG; my $biblionumbers; @@ -1934,7 +2052,7 @@ sub NZanalyse { sub NZoperatorAND{ my ($rightresult, $leftresult)=@_; - my @leftresult = split /;/, $leftresult; + my @leftresult = split (/;/, $leftresult); warn " @leftresult / $rightresult \n" if $DEBUG; # my @rightresult = split /;/,$leftresult; @@ -2008,8 +2126,8 @@ sub NZorder { # popularity is not in MARC record, it's builded from a specific query my $sth = $dbh->prepare("select sum(issues) from items where biblionumber=?"); - foreach ( split /;/, $biblionumbers ) { - my ( $biblionumber, $title ) = split /,/, $_; + foreach ( split (/;/, $biblionumbers )) { + my ( $biblionumber, $title ) = split (/,/, $_); $result{$biblionumber} = GetMarcBiblio($biblionumber); $sth->execute($biblionumber); my $popularity = $sth->fetchrow || 0; @@ -2048,8 +2166,8 @@ sub NZorder { } elsif ( $ordering =~ /author/ ) { my %result; - foreach ( split /;/, $biblionumbers ) { - my ( $biblionumber, $title ) = split /,/, $_; + foreach ( split (/;/, $biblionumbers )) { + my ( $biblionumber, $title ) = split (/,/, $_); my $record = GetMarcBiblio($biblionumber); my $author; if ( C4::Context->preference('marcflavour') eq 'UNIMARC' ) { @@ -2091,8 +2209,8 @@ sub NZorder { } elsif ( $ordering =~ /callnumber/ ) { my %result; - foreach ( split /;/, $biblionumbers ) { - my ( $biblionumber, $title ) = split /,/, $_; + foreach ( split (/;/, $biblionumbers )) { + my ( $biblionumber, $title ) = split (/,/, $_); my $record = GetMarcBiblio($biblionumber); my $callnumber; my ( $callnumber_tag, $callnumber_subfield ) = @@ -2134,8 +2252,8 @@ sub NZorder { } elsif ( $ordering =~ /pubdate/ ) { #pub year my %result; - foreach ( split /;/, $biblionumbers ) { - my ( $biblionumber, $title ) = split /,/, $_; + foreach ( split (/;/, $biblionumbers )) { + my ( $biblionumber, $title ) = split (/,/, $_); my $record = GetMarcBiblio($biblionumber); my ( $publicationyear_tag, $publicationyear_subfield ) = GetMarcFromKohaField( 'biblioitems.publicationyear', '' ); @@ -2176,8 +2294,8 @@ sub NZorder { # the title is in the biblionumbers string, so we just need to build a hash, sort it and return my %result; - foreach ( split /;/, $biblionumbers ) { - my ( $biblionumber, $title ) = split /,/, $_; + foreach ( split (/;/, $biblionumbers )) { + my ( $biblionumber, $title ) = split (/,/, $_); # hint : the result is sorted by title.biblionumber because we can have X biblios with the same title # and we don't want to get only 1 result for each of them !!!