use C4::Members qw(GetHideLostItemsPreference);
use C4::XSLT;
use C4::Branch;
-use C4::Reserves; # CheckReserves
+use C4::Reserves; # GetReserveStatus
use C4::Debug;
use C4::Charset;
use YAML;
if ( $result->{isbn} ) {
$result->{isbn} =~ s/\(.*$//;
$result->{isbn} =~ s/\s+$//;
- $query = "isbn=$result->{isbn}";
+ $query = "isbn:$result->{isbn}";
}
else {
+ my $QParser;
+ $QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser'));
+ my $titleindex;
+ my $authorindex;
+ my $op;
+
+ if ($QParser) {
+ $titleindex = 'title|exact';
+ $authorindex = 'author|exact';
+ $op = '&&';
+ } else {
+ $titleindex = 'ti,ext';
+ $authorindex = 'au,ext';
+ $op = 'and';
+ }
+
$result->{title} =~ s /\\//g;
$result->{title} =~ s /\"//g;
$result->{title} =~ s /\(//g;
# FIXME: instead of removing operators, could just do
# quotes around the value
$result->{title} =~ s/(and|or|not)//g;
- $query = "ti,ext=$result->{title}";
- $query .= " and itemtype=$result->{itemtype}"
- if ( $result->{itemtype} );
+ $query = "$titleindex:\"$result->{title}\"";
if ( $result->{author} ) {
$result->{author} =~ s /\\//g;
$result->{author} =~ s /\"//g;
# remove valid operators
$result->{author} =~ s/(and|or|not)//g;
- $query .= " and au,ext=$result->{author}";
+ $query .= " $op $authorindex:\"$result->{author}\"";
}
}
my $results = [];
my $total_hits = 0;
+ my $QParser;
+ $QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser') && ! ($query =~ m/\w,\w|\w=\w/));
+
# Initialize & Search Zebra
for ( my $i = 0 ; $i < @servers ; $i++ ) {
eval {
$zconns[$i] = C4::Context->Zconn( $servers[$i], 1 );
- $zoom_queries[$i] = new ZOOM::Query::CCL2RPN( $query, $zconns[$i]);
+ if ($QParser) {
+ $query =~ s/=/:/g;
+ $QParser->parse( $query );
+ $query = $QParser->target_syntax($servers[$i]);
+ $zoom_queries[$i] = new ZOOM::Query::PQF( $query, $zconns[$i]);
+ } else {
+ $zoom_queries[$i] = new ZOOM::Query::CCL2RPN( $query, $zconns[$i]);
+ }
$tmpresults[$i] = $zconns[$i]->search( $zoom_queries[$i] );
# error handling
return ( $error, undef, undef );
}
}
- while ( ( my $i = ZOOM::event( \@zconns ) ) != 0 ) {
- my $event = $zconns[ $i - 1 ]->last_event();
- if ( $event == ZOOM::Event::ZEND ) {
- my $first_record = defined( $offset ) ? $offset+1 : 1;
+ _ZOOM_event_loop(
+ \@zconns,
+ \@tmpresults,
+ sub {
+ my ($i, $size) = @_;
+ my $first_record = defined($offset) ? $offset + 1 : 1;
my $hits = $tmpresults[ $i - 1 ]->size();
$total_hits += $hits;
my $last_record = $hits;
if ( defined $max_results && $offset + $max_results < $hits ) {
- $last_record = $offset + $max_results;
+ $last_record = $offset + $max_results;
}
- for my $j ( $first_record..$last_record ) {
- my $record = $tmpresults[ $i - 1 ]->record( $j-1 )->raw(); # 0 indexed
+ for my $j ( $first_record .. $last_record ) {
+ my $record =
+ $tmpresults[ $i - 1 ]->record( $j - 1 )->raw()
+ ; # 0 indexed
push @{$results}, $record;
}
}
- }
+ );
- foreach my $result (@tmpresults) {
- $result->destroy();
- }
foreach my $zoom_query (@zoom_queries) {
$zoom_query->destroy();
}
} # finished looping through servers
# The big moment: asynchronously retrieve results from all servers
- while ( ( my $i = ZOOM::event( \@zconns ) ) != 0 ) {
- my $ev = $zconns[ $i - 1 ]->last_event();
- if ( $ev == ZOOM::Event::ZEND ) {
- next unless $results[ $i - 1 ];
- my $size = $results[ $i - 1 ]->size();
- if ( $size > 0 ) {
+ _ZOOM_event_loop(
+ \@zconns,
+ \@results,
+ sub {
+ my ( $i, $size ) = @_;
my $results_hash;
# loop through the results
my $tmpauthor;
# the minimal record in author/title (depending on MARC flavour)
- if (C4::Context->preference("marcflavour") eq "UNIMARC") {
- $tmptitle = MARC::Field->new('200',' ',' ', a => $term, f => $occ);
+ if ( C4::Context->preference("marcflavour") eq
+ "UNIMARC" )
+ {
+ $tmptitle = MARC::Field->new(
+ '200', ' ', ' ',
+ a => $term,
+ f => $occ
+ );
$tmprecord->append_fields($tmptitle);
- } else {
- $tmptitle = MARC::Field->new('245',' ',' ', a => $term,);
- $tmpauthor = MARC::Field->new('100',' ',' ', a => $occ,);
+ }
+ else {
+ $tmptitle =
+ MARC::Field->new( '245', ' ', ' ', a => $term, );
+ $tmpauthor =
+ MARC::Field->new( '100', ' ', ' ', a => $occ, );
$tmprecord->append_fields($tmptitle);
$tmprecord->append_fields($tmpauthor);
}
- $results_hash->{'RECORDS'}[$j] = $tmprecord->as_usmarc();
+ $results_hash->{'RECORDS'}[$j] =
+ $tmprecord->as_usmarc();
}
# not an index scan
}
$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 $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}} ) {
+ 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 ) ;
+ 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 @subf = ( $field_token =~
+ /\$([a-zA-Z0-9]) ([^\$]+)/g );
my @values;
- for (my $i = 0; $i < @subf; $i += 2) {
+ 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 $value = $subf[ $i + 1 ];
+ $value =~ s/^ *//;
+ $value =~ s/ *$//;
+ push @values, $value;
}
}
- my $data = join($facet->{sep}, @values);
+ my $data = join( $facet->{sep}, @values );
unless ( $data ~~ @used_datas ) {
- $facets_counter->{ $facet->{idx} }->{$data}++;
+ $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
+ } # fields
+ } # field codes
+ } # records
+ $facets_info->{ $facet->{idx} }->{label_value} =
+ $facet->{label};
+ $facets_info->{ $facet->{idx} }->{expanded} =
+ $facet->{expanded};
+ } # facets
}
- }
- # warn "connection ", $i-1, ": $size hits";
- # warn $results[$i-1]->record(0)->render() if $size > 0;
+ # 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 (
- sort { $facets_counter->{$b} <=> $facets_counter->{$a} }
- 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}
- } keys %{ $facets_counter->{$link_value} }
+ # BUILD FACETS
+ if ( $servers[ $i - 1 ] =~ /biblioserver/ ) {
+ for my $link_value (
+ sort { $facets_counter->{$b} <=> $facets_counter->{$a} }
+ keys %$facets_counter
)
{
- $number_of_facets++;
- if ( ( $number_of_facets < 6 )
- || ( $expanded_facet eq $link_value )
- || ( $facets_info->{$link_value}->{'expanded'} ) )
+ 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}
+ } keys %{ $facets_counter->{$link_value} }
+ )
{
+ $number_of_facets++;
+ if ( ( $number_of_facets < 6 )
+ || ( $expanded_facet eq $link_value )
+ || ( $facets_info->{$link_value}->{'expanded'} )
+ )
+ {
+
+# Sanitize the link value : parenthesis, question and exclamation mark will cause errors with CCL
+ my $facet_link_value = $one_facet;
+ $facet_link_value =~ s/[()!?¡¿؟]/ /g;
+
+ # fix the length that will display in the label,
+ my $facet_label_value = $one_facet;
+ my $facet_max_length = C4::Context->preference(
+ 'FacetLabelTruncationLength')
+ || 20;
+ $facet_label_value =
+ substr( $one_facet, 0, $facet_max_length )
+ . "..."
+ if length($facet_label_value) >
+ $facet_max_length;
- # Sanitize the link value ), ( will cause errors with CCL,
- my $facet_link_value = $one_facet;
- $facet_link_value =~ s/(\(|\))/ /g;
+ # if it's a branch, label by the name, not the code,
+ if ( $link_value =~ /branch/ ) {
+ if ( defined $branches
+ && ref($branches) eq "HASH"
+ && defined $branches->{$one_facet}
+ && ref( $branches->{$one_facet} ) eq
+ "HASH" )
+ {
+ $facet_label_value =
+ $branches->{$one_facet}
+ ->{'branchname'};
+ }
+ else {
+ $facet_label_value = "*";
+ }
+ }
- # fix the length that will display in the label,
- my $facet_label_value = $one_facet;
- my $facet_max_length =
- C4::Context->preference('FacetLabelTruncationLength') || 20;
- $facet_label_value =
- substr( $one_facet, 0, $facet_max_length ) . "..."
- if length($facet_label_value) > $facet_max_length;
+ # if it's a itemtype, label by the name, not the code,
+ if ( $link_value =~ /itype/ ) {
+ if ( defined $itemtypes
+ && ref($itemtypes) eq "HASH"
+ && defined $itemtypes->{$one_facet}
+ && ref( $itemtypes->{$one_facet} ) eq
+ "HASH" )
+ {
+ $facet_label_value =
+ $itemtypes->{$one_facet}
+ ->{'description'};
+ }
+ }
- # if it's a branch, label by the name, not the code,
- if ( $link_value =~ /branch/ ) {
- if (defined $branches
- && ref($branches) eq "HASH"
- && defined $branches->{$one_facet}
- && ref ($branches->{$one_facet}) eq "HASH")
- {
- $facet_label_value =
- $branches->{$one_facet}->{'branchname'};
- }
- else {
- $facet_label_value = "*";
- }
- }
- # if it's a itemtype, label by the name, not the code,
- if ( $link_value =~ /itype/ ) {
- if (defined $itemtypes
- && ref($itemtypes) eq "HASH"
- && defined $itemtypes->{$one_facet}
- && ref ($itemtypes->{$one_facet}) eq "HASH")
- {
+ # also, if it's a location code, use the name instead of the code
+ if ( $link_value =~ /location/ ) {
$facet_label_value =
- $itemtypes->{$one_facet}->{'description'};
+ GetKohaAuthorisedValueLib( 'LOC',
+ $one_facet, $opac );
}
- }
- # also, if it's a location code, use the name instead of the code
- if ( $link_value =~ /location/ ) {
- $facet_label_value = GetKohaAuthorisedValueLib('LOC', $one_facet, $opac);
+ # 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,
+ }
+ if ($facet_label_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,
- } if ( $facet_label_value );
}
- }
- # handle expanded option
- unless ( $facets_info->{$link_value}->{'expanded'} ) {
- $expandable = 1
- if ( ( $number_of_facets > 6 )
- && ( $expanded_facet ne $link_value ) );
+ # handle expanded option
+ unless ( $facets_info->{$link_value}->{'expanded'} ) {
+ $expandable = 1
+ 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')) );
}
}
- }
- }
+ );
return ( undef, $results_hashref, \@facets_loop );
}
=cut
sub _handle_exploding_index {
- my ( $index, $term ) = @_;
+ my ($QParser, $struct, $filter, $params, $negate, $server) = @_;
+ my $index = $filter;
+ my $term = join(' ', @$params);
return unless ($index =~ m/(su-br|su-na|su-rl)/ && $term);
my $codesubfield = $marcflavour eq 'UNIMARC' ? '5' : 'w';
my $wantedcodes = '';
- my @subqueries = ( "(su=\"$term\")");
- my ($error, $results, $total_hits) = SimpleSearch( "Heading,wrdl=$term", undef, undef, [ "authorityserver" ] );
+ my @subqueries = ( "su:\"$term\"");
+ my ($error, $results, $total_hits) = SimpleSearch( "he:$term", undef, undef, [ "authorityserver" ] );
foreach my $auth (@$results) {
my $record = MARC::Record->new_from_usmarc($auth);
my @references = $record->field('5..');
}
foreach my $reference (@references) {
my $codes = $reference->subfield($codesubfield);
- push @subqueries, '(su="' . $reference->as_string('abcdefghijlmnopqrstuvxyz') . '")' if (($codes && $codes eq $wantedcodes) || !$wantedcodes);
+ push @subqueries, 'su:"' . $reference->as_string('abcdefghijlmnopqrstuvxyz') . '"' if (($codes && $codes eq $wantedcodes) || !$wantedcodes);
}
}
}
- return join(' or ', @subqueries);
+ my $query = '(' x scalar(@subqueries) . join(') || ', @subqueries) . ')';
+ warn $query;
+ return $query;
}
=head2 parseQuery
my $query = $operands[0];
my $index;
my $term;
+ my $query_desc;
-# TODO: once we are using QueryParser, all this special case code for
-# exploded search indexes will be replaced by a callback to
-# _handle_exploding_index
- if ( $query =~ m/^(.*)\b(su-br|su-na|su-rl)[:=](\w.*)$/ ) {
- $query = $1;
- $index = $2;
- $term = $3;
- } else {
+ my $QParser;
+ $QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser') || $query =~ s/^qp=//);
+ undef $QParser if ($query =~ m/^(ccl=|pqf=|cql=)/ || grep (/\w,\w|\w=\w/, @operands) );
+
+ if ($QParser)
+ {
$query = '';
- for ( my $i = 0 ; $i <= @operands ; $i++ ) {
- if ($operands[$i] && $indexes[$i] =~ m/(su-br|su-na|su-rl)/) {
- $index = $indexes[$i];
- $term = $operands[$i];
- } elsif ($operands[$i]) {
- $query .= $operators[$i] eq 'or' ? ' or ' : ' and ' if ($query);
- $query .= "($indexes[$i]:$operands[$i])";
- }
+ for ( my $ii = 0 ; $ii <= @operands ; $ii++ ) {
+ next unless $operands[$ii];
+ $query .= $operators[ $ii - 1 ] eq 'or' ? ' || ' : ' && '
+ if ($query);
+ $query .=
+ ( $indexes[$ii] ? "$indexes[$ii]:" : '' ) . $operands[$ii];
+ }
+ foreach my $limit (@limits) {
+ }
+ foreach my $modifier (@sort_by) {
+ $query .= " #$modifier";
}
- }
- if ($index) {
- my $queryPart = _handle_exploding_index($index, $term);
- if ($queryPart) {
- $query .= "($queryPart)";
+ $query_desc = $query;
+ if ( C4::Context->preference("QueryWeightFields") ) {
}
- $operators = ();
- $operands[0] = "ccl=$query";
+ $QParser->add_bib1_filter_map( 'biblioserver', 'su-br', { 'callback' => \&_handle_exploding_index });
+ $QParser->add_bib1_filter_map( 'biblioserver', 'su-na', { 'callback' => \&_handle_exploding_index });
+ $QParser->add_bib1_filter_map( 'biblioserver', 'su-rl', { 'callback' => \&_handle_exploding_index });
+ $QParser->parse( $query );
+ $operands[0] = "pqf=" . $QParser->target_syntax('biblioserver');
+# TODO: once we are using QueryParser, all this special case code for
+# exploded search indexes will be replaced by a callback to
+# _handle_exploding_index
}
- return ( $operators, \@operands, $indexes, $limits, $sort_by, $scan, $lang);
+ return ( $operators, \@operands, $indexes, $limits, $sort_by, $scan, $lang, $query_desc);
}
=head2 buildQuery
warn "---------\nEnter buildQuery\n---------" if $DEBUG;
- ( $operators, $operands, $indexes, $limits, $sort_by, $scan, $lang) = parseQuery($operators, $operands, $indexes, $limits, $sort_by, $scan, $lang);
+ my $query_desc;
+ ( $operators, $operands, $indexes, $limits, $sort_by, $scan, $lang, $query_desc) = parseQuery($operators, $operands, $indexes, $limits, $sort_by, $scan, $lang);
# dereference
my @operators = $operators ? @$operators : ();
# initialize the variables we're passing back
my $query_cgi;
- my $query_desc;
my $query_type;
my $limit;
return ( undef, $', $', "q=cql=$'", $', '', '', '', '', 'cql' );
}
if ( $query =~ /^pqf=/ ) {
- return ( undef, $', $', "q=pqf=$'", $', '', '', '', '', 'pqf' );
+ if ($query_desc) {
+ $query_cgi = "q=$query_desc";
+ } else {
+ $query_desc = $';
+ $query_cgi = "q=pqf=$'";
+ }
+ return ( undef, $', $', $query_cgi, $query_desc, '', '', '', '', 'pqf' );
}
# pass nested queries directly
else {
# item is on order
- if ( $item->{notforloan} == -1 ) {
+ if ( $item->{notforloan} < 0 ) {
$ordered_count++;
}
my ($transfertfrom, $transfertto);
# is item on the reserve shelf?
- my $reservestatus = '';
- my $reserveitem;
+ my $reservestatus = '';
unless ($item->{wthdrawn}
|| $item->{itemlost}
# should map transit status to record indexed in Zebra.
#
($transfertwhen, $transfertfrom, $transfertto) = C4::Circulation::GetTransfers($item->{itemnumber});
- ($reservestatus, $reserveitem, undef) = C4::Reserves::CheckReserves($item->{itemnumber});
+ $reservestatus = C4::Reserves::GetReserveStatus( $item->{itemnumber}, $oldbiblio->{biblionumber} );
}
# item is withdrawn, lost, damaged, not for loan, reserved or in transit
if ( $item->{wthdrawn}
|| $item->{itemlost}
|| $item->{damaged}
- || $item->{notforloan} > 0
- || $reservestatus eq 'Waiting'
+ || $item->{notforloan}
+ || $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_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;
+ if ( !$item->{itemlost} ) {
+ if ( !$item->{wthdrawn} ){
+ if ( $item->{damaged} ){
+ if ( C4::Context->preference('AllowHoldsOnDamagedItems') ){
+ # can place a hold on a damaged item if AllowHoldsOnDamagedItems is true
+ if ( ( !$item->{notforloan} || $item->{notforloan} < 0 ) ){
+ # item is either for loan or has notforloan < 0
+ $can_place_holds = 1;
+ }
+ }
+ } elsif ( $item->{notforloan} < 0 ) {
+ # item is not damaged and notforloan is < 0
+ $can_place_holds = 1;
+ }
+ }
}
-
+
$other_count++;
my $key = $prefix . $item->{status};
}
# The big moment: asynchronously retrieve results from all servers
my @elements;
- while ( ( my $i = ZOOM::event( \@zconns ) ) != 0 ) {
- my $ev = $zconns[ $i - 1 ]->last_event();
- if ( $ev == ZOOM::Event::ZEND ) {
- next unless $results[ $i - 1 ];
- my $size = $results[ $i - 1 ]->size();
- if ( $size > 0 ) {
- for (my $j=0;$j<$size;$j++){
- my %hashscan;
- @hashscan{qw(value cnt)}=$results[ $i - 1 ]->display_term($j);
- push @elements, \%hashscan;
- }
- }
- }
- }
+ _ZOOM_event_loop(
+ \@zconns,
+ \@results,
+ sub {
+ my ( $i, $size ) = @_;
+ for ( my $j = 0 ; $j < $size ; $j++ ) {
+ my %hashscan;
+ @hashscan{qw(value cnt)} =
+ $results[ $i - 1 ]->display_term($j);
+ push @elements, \%hashscan;
+ }
+ }
+ );
return \@elements;
}
}
+=head2 _ZOOM_event_loop
+
+ _ZOOM_event_loop(\@zconns, \@results, sub {
+ my ( $i, $size ) = @_;
+ ....
+ } );
+
+Processes a ZOOM event loop and passes control to a closure for
+processing the results, and destroying the resultsets.
+
+=cut
+
+sub _ZOOM_event_loop {
+ my ($zconns, $results, $callback) = @_;
+ while ( ( my $i = ZOOM::event( $zconns ) ) != 0 ) {
+ my $ev = $zconns->[ $i - 1 ]->last_event();
+ if ( $ev == ZOOM::Event::ZEND ) {
+ next unless $results->[ $i - 1 ];
+ my $size = $results->[ $i - 1 ]->size();
+ if ( $size > 0 ) {
+ $callback->($i, $size);
+ }
+ }
+ }
+
+ foreach my $result (@$results) {
+ $result->destroy();
+ }
+}
+
END { } # module clean-up code here (global destructor)