# Suite 330, Boston, MA 02111-1307 USA
use strict;
-# use warnings; # FIXME
+#use warnings; FIXME - Bug 2505
require Exporter;
use C4::Context;
use C4::Biblio; # GetMarcFromKohaField, GetBiblioData
use C4::Dates qw(format_date);
use C4::XSLT;
use C4::Branch;
+use C4::Reserves; # CheckReserves
use C4::Debug;
-use YAML;
use URI::Escape;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $DEBUG);
#
foreach ( keys %{ C4::Context->stopwords } ) {
next if ( $_ =~ /(and|or|not)/ ); # don't remove operators
- $debug && warn "$_ Dump($operand)";
if ( my ($matched) = ($operand =~
/([^\X\p{isAlnum}]\Q$_\E[^\X\p{isAlnum}]|[^\X\p{isAlnum}]\Q$_\E$|^\Q$_\E[^\X\p{isAlnum}])/gi))
{
'biblionumber',
'bio',
'biography',
- 'callnum',
+ 'callnum',
'cfn',
'Chronological-subdivision',
'cn-bib-source',
'popularity',
'pubdate',
'Publisher',
+ 'Record-control-number',
+ 'rcn',
'Record-type',
'rtype',
'se',
'Title-uniform-seealso',
'totalissues',
'yr',
-
+
# items indexes
'acqsource',
'barcode',
'holdingbranch',
'homebranch',
'issues',
+ 'item',
'itemnumber',
'itype',
'Local-classification',
'stack',
'uri',
'withdrawn',
-
+
# subject related
);
-
+
return \@indexes;
}
# 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];
# for handling ccl, cql, pqf queries in diagnostic mode, skip the rest of the steps
# DIAGNOSTIC ONLY!!
if ( $query =~ /^ccl=/ ) {
- return ( undef, $', $', "q=ccl=$'", $', '', '', '', '', 'ccl' );
+ my $q=$';
+ # This is needed otherwise ccl= and &limit won't work together, and
+ # this happens when selecting a subject on the opac-detail page
+ if (@limits) {
+ $q .= ' and '.join(' and ', @limits);
+ }
+ return ( undef, $q, $q, "q=ccl=$q", $q, '', '', '', '', 'ccl' );
}
if ( $query =~ /^cql=/ ) {
return ( undef, $', $', "q=cql=$'", $', '', '', '', '', 'cql' );
# COMBINE OPERANDS, INDEXES AND OPERATORS
if ( $operands[$i] ) {
+ $operands[$i]=~s/^\s+//;
# A flag to determine whether or not to add the index to the query
my $indexes_set;
) = ( 0, 0, 0, 0, 0 );
}
-
+
if(not $index){
$index = 'kw';
}
-
+
# Set default structure attribute (word list)
- my $struct_attr;
+ my $struct_attr = q{};
unless ( $indexes_set || !$index || $index =~ /(st-|phr|ext|wrdl)/ ) {
$struct_attr = ",wrdl";
}
# Some helpful index variants
- my $index_plus = $index . $struct_attr . ":" if $index;
- my $index_plus_comma = $index . $struct_attr . "," if $index;
+ my $index_plus = $index . $struct_attr . ':';
+ my $index_plus_comma = $index . $struct_attr . ',';
# Remove Stopwords
if ($remove_stopwords) {
}
if ($auto_truncation){
- $operand=~join(" ",map{ "$_*" }split (/\s+/,$operand));
+ 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
my $group_OR_limits;
my $availability_limit;
foreach my $this_limit (@limits) {
-# if ( $this_limit =~ /available/ ) {
+ if ( $this_limit =~ /available/ ) {
#
## 'available' is defined as (items.onloan is NULL) and (items.itemlost = 0)
## 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='')) )";
-# $limit_cgi .= "&limit=available";
-# $limit_desc .= "";
-# }
-#
+ $availability_limit .=
+"( ( allrecords,AlwaysMatches='' not onloan,AlwaysMatches='') and (lost,st-numeric=0) )"; #or ( allrecords,AlwaysMatches='' not lost,AlwaysMatches='')) )";
+ $limit_cgi .= "&limit=available";
+ $limit_desc .= "";
+ }
+
# group_OR_limits, prefixed by mc-
# OR every member of the group
-# elsif ( $this_limit =~ /mc/ ) {
- if ( $this_limit =~ /mc/ ) {
+ elsif ( $this_limit =~ /mc/ ) {
+
+ if ( $this_limit =~ /mc-ccode:/ ) {
+ # in case the mc-ccode value has complicating chars like ()'s inside it we wrap in quotes
+ $this_limit =~ tr/"//d;
+ my ($k,$v) = split(/:/, $this_limit,2);
+ $this_limit = $k.":\"".$v."\"";
+ }
+
$group_OR_limits .= " or " if $group_OR_limits;
$limit_desc .= " or " if $group_OR_limits;
$group_OR_limits .= "$this_limit";
# Normalize the query and limit strings
# This is flawed , means we can't search anything with : in it
# if user wants to do ccl or cql, start the query with that
- $query =~ s/:/=/g;
+# $query =~ s/:/=/g;
+ $query =~ s/(?<=(ti|au|pb|su|an|kw|mc)):/=/g;
+ $query =~ s/(?<=(wrdl)):/=/g;
+ $query =~ s/(?<=(trn|phr)):/=/g;
$limit =~ s/:/=/g;
for ( $query, $query_desc, $limit, $limit_desc ) {
- s/ / /g; # remove extra spaces
+ s/ +/ /g; # remove extra spaces
s/^ //g; # remove any beginning spaces
s/ $//g; # remove any ending spaces
s/==/=/g; # remove double == from query
=head2 searchResults
+ my @search_results = searchResults($search_context, $searchdesc, $hits,
+ $results_per_page, $offset, $scan,
+ @marcresults, $hidelostitems);
+
Format results in a form suitable for passing to the template
=cut
# IMO this subroutine is pretty messy still -- it's responsible for
# building the HTML output for the template
sub searchResults {
- my ( $searchdesc, $hits, $results_per_page, $offset, $scan, @marcresults, $hidelostitems ) = @_;
+ my ( $search_context, $searchdesc, $hits, $results_per_page, $offset, $scan, @marcresults, $hidelostitems ) = @_;
my $dbh = C4::Context->dbh;
my @newresults;
+ $search_context = 'opac' unless $search_context eq 'opac' or $search_context eq 'intranet';
+
#Build branchnames hash
#find branchname
#get branch information.....
# 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));
- }
-
+ $fw = $scan
+ ? undef
+ : $bibliotag < 10
+ ? GetFrameworkCode($marcrecord->field($bibliotag)->data)
+ : GetFrameworkCode($marcrecord->subfield($bibliotag,$bibliosubf));
my $oldbiblio = TransformMarcToKoha( $dbh, $marcrecord, $fw );
$oldbiblio->{subtitle} = GetRecordValue('subtitle', $marcrecord, $fw);
$oldbiblio->{result_number} = $i + 1;
my $itemdamaged_count = 0;
my $item_in_transit_count = 0;
my $can_place_holds = 0;
+ my $item_onhold_count = 0;
my $items_count = scalar(@fields);
my $maxitems =
( C4::Context->preference('maxItemsinSearchResults') )
my $transfertwhen = '';
my ($transfertfrom, $transfertto);
+ # is item on the reserve shelf?
+ my $reservestatus = 0;
+ my $reserveitem;
+
unless ($item->{wthdrawn}
|| $item->{itemlost}
|| $item->{damaged}
# should map transit status to record indexed in Zebra.
#
($transfertwhen, $transfertfrom, $transfertto) = C4::Circulation::GetTransfers($item->{itemnumber});
+ ($reservestatus, $reserveitem) = C4::Reserves::CheckReserves($item->{itemnumber});
}
# item is withdrawn, lost or damaged
if ( $item->{wthdrawn}
|| $item->{itemlost}
|| $item->{damaged}
- || $item->{notforloan}
+ || $item->{notforloan} > 0
+ || $reservestatus eq 'Waiting'
|| ($transfertwhen ne ''))
{
$wthdrawn_count++ if $item->{wthdrawn};
$itemlost_count++ if $item->{itemlost};
$itemdamaged_count++ if $item->{damaged};
$item_in_transit_count++ if $transfertwhen ne '';
+ $item_onhold_count++ if $reservestatus eq 'Waiting';
$item->{status} = $item->{wthdrawn} . "-" . $item->{itemlost} . "-" . $item->{damaged} . "-" . $item->{notforloan};
$other_count++;
$other_items->{$key}->{$_} = $item->{$_};
}
$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;
$other_items->{$key}->{count}++ if $item->{$hbranch};
$other_items->{$key}->{location} = $shelflocations->{ $item->{location} };
}
# XSLT processing of some stuff
- if (C4::Context->preference("XSLTResultsDisplay") && !$scan) {
- $oldbiblio->{XSLTResultsRecord} = XSLTParse4Display(
- $oldbiblio->{biblionumber}, $marcrecord, 'Results' );
+ 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
+
}
# last check for norequest : if itemtype is notforloan, it can't be reserved either, whatever the items
$oldbiblio->{itemlostcount} = $itemlost_count;
$oldbiblio->{damagedcount} = $itemdamaged_count;
$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
# depending of operand, intersect, union or exclude both lists
# to get a result list
if ( $operator eq ' and ' ) {
- warn "NZAND";
return NZoperatorAND($leftresult,$rightresult);
}
elsif ( $operator eq ' or ' ) {
=item C<BUGS>
* 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
#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});
+ 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'));
if ($fieldname=~/\./){
my ($table,$column)=split /\./, $fieldname;
my $dbh = C4::Context->dbh;
- warn "select DISTINCT($column) as value, count(*) as cnt from $table group by lib order by $column ";
+ warn "select DISTINCT($column) as value, count(*) as cnt from $table group by lib order by $column " if $DEBUG;
my $sth = $dbh->prepare("select DISTINCT($column) as value, count(*) as cnt from $table ".($string?" where $column like \"$string%\"":"")."group by value order by $column ");
$sth->execute;
my $elements=$sth->fetchall_arrayref({});
=head1 AUTHOR
-Koha Developement team <info@koha.org>
+Koha Development Team <http://koha-community.org/>
=cut