&searchResults
&getRecords
&buildQuery
- &AddSearchHistory
&GetDistinctValues
&enabled_staff_search_views
&PurgeSearchHistory
my @results;
if (!defined $error) {
foreach my $possible_duplicate_record (@{$searchresults}) {
- my $marcrecord =
- MARC::Record->new_from_usmarc($possible_duplicate_record);
+ my $marcrecord = new_record_from_zebra(
+ 'biblioserver',
+ $possible_duplicate_record
+ );
+
my $result = TransformMarcToKoha( $dbh, $marcrecord, '' );
# FIXME :: why 2 $biblionumber ?
}
for my $j ( $first_record .. $last_record ) {
- my $record =
+ my $record = eval {
$tmpresults[ $i - 1 ]->record( $j - 1 )->raw()
; # 0 indexed
- push @{$results}, $record;
+ };
+ push @{$results}, $record if defined $record;
}
}
);
my $results_hashref = ();
# Initialize variables for the faceted results objects
- my $facets_counter = ();
- my $facets_info = ();
+ my $facets_counter = {};
+ my $facets_info = {};
my $facets = getFacets();
- my $facets_maxrecs = C4::Context->preference('maxRecordsForFacets')||20;
my @facets_loop; # stores the ref to array of hashes for template facets loop
warn "Ignoring unrecognized sort '$sort' requested" if $sort_by;
}
}
- if ($sort_by && !$scan) {
+ if ( $sort_by && !$scan && $results[$i] ) {
if ( $results[$i]->sort( "yaz", $sort_by ) < 0 ) {
warn "WARNING sort $sort_by failed";
}
else {
$times = $size;
}
+
for ( my $j = $offset ; $j < $times ; $j++ ) {
my $records_hash;
my $record;
## Check if it's an index scan
if ($scan) {
- my ( $term, $occ ) = $results[ $i - 1 ]->term($j);
+ my ( $term, $occ ) = $results[ $i - 1 ]->display_term($j);
# here we create a minimal MARC record and hand it off to the
# template just like a normal result ... perhaps not ideal, but
# not an index scan
else {
$record = $results[ $i - 1 ]->record($j)->raw();
-
# warn "RECORD $j:".$record;
$results_hash->{'RECORDS'}[$j] = $record;
}
}
$results_hashref->{ $servers[ $i - 1 ] } = $results_hash;
-# Fill the facets while we're looping, but only for the biblioserver and not for a scan
+ # Fill the facets while we're looping, but only for the
+ # biblioserver and not for a scan
if ( !$scan && $servers[ $i - 1 ] =~ /biblioserver/ ) {
-
- my $jmax =
- $size > $facets_maxrecs ? $facets_maxrecs : $size;
- for my $facet (@$facets) {
- for ( my $j = 0 ; $j < $jmax ; $j++ ) {
- my $render_record =
- $results[ $i - 1 ]->record($j)->render();
- my @used_datas = ();
- foreach my $tag ( @{ $facet->{tags} } ) {
-
- # avoid first line
- my $tag_num = substr( $tag, 0, 3 );
- my $letters = substr( $tag, 3 );
- my $field_pattern =
- '\n' . $tag_num . ' ([^z][^\n]+)';
- $field_pattern = '\n' . $tag_num . ' ([^\n]+)'
- if ( int($tag_num) < 10 );
- my @field_tokens =
- ( $render_record =~ /$field_pattern/g );
- foreach my $field_token (@field_tokens) {
- my @subf = ( $field_token =~
- /\$([a-zA-Z0-9]) ([^\$]+)/g );
- my @values;
- for ( my $i = 0 ; $i < @subf ; $i += 2 ) {
- if ( $letters =~ $subf[$i] ) {
- my $value = $subf[ $i + 1 ];
- $value =~ s/^ *//;
- $value =~ s/ *$//;
- push @values, $value;
- }
- }
- my $data = join( $facet->{sep}, @values );
- unless ( $data ~~ @used_datas ) {
- $facets_counter->{ $facet->{idx} }
- ->{$data}++;
- push @used_datas, $data;
- }
- } # fields
- } # field codes
- } # records
- $facets_info->{ $facet->{idx} }->{label_value} =
- $facet->{label};
- $facets_info->{ $facet->{idx} }->{expanded} =
- $facet->{expanded};
- } # facets
+ $facets_counter = GetFacets( $results[ $i - 1 ] );
+ $facets_info = _get_facets_info( $facets );
}
- # warn "connection ", $i-1, ": $size hits";
- # warn $results[$i-1]->record(0)->render() if $size > 0;
-
# BUILD FACETS
if ( $servers[ $i - 1 ] =~ /biblioserver/ ) {
for my $link_value (
)
{
$number_of_facets++;
- if ( ( $number_of_facets < 6 )
+ if ( ( $number_of_facets <= 5 )
|| ( $expanded_facet eq $link_value )
|| ( $facets_info->{$link_value}->{'expanded'} )
)
# handle expanded option
unless ( $facets_info->{$link_value}->{'expanded'} ) {
$expandable = 1
- if ( ( $number_of_facets > 6 )
+ if ( ( $number_of_facets > 5 )
&& ( $expanded_facet ne $link_value ) );
}
push @facets_loop,
return ( undef, $results_hashref, \@facets_loop );
}
+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 ) {
+ $facets = _get_facets_from_zebra( $rs );
+ } else {
+ $facets = _get_facets_from_records( $rs );
+ }
+
+ return $facets;
+}
+
+sub _get_facets_from_records {
+
+ my $rs = shift;
+
+ my $facets_maxrecs = C4::Context->preference('maxRecordsForFacets') // 20;
+ my $facets_config = getFacets();
+ my $facets = {};
+ my $size = $rs->size();
+ my $jmax = $size > $facets_maxrecs
+ ? $facets_maxrecs
+ : $size;
+
+ for ( my $j = 0 ; $j < $jmax ; $j++ ) {
+
+ my $marc_record = new_record_from_zebra (
+ 'biblioserver',
+ $rs->record( $j )->raw()
+ );
+
+ if ( ! defined $marc_record ) {
+ warn "ERROR DECODING RECORD - $@: " .
+ $rs->record( $j )->raw();
+ next;
+ }
+
+ _get_facets_data_from_record( $marc_record, $facets_config, $facets );
+ }
+
+ return $facets;
+}
+
+=head2 _get_facets_data_from_record
+
+ C4::Search::_get_facets_data_from_record( $marc_record, $facets, $facets_counter );
+
+Internal function that extracts facets information from a MARC::Record object
+and populates $facets_counter for using in getRecords.
+
+$facets is expected to be filled with C4::Koha::getFacets output (i.e. the configured
+facets for Zebra).
+
+=cut
+
+sub _get_facets_data_from_record {
+
+ my ( $marc_record, $facets, $facets_counter ) = @_;
+
+ for my $facet (@$facets) {
+
+ my @used_datas = ();
+
+ foreach my $tag ( @{ $facet->{ tags } } ) {
+
+ # tag number is the first three digits
+ my $tag_num = substr( $tag, 0, 3 );
+ # subfields are the remainder
+ my $subfield_letters = substr( $tag, 3 );
+
+ my @fields = $marc_record->field( $tag_num );
+ foreach my $field (@fields) {
+ # If $field->indicator(1) eq 'z', it means it is a 'see from'
+ # field introduced because of IncludeSeeFromInSearches, so skip it
+ next if $field->indicator(1) eq 'z';
+
+ my $data = $field->as_string( $subfield_letters, $facet->{ sep } );
+
+ unless ( grep { /^\Q$data\E$/ } @used_datas ) {
+ push @used_datas, $data;
+ $facets_counter->{ $facet->{ idx } }->{ $data }++;
+ }
+ }
+ }
+ }
+}
+
+=head2 _get_facets_from_zebra
+
+ my $facets = _get_facets_from_zebra( $result_set )
+
+Retrieves facets for a specified result set. It loops through the facets defined
+in C4::Koha::getFacets and returns a hash with the following structure:
+
+ { facet_idx => {
+ facet_value => count
+ },
+ ...
+ }
+
+=cut
+
+sub _get_facets_from_zebra {
+
+ my $rs = shift;
+
+ # save current elementSetName
+ my $elementSetName = $rs->option( 'elementSetName' );
+
+ my $facets_loop = getFacets();
+ my $facets_data = {};
+ # loop through defined facets and fill the facets hashref
+ foreach my $facet ( @$facets_loop ) {
+
+ my $idx = $facet->{ idx };
+ my $sep = $facet->{ sep };
+ my $facet_values = _get_facet_from_result_set( $idx, $rs, $sep );
+ if ( $facet_values ) {
+ # we've actually got a result
+ $facets_data->{ $idx } = $facet_values;
+ }
+ }
+ # set elementSetName to its previous value to avoid side effects
+ $rs->option( elementSetName => $elementSetName );
+
+ return $facets_data;
+}
+
+=head2 _get_facet_from_result_set
+
+ my $facet_values =
+ C4::Search::_get_facet_from_result_set( $facet_idx, $result_set, $sep )
+
+Internal function that extracts facet information for a specific index ($facet_idx) and
+returns a hash containing facet values and count:
+
+ {
+ $facet_value => $count ,
+ ...
+ }
+
+Warning: this function has the side effect of changing the elementSetName for the result
+set. It is a helper function for the main loop, which takes care of backing it up for
+restoring.
+
+=cut
+
+sub _get_facet_from_result_set {
+
+ my $facet_idx = shift;
+ my $rs = shift;
+ my $sep = shift;
+
+ my $internal_sep = '<*>';
+ my $facetMaxCount = C4::Context->preference('FacetMaxCount') // 20;
+
+ return if ( ! defined $facet_idx || ! defined $rs );
+ # zebra's facet element, untokenized index
+ my $facet_element = 'zebra::facet::' . $facet_idx . ':0:' . $facetMaxCount;
+ # configure zebra results for retrieving the desired facet
+ $rs->option( elementSetName => $facet_element );
+ # get the facet record from result set
+ my $facet = $rs->record( 0 )->raw;
+ # if the facet has no restuls...
+ return if !defined $facet;
+ # TODO: benchmark DOM vs. SAX performance
+ my $facet_dom = XML::LibXML->load_xml(
+ string => ($facet)
+ );
+ my @terms = $facet_dom->getElementsByTagName('term');
+ return if ! @terms;
+
+ my $facets = {};
+ foreach my $term ( @terms ) {
+ my $facet_value = $term->textContent;
+ $facet_value =~ s/\Q$internal_sep\E/$sep/ if defined $sep;
+ $facets->{ $facet_value } = $term->getAttribute( 'occur' );
+ }
+
+ return $facets;
+}
+
+=head2 _get_facets_info
+
+ my $facets_info = C4::Search::_get_facets_info( $facets )
+
+Internal function that extracts facets information and properly builds
+the data structure needed to render facet labels.
+
+=cut
+
+sub _get_facets_info {
+
+ my $facets = shift;
+
+ my $facets_info = {};
+
+ for my $facet ( @$facets ) {
+ $facets_info->{ $facet->{ idx } }->{ label_value } = $facet->{ label };
+ $facets_info->{ $facet->{ idx } }->{ expanded } = $facet->{ expanded };
+ }
+
+ return $facets_info;
+}
+
sub pazGetRecords {
my (
$koha_query, $simple_query, $sort_by_ref, $servers_ref,
"Title-cover,ext,r1=\"$operand\""; # exact title-cover
$weighted_query .= " or ti,ext,r2=\"$operand\""; # exact title
$weighted_query .= " or Title-cover,phr,r3=\"$operand\""; # phrase title
+ $weighted_query .= " or ti,wrdl,r4=\"$operand\""; # words in title
#$weighted_query .= " or any,ext,r4=$operand"; # exact any
#$weighted_query .=" or kw,wrdl,r5=\"$operand\""; # word list any
$weighted_query .= " or wrdl,fuzzy,r8=\"$operand\""
'Corporate-name-seealso',
'Country-publication',
'ctype',
+ 'curriculum',
'date-entered-on-file',
'Date-of-acquisition',
'Date-of-publication',
'Dewey-classification',
+ 'Dissertation-information',
'EAN',
'extent',
'fic',
'Host-item',
'id-other',
'Illustration-code',
+ 'Index-term-genre',
+ 'Index-term-uncontrolled',
'ISBN',
'isbn',
'ISSN',
'lc-card',
'LC-card-number',
'lcn',
+ 'lex',
'llength',
'ln',
+ 'ln-audio',
+ 'ln-subtitle',
'Local-classification',
'Local-number',
'Match-heading',
'su-to',
'su-ut',
'ut',
- 'UPC',
'Term-genre-form',
'Term-genre-form-heading',
'Term-genre-form-see',
'Title',
'Title-cover',
'Title-series',
- 'Title-host',
'Title-uniform',
'Title-uniform-heading',
'Title-uniform-see',
'mc-itype',
'mc-loc',
'notforloan',
+ 'Number-local-acquisition',
'onloan',
'price',
'renewals',
my $index = $indexes[$i];
# Add index-specific attributes
+
+ #Afaik, this 'yr' condition will only ever be met in the staff client advanced search
+ #for "Publication date", since typing 'yr:YYYY' into the search box produces a CCL query,
+ #which is processed higher up in this sub. Other than that, year searches are typically
+ #handled as limits which are not processed her either.
+
# Date of Publication
- if ( $index eq 'yr' ) {
- $index .= ",st-numeric";
- $indexes_set++;
+ if ( $index =~ /yr/ ) {
+ #weight_fields/relevance search causes errors with date ranges
+ #In the case of YYYY-, it will only return records with a 'yr' of YYYY (not the range)
+ #In the case of YYYY-YYYY, it will return no results
$stemming = $auto_truncation = $weight_fields = $fuzzy_enabled = $remove_stopwords = 0;
}
# Date of Acquisition
- elsif ( $index eq 'acqdate' ) {
- $index .= ",st-date-normalized";
- $indexes_set++;
+ elsif ( $index =~ /acqdate/ ) {
+ #stemming and auto_truncation would have zero impact since it already is YYYY-MM-DD format
+ #Weight_fields probably SHOULD be turned OFF, otherwise you'll get records floating to the
+ #top of the results just because they have lots of item records matching that date.
+ #Fuzzy actually only applies during _build_weighted_query, and is reset there anyway, so
+ #irrelevant here
+ #remove_stopwords doesn't function anymore so is irrelevant
$stemming = $auto_truncation = $weight_fields = $fuzzy_enabled = $remove_stopwords = 0;
}
# ISBN,ISSN,Standard Number, don't need special treatment
warn "FIELD WEIGHTED OPERAND: >$weighted_operand<" if $DEBUG;
- # If there's a previous operand, we need to add an operator
- if ($previous_operand) {
-
- # User-specified operator
- if ( $operators[ $i - 1 ] ) {
- $query .= " $operators[$i-1] ";
- $query .= " $index_plus " unless $indexes_set;
- $query .= " $operand";
- $query_cgi .= "&op=".uri_escape($operators[$i-1]);
- $query_cgi .= "&idx=".uri_escape($index) if $index;
- $query_cgi .= "&q=".uri_escape($operands[$i]) if $operands[$i];
- $query_desc .=
- " $operators[$i-1] $index_plus $operands[$i]";
- }
+ ($query,$query_cgi,$query_desc,$previous_operand) = _build_initial_query({
+ query => $query,
+ query_cgi => $query_cgi,
+ query_desc => $query_desc,
+ operator => ($operators[ $i - 1 ]) ? $operators[ $i - 1 ] : '',
+ parsed_operand => $operand,
+ original_operand => ($operands[$i]) ? $operands[$i] : '',
+ index => $index,
+ index_plus => $index_plus,
+ indexes_set => $indexes_set,
+ previous_operand => $previous_operand,
+ });
- # Default operator is and
- else {
- $query .= " and ";
- $query .= "$index_plus " unless $indexes_set;
- $query .= "$operand";
- $query_cgi .= "&op=and&idx=".uri_escape($index) if $index;
- $query_cgi .= "&q=".uri_escape($operands[$i]) if $operands[$i];
- $query_desc .= " and $index_plus $operands[$i]";
- }
- }
-
- # There isn't a pervious operand, don't need an operator
- else {
-
- # Field-weighted queries already have indexes set
- $query .= " $index_plus " unless $indexes_set;
- $query .= $operand;
- $query_desc .= " $index_plus $operands[$i]";
- $query_cgi .= "&idx=".uri_escape($index) if $index;
- $query_cgi .= "&q=".uri_escape($operands[$i]) if $operands[$i];
- $previous_operand = 1;
- }
} #/if $operands
} # /for
}
$group_OR_limits{$k} .= " or " if $group_OR_limits{$k};
$limit_desc .= " or " if $group_OR_limits{$k};
$group_OR_limits{$k} .= "$this_limit";
- $limit_cgi .= "&limit=$this_limit";
+ $limit_cgi .= "&limit=" . uri_escape($this_limit);
$limit_desc .= " $this_limit";
}
else {
$limit .= " and " if $limit || $query;
$limit .= "$this_limit";
- $limit_cgi .= "&limit=$this_limit";
+ $limit_cgi .= "&limit=" . uri_escape($this_limit);
if ($this_limit =~ /^branch:(.+)/) {
my $branchcode = $1;
my $branchname = GetBranchName($branchcode);
# 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;
+ #NOTE: We use several several different regexps here as you can't have variable length lookback assertions
$query =~ s/(?<=(ti|au|pb|su|an|kw|mc|nb|ns)):/=/g;
$query =~ s/(?<=(wrdl)):/=/g;
$query =~ s/(?<=(trn|phr)):/=/g;
+ $query =~ s/(?<=(st-numeric)):/=/g;
+ $query =~ s/(?<=(st-year)):/=/g;
+ $query =~ s/(?<=(st-date-normalized)):/=/g;
$limit =~ s/:/=/g;
for ( $query, $query_desc, $limit, $limit_desc ) {
s/ +/ /g; # remove extra spaces
);
}
+=head2 _build_initial_query
+
+ ($query, $query_cgi, $query_desc, $previous_operand) = _build_initial_query($initial_query_params);
+
+ Build a section of the initial query containing indexes, operators, and operands.
+
+=cut
+
+sub _build_initial_query {
+ my ($params) = @_;
+
+ my $operator = "";
+ if ($params->{previous_operand}){
+ #If there is a previous operand, add a supplied operator or the default 'and'
+ $operator = ($params->{operator}) ? " ".($params->{operator})." " : ' and ';
+ }
+
+ #NOTE: indexes_set is typically set when doing truncation or field weighting
+ my $operand = ($params->{indexes_set}) ? $params->{parsed_operand} : $params->{index_plus}.$params->{parsed_operand};
+
+ #e.g. "kw,wrdl:test"
+ #e.g. " and kw,wrdl:test"
+ $params->{query} .= $operator . $operand;
+
+ $params->{query_cgi} .= "&op=".uri_escape($operator) if $operator;
+ $params->{query_cgi} .= "&idx=".uri_escape($params->{index}) if $params->{index};
+ $params->{query_cgi} .= "&q=".uri_escape($params->{original_operand}) if $params->{original_operand};
+
+ #e.g. " and kw,wrdl: test"
+ $params->{query_desc} .= $operator . $params->{index_plus} . " " . $params->{original_operand};
+
+ $params->{previous_operand} = 1 unless $params->{previous_operand}; #If there is no previous operand, mark this as one
+
+ return ($params->{query}, $params->{query_cgi}, $params->{query_desc}, $params->{previous_operand});
+}
+
=head2 searchResults
my @search_results = searchResults($search_context, $searchdesc, $hits,
$times = $hits; # FIXME: if $hits is undefined, why do we want to equal it?
}
- my $marcflavour = C4::Context->preference("marcflavour");
+ my $marcflavour = C4::Context->preference("marcflavour");
# We get the biblionumber position in MARC
my ($bibliotag,$bibliosubf)=GetMarcFromKohaField('biblio.biblionumber','');
# loop through all of the records we've retrieved
for ( my $i = $offset ; $i <= $times - 1 ; $i++ ) {
- my $marcrecord = eval { MARC::File::USMARC::decode( $marcresults->[$i] ); };
- if ( $@ ) {
- warn "ERROR DECODING RECORD - $@: " . $marcresults->[$i];
- next;
+
+ my $marcrecord;
+ if ($scan) {
+ # For Scan searches we built USMARC data
+ $marcrecord = MARC::Record->new_from_usmarc( $marcresults->[$i]);
+ } else {
+ # Normal search, render from Zebra's output
+ $marcrecord = new_record_from_zebra(
+ 'biblioserver',
+ $marcresults->[$i]
+ );
+
+ if ( ! defined $marcrecord ) {
+ warn "ERROR DECODING RECORD - $@: " . $marcresults->[$i];
+ next;
+ }
}
my $fw = $scan
my $item_in_transit_count = 0;
my $can_place_holds = 0;
my $item_onhold_count = 0;
+ my $notforloan_count = 0;
my $items_count = scalar(@fields);
my $maxitems_pref = C4::Context->preference('maxItemsinSearchResults');
my $maxitems = $maxitems_pref ? $maxitems_pref - 1 : 1;
}
}
- my $hbranch = C4::Context->preference('HomeOrHoldingBranch') eq 'homebranch' ? 'homebranch' : 'holdingbranch';
- my $otherbranch = C4::Context->preference('HomeOrHoldingBranch') eq 'homebranch' ? 'holdingbranch' : 'homebranch';
+ my $hbranch = C4::Context->preference('StaffSearchResultsDisplayBranch');
+ my $otherbranch = $hbranch eq 'homebranch' ? 'holdingbranch' : 'homebranch';
# set item's branch name, use HomeOrHoldingBranch syspref first, fall back to the other one
if ($item->{$hbranch}) {
# item is on order
if ( $item->{notforloan} < 0 ) {
$ordered_count++;
+ } elsif ( $item->{notforloan} > 0 ) {
+ $notforloan_count++;
}
# is item in transit?
}
# XSLT processing of some stuff
- use C4::Charset;
- SetUTF8Flag($marcrecord);
+ SetUTF8Flag($marcrecord);
warn $marcrecord->as_formatted if $DEBUG;
- my $interface = $search_context eq 'opac' ? 'OPAC' : '';
- if (!$scan && C4::Context->preference($interface . "XSLTResultsDisplay")) {
+ my $interface = $search_context eq 'opac' ? 'OPAC' : '';
+ if (!$scan && C4::Context->preference($interface . "XSLTResultsDisplay")) {
$oldbiblio->{XSLTResultsRecord} = XSLTParse4Display($oldbiblio->{biblionumber}, $marcrecord, $interface."XSLTResultsDisplay", 1, \@hiddenitems);
- # the last parameter tells Koha to clean up the problematic ampersand entities that Zebra outputs
+ # 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
$oldbiblio->{intransitcount} = $item_in_transit_count;
$oldbiblio->{onholdcount} = $item_onhold_count;
$oldbiblio->{orderedcount} = $ordered_count;
+ $oldbiblio->{notforloancount} = $notforloan_count;
if (C4::Context->preference("AlternateHoldingsField") && $items_count == 0) {
my $fieldspec = C4::Context->preference("AlternateHoldingsField");
);
}
-sub AddSearchHistory{
- my ($borrowernumber,$session,$query_desc,$query_cgi, $total)=@_;
- my $dbh = C4::Context->dbh;
-
- # Add the request the user just made
- my $sql = "INSERT INTO search_history(userid, sessionid, query_desc, query_cgi, total, time) VALUES(?, ?, ?, ?, ?, NOW())";
- my $sth = $dbh->prepare($sql);
- $sth->execute($borrowernumber, $session, $query_desc, $query_cgi, $total);
- return $dbh->last_insert_id(undef, 'search_history', undef,undef,undef);
-}
-
-sub GetSearchHistory{
- my ($borrowernumber,$session)=@_;
- my $dbh = C4::Context->dbh;
-
- # Add the request the user just made
- my $query = "SELECT FROM search_history WHERE (userid=? OR sessionid=?)";
- my $sth = $dbh->prepare($query);
- $sth->execute($borrowernumber, $session);
- return $sth->fetchall_hashref({});
-}
-
sub PurgeSearchHistory{
my ($pSearchhistory)=@_;
my $dbh = C4::Context->dbh;
This function returns an array reference that contains the search parameters to be
passed to the Z39.50 search script (z3950_search.pl). The array elements
-are hash refs whose keys are name, value and encvalue, and whose values are the
+are hash refs whose keys are name and value, and whose values are the
name of a search parameter, the value of that search parameter and the URL encoded
value of that parameter.
If $matchpoints is a scalar, it is assumed to be an unnamed query descriptor, e.g.
a general purpose search argument. In this case, the returned array contains only
-entry: the key is 'title' and the value and encvalue are derived from $matchpoints.
+entry: the key is 'title' and the value is derived from $matchpoints.
If a search parameter value is undefined or empty, it is not included in the returned
array.
sub z3950_search_args {
my $bibrec = shift;
- my $isbn = Business::ISBN->new($bibrec);
+
+ my $isbn_string = ref( $bibrec ) ? $bibrec->{title} : $bibrec;
+ my $isbn = Business::ISBN->new( $isbn_string );
if (defined $isbn && $isbn->is_valid)
{
- $bibrec = { isbn => $bibrec } if !ref $bibrec;
+ if ( ref($bibrec) ) {
+ $bibrec->{isbn} = $isbn_string;
+ $bibrec->{title} = undef;
+ } else {
+ $bibrec = { isbn => $isbn_string };
+ }
}
else {
$bibrec = { title => $bibrec } if !ref $bibrec;
my $array = [];
for my $field (qw/ lccn isbn issn title author dewey subject /)
{
- my $encvalue = URI::Escape::uri_escape_utf8($bibrec->{$field});
- push @$array, { name=>$field, value=>$bibrec->{$field}, encvalue=>$encvalue } if defined $bibrec->{$field};
+ push @$array, { name => $field, value => $bibrec->{$field} }
+ if defined $bibrec->{$field};
}
return $array;
}
}
}
+=head2 new_record_from_zebra
+
+Given raw data from a Zebra result set, return a MARC::Record object
+
+This helper function is needed to take into account all the involved
+system preferences and configuration variables to properly create the
+MARC::Record object.
+
+If we are using GRS-1, then the raw data we get from Zebra should be USMARC
+data. If we are using DOM, then it has to be MARCXML.
+
+=cut
+
+sub new_record_from_zebra {
+
+ my $server = shift;
+ my $raw_data = shift;
+ # Set the default indexing modes
+ my $index_mode = ( $server eq 'biblioserver' )
+ ? C4::Context->config('zebra_bib_index_mode') // 'dom'
+ : C4::Context->config('zebra_auth_index_mode') // 'dom';
+
+ my $marc_record = eval {
+ if ( $index_mode eq 'dom' ) {
+ MARC::Record->new_from_xml( $raw_data, 'UTF-8' );
+ } else {
+ MARC::Record->new_from_usmarc( $raw_data );
+ }
+ };
+
+ if ($@) {
+ return;
+ } else {
+ return $marc_record;
+ }
+
+}
END { } # module clean-up code here (global destructor)