Bug 24735: Remove QueryParser-related code

At the last development meeting we have voted to remove the
QueryParser-related code
https://wiki.koha-community.org/wiki/Development_IRC_meeting_19_February_2020

Hea tells us that it has not been adopted, and the code/bug tracker that
it is not really usable as it. As nobody is willing to work on it, we
decided to remove it instead.

Test plan:
 % prove t/db_dependent/Search.t
must return green

See commits from bug 9239 and confirm that the code is removed in this
patch.

Also play with the search on the UI and confirm that you do not see
obvious regressions

Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Katrin Fischer <katrin.fischer.83@web.de>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
This commit is contained in:
Jonathan Druart 2020-02-26 13:28:27 +01:00 committed by Martin Renvoize
parent 35b47f0119
commit 52e95fff34
No known key found for this signature in database
GPG Key ID: 422B469130441A0F
35 changed files with 43 additions and 5981 deletions

View File

@ -113,8 +113,6 @@ sub SearchAuthorities {
$sortby="" unless $sortby;
my $query;
my $qpquery = '';
my $QParser;
$QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser'));
my $attr = '';
# the marclist may contain "mainentry". In this case, search the tag_to_report, that depends on
# the authtypecode. Then, search on $a of this tag_to_report
@ -133,9 +131,6 @@ sub SearchAuthorities {
if ($n>1){
while ($n>1){$query= "\@or ".$query;$n--;}
}
if ($QParser) {
$qpquery .= '(authtype:' . join('|| authtype:', @auths) . ')';
}
}
my $dosearch;
@ -203,9 +198,6 @@ sub SearchAuthorities {
$q2 .= $attr;
$dosearch = 1;
++$attr_cnt;
if ($QParser) {
$qpquery .= " $tags->[$i]:\"$value->[$i]\"";
}
} #if value
}
##Add how many queries generated
@ -226,21 +218,8 @@ sub SearchAuthorities {
} elsif ($sortby eq 'AuthidDsc') {
$orderstring = '@attr 7=2 @attr 4=109 @attr 1=Local-Number 0';
}
if ($QParser) {
$qpquery .= ' all:all' unless $value->[0];
if ( $value->[0] =~ m/^qp=(.*)$/ ) {
$qpquery = $1;
}
$qpquery .= " #$sortby" unless $sortby eq '';
$QParser->parse( $qpquery );
$query = $QParser->target_syntax('authorityserver');
} else {
$query=($query?$query:"\@attr 1=_ALLRECORDS \@attr 2=103 ''");
$query="\@or $orderstring $query" if $orderstring;
}
$query=($query?$query:"\@attr 1=_ALLRECORDS \@attr 2=103 ''");
$query="\@or $orderstring $query" if $orderstring;
$offset = 0 if not defined $offset or $offset < 0;
my $counter = $offset;
@ -758,14 +737,7 @@ sub FindDuplicateAuthority {
my $auth_tag_to_report = Koha::Authority::Types->find($authtypecode)->auth_tag_to_report;
# warn "record :".$record->as_formatted." auth_tag_to_report :$auth_tag_to_report";
# build a request for SearchAuthorities
my $QParser;
$QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser'));
my $op;
if ($QParser) {
$op = '&&';
} else {
$op = 'AND';
}
my $op = 'AND';
$authtypecode =~ s#/#\\/#; # GENRE/FORM contains forward slash which is a reserved character
my $query='at:'.$authtypecode.' ';
my $filtervalues=qr([\001-\040\Q!'"`#$%&*+,-./:;<=>?@(){[}_|~\E\]]);

View File

@ -783,53 +783,6 @@ sub restore_dbh
# return something, then this function should, too.
}
=head2 queryparser
$queryparser = C4::Context->queryparser
Returns a handle to an initialized Koha::QueryParser::Driver::PQF object.
=cut
sub queryparser {
my $self = shift;
unless (defined $context->{"queryparser"}) {
$context->{"queryparser"} = &_new_queryparser();
}
return
defined( $context->{"queryparser"} )
? $context->{"queryparser"}->new
: undef;
}
=head2 _new_queryparser
Internal helper function to create a new QueryParser object. QueryParser
is loaded dynamically so as to keep the lack of the QueryParser library from
getting in anyone's way.
=cut
sub _new_queryparser {
my $qpmodules = {
'OpenILS::QueryParser' => undef,
'Koha::QueryParser::Driver::PQF' => undef
};
if ( can_load( 'modules' => $qpmodules ) ) {
my $QParser = Koha::QueryParser::Driver::PQF->new();
my $config_file = $context->config('queryparser_config');
$config_file ||= '/etc/koha/searchengine/queryparser.yaml';
if ( $QParser->load_config($config_file) ) {
# Set 'keyword' as the default search class
$QParser->default_search_class('keyword');
# TODO: allow indexes to be configured in the database
return $QParser;
}
}
return;
}
=head2 userenv
C4::Context->userenv;

View File

@ -622,26 +622,18 @@ sub get_matches {
my $matches = {};
my $QParser;
$QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser'));
foreach my $matchpoint ( @{ $self->{'matchpoints'} } ) {
my @source_keys = _get_match_keys( $source_record, $matchpoint );
next if scalar(@source_keys) == 0;
# FIXME - because of a bug in QueryParser, an expression ofthe
# format 'isbn:"isbn1" || isbn:"isbn2" || isbn"isbn3"...'
# does not get parsed correctly, so we will not
# do AggressiveMatchOnISBN if UseQueryParser is on
@source_keys = C4::Koha::GetVariationsOfISBNs(@source_keys)
if ( $matchpoint->{index} =~ /^isbn$/i
&& C4::Context->preference('AggressiveMatchOnISBN') )
&& !C4::Context->preference('UseQueryParser');
&& C4::Context->preference('AggressiveMatchOnISBN') );
@source_keys = C4::Koha::GetVariationsOfISSNs(@source_keys)
if ( $matchpoint->{index} =~ /^issn$/i
&& C4::Context->preference('AggressiveMatchOnISSN') )
&& !C4::Context->preference('UseQueryParser');
&& C4::Context->preference('AggressiveMatchOnISSN') );
# build query
my $query;
@ -650,18 +642,10 @@ sub get_matches {
my $total_hits;
if ( $self->{'record_type'} eq 'biblio' ) {
#NOTE: The QueryParser can't handle the CCL syntax of 'qualifier','qualifier', so fallback to non-QueryParser.
#NOTE: You can see this in C4::Search::SimpleSearch() as well in a different way.
if ($QParser && $matchpoint->{'index'} !~ m/\w,\w/) {
$query = join( " || ",
map { "$matchpoint->{'index'}:$_" } @source_keys );
}
else {
my $phr = ( C4::Context->preference('AggressiveMatchOnISBN') || C4::Context->preference('AggressiveMatchOnISSN') ) ? ',phr' : q{};
$query = join( " OR ",
map { "$matchpoint->{'index'}$phr=\"$_\"" } @source_keys );
#NOTE: double-quote the values so you don't get a "Embedded truncation not supported" error when a term has a ? in it.
}
my $phr = ( C4::Context->preference('AggressiveMatchOnISBN') || C4::Context->preference('AggressiveMatchOnISSN') ) ? ',phr' : q{};
$query = join( " OR ",
map { "$matchpoint->{'index'}$phr=\"$_\"" } @source_keys );
#NOTE: double-quote the values so you don't get a "Embedded truncation not supported" error when a term has a ? in it.
# Use state variables to avoid recreating the objects every time.
# With Elasticsearch this also avoids creating a massive amount of

View File

@ -99,22 +99,10 @@ sub FindDuplicate {
$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 = '&&';
$QParser->custom_data->{'QueryAutoTruncate'} = C4::Context->preference('QueryAutoTruncate');
} else {
$titleindex = 'ti,ext';
$authorindex = 'au,ext';
$op = 'and';
}
my $titleindex = 'ti,ext';
my $authorindex = 'au,ext';
my $op = 'and';
$result->{title} =~ s /\\//g;
$result->{title} =~ s /\"//g;
@ -233,25 +221,12 @@ sub SimpleSearch {
my $results = [];
my $total_hits = 0;
my $QParser;
$QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser') && ! ($query =~ m/\w,\w|\w=\w/));
if ($QParser) {
$QParser->custom_data->{'QueryAutoTruncate'} = C4::Context->preference('QueryAutoTruncate');
}
# Initialize & Search Zebra
for ( my $i = 0 ; $i < @servers ; $i++ ) {
eval {
$zconns[$i] = C4::Context->Zconn( $servers[$i], 1 );
if ($QParser) {
$query =~ s/=/:/g unless $options{skip_normalize};
$QParser->parse( $query );
$query = $QParser->target_syntax($servers[$i]);
$zoom_queries[$i] = new ZOOM::Query::PQF( $query, $zconns[$i]);
} else {
$query =~ s/:/=/g unless $options{skip_normalize};
$zoom_queries[$i] = new ZOOM::Query::CCL2RPN( $query, $zconns[$i]);
}
$query =~ s/:/=/g unless $options{skip_normalize};
$zoom_queries[$i] = new ZOOM::Query::CCL2RPN( $query, $zconns[$i]);
$tmpresults[$i] = $zconns[$i]->search( $zoom_queries[$i] );
# error handling
@ -1277,134 +1252,6 @@ sub getIndexes{
return \@indexes;
}
=head2 _handle_exploding_index
my $query = _handle_exploding_index($index, $term)
Callback routine to generate the search for "exploding" indexes (i.e.
those indexes which are turned into multiple or-connected searches based
on authority data).
=cut
sub _handle_exploding_index {
my ($QParser, $filter, $params, $negate, $server) = @_;
my $index = $filter;
my $term = join(' ', @$params);
return unless ($index =~ m/(su-br|su-na|su-rl)/ && $term);
my $marcflavour = C4::Context->preference('marcflavour');
my $codesubfield = $marcflavour eq 'UNIMARC' ? '5' : 'w';
my $wantedcodes = '';
my @subqueries = ( "\@attr 1=Subject \@attr 4=1 \"$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..');
if (@references) {
if ($index eq 'su-br') {
$wantedcodes = 'g';
} elsif ($index eq 'su-na') {
$wantedcodes = 'h';
} elsif ($index eq 'su-rl') {
$wantedcodes = '';
}
foreach my $reference (@references) {
my $codes = $reference->subfield($codesubfield);
push @subqueries, '@attr 1=Subject @attr 4=1 "' . $reference->as_string('abcdefghijlmnopqrstuvxyz') . '"' if (($codes && $codes eq $wantedcodes) || !$wantedcodes);
}
}
}
my $query = ' @or ' x (scalar(@subqueries) - 1) . join(' ', @subqueries);
return $query;
}
=head2 parseQuery
( $operators, $operands, $indexes, $limits,
$sort_by, $scan, $lang ) =
parseQuery ( $operators, $operands, $indexes, $limits, $sort_by, $scan, $lang);
Shim function to ease the transition from buildQuery to a new QueryParser.
This function is called at the beginning of buildQuery, and modifies
buildQuery's input. If it can handle the input, it returns a query that
buildQuery will not try to parse.
=cut
sub parseQuery {
my ( $operators, $operands, $indexes, $limits, $sort_by, $scan, $lang) = @_;
my @operators = $operators ? @$operators : ();
my @indexes = $indexes ? @$indexes : ();
my @operands = $operands ? @$operands : ();
my @limits = $limits ? @$limits : ();
my @sort_by = $sort_by ? @$sort_by : ();
my $query = $operands[0];
my $index;
my $term;
my $query_desc;
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, @indexes) );
undef $QParser if (scalar @limits > 0);
if ($QParser)
{
$QParser->custom_data->{'QueryAutoTruncate'} = C4::Context->preference('QueryAutoTruncate');
$query = '';
for ( my $ii = 0 ; $ii <= @operands ; $ii++ ) {
next unless $operands[$ii];
$query .= $operators[$ii-1] && $operators[ $ii - 1 ] eq 'or' ? ' || ' : ' && '
if ($query);
if ( $operands[$ii] =~ /^[^"]\W*[-|_\w]*:\w.*[^"]$/ ) {
$query .= $operands[$ii];
}
elsif ( $indexes[$ii] && $indexes[$ii] =~ m/su-/ ) {
$query .= $indexes[$ii] . '(' . $operands[$ii] . ')';
}
else {
$query .=
( $indexes[$ii] ? "$indexes[$ii]:" : '' ) . $operands[$ii];
}
}
foreach my $limit (@limits) {
}
if ( scalar(@sort_by) > 0 ) {
my $modifier_re =
'#(' . join( '|', @{ $QParser->modifiers } ) . ')';
$query =~ s/$modifier_re//g;
foreach my $modifier (@sort_by) {
$query .= " #$modifier";
}
}
$query_desc = $query;
$query_desc =~ s/\s+/ /g;
if ( C4::Context->preference("QueryWeightFields") ) {
}
$QParser->add_bib1_filter_map( 'su-br' => 'biblioserver' =>
{ 'target_syntax_callback' => \&_handle_exploding_index } );
$QParser->add_bib1_filter_map( 'su-na' => 'biblioserver' =>
{ 'target_syntax_callback' => \&_handle_exploding_index } );
$QParser->add_bib1_filter_map( 'su-rl' => 'biblioserver' =>
{ 'target_syntax_callback' => \&_handle_exploding_index } );
$QParser->parse($query);
$operands[0] = "pqf=" . $QParser->target_syntax('biblioserver');
}
else {
require Koha::QueryParser::Driver::PQF;
my $modifier_re = '#(' . join( '|', @{Koha::QueryParser::Driver::PQF->modifiers}) . ')';
s/$modifier_re//g for @operands;
}
return ( $operators, \@operands, $indexes, $limits, $sort_by, $scan, $lang, $query_desc);
}
=head2 buildQuery
( $error, $query,
@ -1427,7 +1274,6 @@ sub buildQuery {
warn "---------\nEnter buildQuery\n---------" if $DEBUG;
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 : ();
@ -1487,12 +1333,8 @@ sub buildQuery {
return ( undef, $', $', "q=cql=".uri_escape_utf8($'), $', '', '', '', 'cql' );
}
if ( $query =~ /^pqf=/ ) {
if ($query_desc) {
$query_cgi = "q=".uri_escape_utf8($query_desc);
} else {
$query_desc = $';
$query_cgi = "q=pqf=".uri_escape_utf8($');
}
$query_desc = $';
$query_cgi = "q=pqf=".uri_escape_utf8($');
return ( undef, $', $', $query_cgi, $query_desc, '', '', '', 'pqf' );
}

View File

@ -304,7 +304,6 @@ sub BuildReport {
TraceCompleteSubfields
TraceSubjectSubdivisions
UseICU
UseQueryParser
defaultSortField
displayFacetCount
OPACdefaultSortField

View File

@ -1,925 +0,0 @@
package Koha::QueryParser::Driver::PQF;
# This file is part of Koha.
#
# Copyright 2012 C & P Bibliography Services
#
# Koha is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Koha is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Koha; if not, see <http://www.gnu.org/licenses>.
use base qw(OpenILS::QueryParser Class::Accessor);
use strict;
use warnings;
use Module::Load::Conditional qw(can_load);
use Koha::QueryParser::Driver::PQF::Util;
use Koha::QueryParser::Driver::PQF::query_plan;
use Koha::QueryParser::Driver::PQF::query_plan::facet;
use Koha::QueryParser::Driver::PQF::query_plan::filter;
use Koha::QueryParser::Driver::PQF::query_plan::modifier;
use Koha::QueryParser::Driver::PQF::query_plan::node;
use Koha::QueryParser::Driver::PQF::query_plan::node::atom;
use Koha::QueryParser::Driver::PQF::query_plan::node::atom;
=head1 NAME
Koha::QueryParser::Driver::PQF - QueryParser driver for PQF
=head1 SYNOPSIS
use Koha::QueryParser::Driver::PQF;
my $QParser = Koha::QueryParser::Driver::PQF->new(%args);
=head1 DESCRIPTION
Main entrypoint into the QueryParser PQF driver. PQF is the Prefix Query
Language, the syntax used to serialize Z39.50 queries.
=head1 ACCESSORS
In order to simplify Bib-1 attribute mapping, this driver uses Class::Accessor
for accessing the following maps:
=over 4
=item B<bib1_field_map> - search class/field Bib-1 mappings
=item B<bib1_modifier_map> - search modifier mappings
=item B<bib1_filter_map> - search filter mappings
=item B<bib1_relevance_bump_map> - relevance bump mappings
=back
=cut
__PACKAGE__->mk_accessors(qw(bib1_field_map bib1_modifier_map bib1_filter_map bib1_relevance_bump_map));
=head1 FUNCTIONS
=cut
=head2 get
Overridden accessor method for Class::Accessor. (Do not call directly)
=cut
sub get {
my $self = shift;
return $self->_map(@_);
}
=head2 set
Overridden mutator method for Class::Accessor. (Do not call directly)
=cut
sub set {
my $self = shift;
return $self->_map(@_);
}
=head2 add_bib1_field_map
$QParser->add_bib1_field_map($class => $field => $server => \%attributes);
$QParser->add_bib1_field_map('author' => 'personal' => 'biblioserver' =>
{ '1' => '1003' });
Adds a search field<->bib1 attribute mapping for the specified server. The
%attributes hash contains maps Bib-1 Attributes to the appropropriate
values. Not all attributes must be specified.
=cut
sub add_bib1_field_map {
my ($self, $class, $field, $server, $attributes) = @_;
$self->add_search_field( $class => $field );
return $self->_add_field_mapping($self->bib1_field_map, $class, $field, $server, $attributes);
}
=head2 add_bib1_modifier_map
$QParser->add_bib1_modifier_map($name => $server => \%attributes);
$QParser->add_bib1_modifier_map('ascending' => 'biblioserver' =>
{ '7' => '1' });
Adds a search modifier<->bib1 attribute mapping for the specified server. The
%attributes hash contains maps Bib-1 Attributes to the appropropriate
values. Not all attributes must be specified.
=cut
sub add_bib1_modifier_map {
my ($self, $name, $server, $attributes) = @_;
$self->add_search_modifier( $name );
return $self->_add_mapping($self->bib1_modifier_map, $name, $server, $attributes);
}
=head2 add_bib1_filter_map
$QParser->add_bib1_filter_map($name => $server => \%attributes);
$QParser->add_bib1_filter_map('date' => 'biblioserver' =>
{ 'callback' => &_my_callback });
Adds a search filter<->bib1 attribute mapping for the specified server. The
%attributes hash maps Bib-1 Attributes to the appropropriate values and
provides a callback for the filter. Not all attributes must be specified.
=cut
sub add_bib1_filter_map {
my ($self, $name, $server, $attributes) = @_;
$self->add_search_filter( $name, $attributes->{'callback'} );
return $self->_add_mapping($self->bib1_filter_map, $name, $server, $attributes);
}
=head2 add_relevance_bump
$QParser->add_relevance_bump($class, $field, $server, $multiplier, $active);
$QParser->add_relevance_bump('title' => 'exact' => 'biblioserver' => 34, 1);
Add a relevance bump to the specified field. When searching for a class without
any fields, all the relevance bumps for the specified class will be 'OR'ed
together.
=cut
sub add_relevance_bump {
my ($self, $class, $field, $server, $multiplier, $active) = @_;
my $attributes = { '9' => $multiplier, '2' => '102', 'active' => $active };
$self->add_search_field( $class => $field );
return $self->_add_field_mapping($self->bib1_relevance_bump_map, $class, $field, $server, $attributes);
}
=head2 target_syntax
my $pqf = $QParser->target_syntax($server, [$query]);
my $pqf = $QParser->target_syntax('biblioserver', 'author|personal:smith');
print $pqf; # assuming all the indexes are configured,
# prints '@attr 1=1003 @attr 4=6 "smith"'
Transforms the current or specified query into a PQF query string for the
specified server.
=cut
sub target_syntax {
my ($self, $server, $query) = @_;
my $pqf = '';
$self->parse($query) if $query;
warn "QP query for $server: " . $self->query . "\n" if $self->debug;
$pqf = $self->parse_tree->target_syntax($server);
warn "PQF query: $pqf\n" if $self->debug;
$pqf =~ s/ +/ /g;
$pqf =~ s/^ //;
$pqf =~ s/ $//;
return $pqf;
}
=head2 date_filter_target_callback
$QParser->add_bib1_filter_map($server, { 'target_syntax_callback' => \&Koha::QueryParser::Driver::PQF::date_filter_target_callback, '1' => 'pubdate' });
Callback for date filters. Note that although the first argument is the QParser
object, this is technically not an object-oriented routine. This has no
real-world implications.
=cut
sub date_filter_target_callback {
my ($QParser, $filter, $params, $negate, $server) = @_;
my $attr_string = $QParser->bib1_mapping_by_name( 'filter', $filter, $server )->{'attr_string'};
my $pqf = '';
foreach my $datespec (@$params) {
my $datepqf = ' ';
if ($datespec) {
if ($datespec =~ m/(.*)-(.*)/) {
if ($1) {
$datepqf .= $attr_string . ' @attr 2=4 "' . $1 . '"';
}
if ($2) {
$datepqf .= $attr_string . ' @attr 2=2 "' . $2 . '"';
$datepqf = ' @and ' . $datepqf if $1;
}
} else {
$datepqf .= $attr_string . ' "' . $datespec . '"';
}
}
$pqf = ' @or ' . ($negate ? '@not @attr 1=_ALLRECORDS @attr 2=103 "" ' : '') . $pqf if $pqf;
$pqf .= $datepqf;
}
return $pqf;
}
=head2 _map
return $self->_map('bib1_field_map', $map);
Retrieves or sets a map.
=cut
sub _map {
my ($self, $name, $map) = @_;
$self->custom_data->{$name} ||= {};
$self->custom_data->{$name} = $map if ($map);
return $self->custom_data->{$name};
}
=head2 _add_mapping
return $self->_add_mapping($map, $name, $server, $attributes)
Adds a mapping. Note that this is not used for mappings relating to fields.
=cut
sub _add_mapping {
my ($self, $map, $name, $server, $attributes) = @_;
my $attr_string = Koha::QueryParser::Driver::PQF::Util::attributes_to_attr_string($attributes);
$attributes->{'attr_string'} = $attr_string;
$map->{'by_name'}{$name}{$server} = $attributes;
$map->{'by_attr'}{$server}{$attr_string} = { 'name' => $name, %$attributes };
return $map;
}
=head2 _add_field_mapping
return $self->_add_field_mapping($map, $class, $field, $server, $attributes)
Adds a mapping for field-related data.
=cut
sub _add_field_mapping {
my ($self, $map, $class, $field, $server, $attributes) = @_;
my $attr_string = Koha::QueryParser::Driver::PQF::Util::attributes_to_attr_string($attributes);
$attributes->{'attr_string'} = $attr_string;
$map->{'by_name'}{$class}{$field}{$server} = $attributes;
$map->{'by_attr'}{$server}{$attr_string} = { 'classname' => $class, 'field' => $field, %$attributes };
return $map;
}
=head2 bib1_mapping_by_name
my $attributes = $QParser->bib1_mapping_by_name($type, $name[, $subname], $server);
my $attributes = $QParser->bib1_mapping_by_name('field', 'author', 'personal', 'biblioserver');
my $attributes = $QParser->bib1_mapping_by_name('filter', 'pubdate', 'biblioserver');
Retrieve the Bib-1 attribute set associated with the specified mapping.
=cut
sub bib1_mapping_by_name {
my $server = pop;
my ($self, $type, $name, $field) = @_;
return unless ($server && $name);
return unless ($type eq 'field' || $type eq 'modifier' || $type eq 'filter' || $type eq 'relevance_bump');
if ($type eq 'field' || $type eq 'relevance_bump') {
# Unfortunately field is a special case thanks to the class->field hierarchy
return $self->_map('bib1_' . $type . '_map')->{'by_name'}{$name}{$field}{$server} if $field;
return $self->_map('bib1_' . $type . '_map')->{'by_name'}{$name};
} else {
return $self->_map('bib1_' . $type . '_map')->{'by_name'}{$name}{$server};
}
}
=head2 bib1_mapping_by_attr
my $field = $QParser->bib1_mapping_by_attr($type, $server, \%attr);
my $field = $QParser->bib1_mapping_by_attr('field', 'biblioserver', {'1' => '1004'});
print $field->{'classname'}; # prints "author"
print $field->{'field'}; # prints "personal"
Retrieve the search field/modifier/filter used for the specified Bib-1 attribute set.
=cut
sub bib1_mapping_by_attr {
my ($self, $type, $server, $attributes) = @_;
return unless ($server && $attributes);
my $attr_string = Koha::QueryParser::Driver::PQF::Util::attributes_to_attr_string($attributes);
return $self->bib1_mapping_by_attr_string($type, $server, $attr_string);
}
=head2 bib1_mapping_by_attr_string
my $field = $QParser->bib1_mapping_by_attr_string($type, $server, $attr_string);
my $field = $QParser->bib1_mapping_by_attr_string('field', 'biblioserver', '@attr 1=1004');
print $field->{'classname'}; # prints "author"
print $field->{'field'}; # prints "personal"
Retrieve the search field/modifier/filter used for the specified Bib-1 attribute string
(i.e. PQF snippet).
=cut
sub bib1_mapping_by_attr_string {
my ($self, $type, $server, $attr_string) = @_;
return unless ($server && $attr_string);
return unless ($type eq 'field' || $type eq 'modifier' || $type eq 'filter' || $type eq 'relevance_bump');
return $self->_map('bib1_' . $type . '_map')->{'by_attr'}{$server}{$attr_string};
}
=head2 clear_all_configuration
$QParser->clear_all_configuration
Clear all configuration. This is a highly destructive method. You may
not want to use it.
=cut
sub clear_all_configuration {
my ($self) = @_;
%OpenILS::QueryParser::parser_config = (
'OpenILS::QueryParser' => {
filters => [],
modifiers => [],
operators => {
'and' => '&&',
'or' => '||',
float_start => '{{',
float_end => '}}',
group_start => '(',
group_end => ')',
required => '+',
disallowed => '-',
modifier => '#',
negated => '!'
}
}
);
return $self;
}
=head2 clear_all_mappings
$QParser->clear_all_mappings
Clear all bib-1 mappings.
=cut
sub clear_all_mappings {
my ($self) = @_;
foreach my $name (qw(field modifier filter relevance_bump)) {
$self->custom_data->{'bib1_' . $name . '_map'} = { };
}
return $self;
}
=head2 _canonicalize_field_map
Convert a field map into its canonical form for serialization. Used only for
fields and relevance bumps.
=cut
sub _canonicalize_field_map {
my ( $map, $aliases ) = @_;
my $canonical_map = {};
foreach my $class ( keys %{ $map->{'by_name'} } ) {
$canonical_map->{$class} ||= {};
foreach my $field ( keys %{ $map->{'by_name'}->{$class} } ) {
my $field_map = {
'index' => $field,
'label' => ucfirst($field),
'enabled' => '1',
};
foreach
my $server ( keys %{ $map->{'by_name'}->{$class}->{$field} } )
{
$field_map->{'bib1_mapping'} ||= {};
$field_map->{'bib1_mapping'}->{$server} =
$map->{'by_name'}->{$class}->{$field}->{$server};
delete $field_map->{'bib1_mapping'}->{$server}->{'attr_string'}
if defined(
$field_map->{'bib1_mapping'}->{$server}
->{'attr_string'}
);
}
if ($aliases) {
$field_map->{'aliases'} = [];
foreach my $alias ( @{ $aliases->{$class}->{$field} } ) {
push @{ $field_map->{'aliases'} },
$alias;
}
}
$canonical_map->{$class}->{$field} = $field_map;
}
}
return $canonical_map;
}
=head2 _canonicalize_map
Convert a map into its canonical form for serialization. Not used for fields.
=cut
sub _canonicalize_map {
my ($map) = @_;
my $canonical_map = {};
foreach my $name ( keys %{ $map->{'by_name'} } ) {
$canonical_map->{$name} = {
'label' => ucfirst($name),
'enabled' => 1,
'bib1_mapping' => {}
};
foreach my $server ( keys %{ $map->{'by_name'}->{$name} } ) {
$canonical_map->{$name}->{'bib1_mapping'}->{$server} =
$map->{'by_name'}->{$name}->{$server};
delete $canonical_map->{$name}->{'bib1_mapping'}->{$server}
->{'attr_string'}
if defined(
$canonical_map->{$name}->{'bib1_mapping'}->{$server}
->{'attr_string'}
);
}
}
return $canonical_map;
}
=head2 serialize_mappings
my $yaml = $QParser->serialize_mappings;
my $json = $QParser->serialize_mappings('json');
Serialize Bib-1 mappings to YAML or JSON.
=cut
sub serialize_mappings {
my ( $self, $format ) = @_;
$format ||= 'yaml';
my $config;
$config->{'field_mappings'} =
_canonicalize_field_map( $self->bib1_field_map,
$self->search_field_aliases );
$config->{'modifier_mappings'} =
_canonicalize_map( $self->bib1_modifier_map );
$config->{'filter_mappings'} = _canonicalize_map( $self->bib1_filter_map );
$config->{'relevance_bumps'} =
_canonicalize_field_map( $self->bib1_relevance_bump_map );
if ( $format eq 'json' && can_load( modules => { 'JSON' => undef } ) ) {
return JSON::to_json($config);
}
elsif ( can_load( modules => { 'YAML::Any' => undef } ) ) {
return YAML::Any::Dump($config);
}
return;
}
=head2 initialize
$QParser->initialize( { 'bib1_field_mappings' => \%bib1_field_mappings,
'search_field_alias_mappings' => \%search_field_alias_mappings,
'bib1_modifier_mappings' => \%bib1_modifier_mappings,
'bib1_filter_mappings' => \%bib1_filter_mappings,
'relevance_bumps' => \%relevance_bumps });
Initialize the QueryParser mapping tables based on the provided configuration.
This method was written to play nice with YAML configuration files loaded by load_config.
=cut
sub initialize {
my ( $self, $args ) = @_;
my $field_mappings = $args->{'field_mappings'};
my $modifier_mappings = $args->{'modifier_mappings'};
my $filter_mappings = $args->{'filter_mappings'};
my $relbumps = $args->{'relevance_bumps'};
my ( $server, $bib1_mapping );
foreach my $class ( keys %$field_mappings ) {
foreach my $field ( keys %{ $field_mappings->{$class} } ) {
if ( $field_mappings->{$class}->{$field}->{'enabled'} ) {
while ( ( $server, $bib1_mapping ) =
each
%{ $field_mappings->{$class}->{$field}->{'bib1_mapping'} } )
{
$self->add_bib1_field_map(
$class => $field => $server => $bib1_mapping );
}
foreach my $alias (
@{ $field_mappings->{$class}->{$field}->{'aliases'} } )
{
$self->add_search_field_alias( $class => $field => $alias );
}
}
}
}
foreach my $modifier ( keys %$modifier_mappings ) {
if ( $modifier_mappings->{$modifier}->{'enabled'} ) {
while ( ( $server, $bib1_mapping ) =
each %{ $modifier_mappings->{$modifier}->{'bib1_mapping'} } )
{
$self->add_bib1_modifier_map(
$modifier => $server => $bib1_mapping );
}
}
}
foreach my $filter ( keys %$filter_mappings ) {
if ( $filter_mappings->{$filter}->{'enabled'} ) {
while ( ( $server, $bib1_mapping ) =
each %{ $filter_mappings->{$filter}->{'bib1_mapping'} } )
{
if ( $bib1_mapping->{'target_syntax_callback'} eq
'date_filter_target_callback' )
{
$bib1_mapping->{'target_syntax_callback'} =
\&Koha::QueryParser::Driver::PQF::date_filter_target_callback;
}
$self->add_bib1_filter_map(
$filter => $server => $bib1_mapping );
}
}
}
foreach my $class ( keys %$relbumps ) {
foreach my $field ( keys %{ $relbumps->{$class} } ) {
if ( $relbumps->{$class}->{$field}->{'enabled'} ) {
while ( ( $server, $bib1_mapping ) =
each %{ $relbumps->{$class}->{$field}->{'bib1_mapping'} } )
{
$self->add_relevance_bump(
$class => $field => $server => $bib1_mapping,
1
);
}
}
}
}
return $self;
}
=head2 load_config
$QParser->load_config($file_name);
Load a YAML file with a parser configuration. The YAML file should match the following format:
---
field_mappings:
author:
"":
aliases:
- au
bib1_mapping:
biblioserver:
1: 1003
enabled: 1
index: ''
label: ''
conference:
aliases:
- conference
- cfn
bib1_mapping:
biblioserver:
1: 1006
enabled: 1
index: conference
label: Conference
filter_mappings:
acqdate:
bib1_mapping:
biblioserver:
1: Date-of-acquisition
4: 4
target_syntax_callback: date_filter_target_callback
enabled: 1
label: Acqdate
modifier_mappings:
AuthidAsc:
bib1_mapping:
authorityserver:
"": 0
1: Local-Number
7: 1
op: "@or"
enabled: 1
label: AuthidAsc
...
=cut
sub load_config {
my ($self, $file) = @_;
require YAML::Any;
return unless ($file && -f $file);
my $config = YAML::Any::LoadFile($file);
return unless ($config);
$self->initialize($config);
return 1;
}
=head2 TEST_SETUP
$QParser->TEST_SETUP
This routine initializes the QueryParser driver with a reasonable set of
defaults. This is intended only for testing. Although such test stubs are
generally not included in Koha, this type of test stub is used by other
QueryParser implementations, and it seems sensible to maintain consistency
as much as possible.
=cut
sub TEST_SETUP {
my ($self) = @_;
$self->default_search_class( 'keyword' );
$self->add_bib1_field_map('keyword' => 'abstract' => 'biblioserver' => { '1' => '62' } );
$self->add_search_field_alias( 'keyword' => 'abstract' => 'ab' );
$self->add_bib1_field_map('keyword' => '' => 'biblioserver' => { '1' => '1016' } );
$self->add_search_field_alias( 'keyword' => '' => 'kw' );
$self->add_bib1_field_map('author' => '' => 'biblioserver' => { '1' => '1003' } );
$self->add_search_field_alias( 'author' => '' => 'au' );
$self->add_bib1_field_map('author' => 'personal' => 'biblioserver' => { '1' => '1004' } );
$self->add_bib1_field_map('author' => 'corporate' => 'biblioserver' => { '1' => '1005' } );
$self->add_search_field_alias( 'author' => 'corporate' => 'cpn' );
$self->add_bib1_field_map('author' => 'conference' => 'biblioserver' => { '1' => '1006' } );
$self->add_search_field_alias( 'author' => 'conference' => 'cfn' );
$self->add_bib1_field_map('keyword' => 'local-classification' => 'biblioserver' => { '1' => '20' } );
$self->add_search_field_alias( 'keyword' => 'local-classification' => 'lcn' );
$self->add_search_field_alias( 'keyword' => 'local-classification' => 'callnum' );
$self->add_bib1_field_map('keyword' => 'bib-level' => 'biblioserver' => { '1' => '1021' } );
$self->add_bib1_field_map('keyword' => 'code-institution' => 'biblioserver' => { '1' => '56' } );
$self->add_bib1_field_map('keyword' => 'language' => 'biblioserver' => { '1' => '54' } );
$self->add_search_field_alias( 'keyword' => 'language' => 'ln' );
$self->add_bib1_field_map('keyword' => 'record-type' => 'biblioserver' => { '1' => '1001' } );
$self->add_search_field_alias( 'keyword' => 'record-type' => 'rtype' );
$self->add_search_field_alias( 'keyword' => 'record-type' => 'mc-rtype' );
$self->add_search_field_alias( 'keyword' => 'record-type' => 'mus' );
$self->add_bib1_field_map('keyword' => 'content-type' => 'biblioserver' => { '1' => '1034' } );
$self->add_search_field_alias( 'keyword' => 'content-type' => 'ctype' );
$self->add_bib1_field_map('keyword' => 'lc-card-number' => 'biblioserver' => { '1' => '9' } );
$self->add_search_field_alias( 'keyword' => 'lc-card-number' => 'lc-card' );
$self->add_bib1_field_map('keyword' => 'local-number' => 'biblioserver' => { '1' => '12' } );
$self->add_search_field_alias( 'keyword' => 'local-number' => 'sn' );
$self->add_bib1_filter_map( 'biblioserver', 'copydate', { 'target_syntax_callback' => \&Koha::QueryParser::Driver::PQF::date_filter_target_callback, '1' => '30', '4' => '4' });
$self->add_bib1_filter_map( 'biblioserver', 'pubdate', { 'target_syntax_callback' => \&Koha::QueryParser::Driver::PQF::date_filter_target_callback, '1' => 'pubdate', '4' => '4' });
$self->add_bib1_filter_map( 'biblioserver', 'acqdate', { 'target_syntax_callback' => \&Koha::QueryParser::Driver::PQF::date_filter_target_callback, '1' => 'Date-of-acquisition', '4' => '4' });
$self->add_bib1_field_map('keyword' => 'isbn' => 'biblioserver' => { '1' => '7' } );
$self->add_search_field_alias( 'keyword' => 'isbn' => 'nb' );
$self->add_bib1_field_map('keyword' => 'issn' => 'biblioserver' => { '1' => '8' } );
$self->add_search_field_alias( 'keyword' => 'issn' => 'ns' );
$self->add_bib1_field_map('keyword' => 'identifier-standard' => 'biblioserver' => { '1' => '1007' } );
$self->add_search_field_alias( 'keyword' => 'identifier-standard' => 'ident' );
$self->add_bib1_field_map('keyword' => 'upc' => 'biblioserver' => { '1' => 'UPC' } );
$self->add_search_field_alias( 'keyword' => 'upc' => 'upc' );
$self->add_bib1_field_map('keyword' => 'ean' => 'biblioserver' => { '1' => 'EAN' } );
$self->add_search_field_alias( 'keyword' => 'ean' => 'ean' );
$self->add_bib1_field_map('keyword' => 'music' => 'biblioserver' => { '1' => 'Music-number' } );
$self->add_search_field_alias( 'keyword' => 'music' => 'music' );
$self->add_bib1_field_map('keyword' => 'stock-number' => 'biblioserver' => { '1' => '1028' } );
$self->add_search_field_alias( 'keyword' => 'stock-number' => 'stock-number' );
$self->add_bib1_field_map('keyword' => 'material-type' => 'biblioserver' => { '1' => '1031' } );
$self->add_search_field_alias( 'keyword' => 'material-type' => 'material-type' );
$self->add_bib1_field_map('keyword' => 'place-publication' => 'biblioserver' => { '1' => '59' } );
$self->add_search_field_alias( 'keyword' => 'place-publication' => 'pl' );
$self->add_bib1_field_map('keyword' => 'personal-name' => 'biblioserver' => { '1' => 'Personal-name' } );
$self->add_search_field_alias( 'keyword' => 'personal-name' => 'pn' );
$self->add_bib1_field_map('keyword' => 'publisher' => 'biblioserver' => { '1' => '1018' } );
$self->add_search_field_alias( 'keyword' => 'publisher' => 'pb' );
$self->add_bib1_field_map('keyword' => 'note' => 'biblioserver' => { '1' => '63' } );
$self->add_search_field_alias( 'keyword' => 'note' => 'nt' );
$self->add_bib1_field_map('keyword' => 'record-control-number' => 'biblioserver' => { '1' => '1045' } );
$self->add_search_field_alias( 'keyword' => 'record-control-number' => 'rcn' );
$self->add_bib1_field_map('subject' => '' => 'biblioserver' => { '1' => '21' } );
$self->add_search_field_alias( 'subject' => '' => 'su' );
$self->add_search_field_alias( 'subject' => '' => 'su-to' );
$self->add_search_field_alias( 'subject' => '' => 'su-geo' );
$self->add_search_field_alias( 'subject' => '' => 'su-ut' );
$self->add_bib1_field_map('subject' => 'name-personal' => 'biblioserver' => { '1' => '1009' } );
$self->add_search_field_alias( 'subject' => 'name-personal' => 'su-na' );
$self->add_bib1_field_map('title' => '' => 'biblioserver' => { '1' => '4' } );
$self->add_search_field_alias( 'title' => '' => 'ti' );
$self->add_bib1_field_map('title' => 'cover' => 'biblioserver' => { '1' => '36' } );
$self->add_search_field_alias( 'title' => 'cover' => 'title-cover' );
$self->add_bib1_field_map('keyword' => 'host-item' => 'biblioserver' => { '1' => '1033' } );
$self->add_bib1_field_map('keyword' => 'video-mt' => 'biblioserver' => { '1' => 'Video-mt' } );
$self->add_bib1_field_map('keyword' => 'graphics-type' => 'biblioserver' => { '1' => 'Graphic-type' } );
$self->add_bib1_field_map('keyword' => 'graphics-support' => 'biblioserver' => { '1' => 'Graphic-support' } );
$self->add_bib1_field_map('keyword' => 'type-of-serial' => 'biblioserver' => { '1' => 'Type-Of-Serial' } );
$self->add_bib1_field_map('keyword' => 'regularity-code' => 'biblioserver' => { '1' => 'Regularity-code' } );
$self->add_bib1_field_map('keyword' => 'material-type' => 'biblioserver' => { '1' => 'Material-type' } );
$self->add_bib1_field_map('keyword' => 'literature-code' => 'biblioserver' => { '1' => 'Literature-Code' } );
$self->add_bib1_field_map('keyword' => 'biography-code' => 'biblioserver' => { '1' => 'Biography-code' } );
$self->add_bib1_field_map('keyword' => 'illustration-code' => 'biblioserver' => { '1' => 'Illustration-code' } );
$self->add_bib1_field_map('title' => 'series' => 'biblioserver' => { '1' => '5' } );
$self->add_search_field_alias( 'title' => 'series' => 'title-series' );
$self->add_search_field_alias( 'title' => 'series' => 'se' );
$self->add_bib1_field_map('title' => 'uniform' => 'biblioserver' => { '1' => 'Title-uniform' } );
$self->add_search_field_alias( 'title' => 'uniform' => 'title-uniform' );
$self->add_bib1_field_map('subject' => 'authority-number' => 'biblioserver' => { '1' => 'Koha-Auth-Number' } );
$self->add_search_field_alias( 'subject' => 'authority-number' => 'an' );
$self->add_bib1_field_map('keyword' => 'control-number' => 'biblioserver' => { '1' => '9001' } );
$self->add_bib1_field_map('keyword' => 'biblionumber' => 'biblioserver' => { '1' => '9002', '5' => '100' } );
$self->add_bib1_field_map('keyword' => 'totalissues' => 'biblioserver' => { '1' => '9003' } );
$self->add_bib1_field_map('keyword' => 'cn-bib-source' => 'biblioserver' => { '1' => '9004' } );
$self->add_bib1_field_map('keyword' => 'cn-bib-sort' => 'biblioserver' => { '1' => '9005' } );
$self->add_bib1_field_map('keyword' => 'itemtype' => 'biblioserver' => { '1' => '9006' } );
$self->add_search_field_alias( 'keyword' => 'itemtype' => 'mc-itemtype' );
$self->add_bib1_field_map('keyword' => 'cn-class' => 'biblioserver' => { '1' => '9007' } );
$self->add_bib1_field_map('keyword' => 'cn-item' => 'biblioserver' => { '1' => '9008' } );
$self->add_bib1_field_map('keyword' => 'cn-prefix' => 'biblioserver' => { '1' => '9009' } );
$self->add_bib1_field_map('keyword' => 'cn-suffix' => 'biblioserver' => { '1' => '9010' } );
$self->add_bib1_field_map('keyword' => 'suppress' => 'biblioserver' => { '1' => '9011' } );
$self->add_bib1_field_map('keyword' => 'id-other' => 'biblioserver' => { '1' => '9012' } );
$self->add_bib1_field_map('keyword' => 'date-entered-on-file' => 'biblioserver' => { '1' => 'date-entered-on-file' } );
$self->add_bib1_field_map('keyword' => 'extent' => 'biblioserver' => { '1' => 'Extent' } );
$self->add_bib1_field_map('keyword' => 'llength' => 'biblioserver' => { '1' => 'llength' } );
$self->add_bib1_field_map('keyword' => 'summary' => 'biblioserver' => { '1' => 'Summary' } );
$self->add_bib1_field_map('keyword' => 'withdrawn' => 'biblioserver' => { '1' => '8001' } );
$self->add_bib1_field_map('keyword' => 'lost' => 'biblioserver' => { '1' => '8002' } );
$self->add_bib1_field_map('keyword' => 'classification-source' => 'biblioserver' => { '1' => '8003' } );
$self->add_bib1_field_map('keyword' => 'materials-specified' => 'biblioserver' => { '1' => '8004' } );
$self->add_bib1_field_map('keyword' => 'damaged' => 'biblioserver' => { '1' => '8005' } );
$self->add_bib1_field_map('keyword' => 'restricted' => 'biblioserver' => { '1' => '8006' } );
$self->add_bib1_field_map('keyword' => 'cn-sort' => 'biblioserver' => { '1' => '8007' } );
$self->add_bib1_field_map('keyword' => 'notforloan' => 'biblioserver' => { '1' => '8008', '4' => '109' } );
$self->add_bib1_field_map('keyword' => 'ccode' => 'biblioserver' => { '1' => '8009' } );
$self->add_search_field_alias( 'keyword' => 'ccode' => 'mc-ccode' );
$self->add_bib1_field_map('keyword' => 'itemnumber' => 'biblioserver' => { '1' => '8010' } );
$self->add_bib1_field_map('keyword' => 'homebranch' => 'biblioserver' => { '1' => 'homebranch' } );
$self->add_search_field_alias( 'keyword' => 'homebranch' => 'branch' );
$self->add_bib1_field_map('keyword' => 'holdingbranch' => 'biblioserver' => { '1' => '8012' } );
$self->add_bib1_field_map('keyword' => 'location' => 'biblioserver' => { '1' => '8013' } );
$self->add_search_field_alias( 'keyword' => 'location' => 'mc-loc' );
$self->add_bib1_field_map('keyword' => 'acqsource' => 'biblioserver' => { '1' => '8015' } );
$self->add_bib1_field_map('keyword' => 'coded-location-qualifier' => 'biblioserver' => { '1' => '8016' } );
$self->add_bib1_field_map('keyword' => 'price' => 'biblioserver' => { '1' => '8017' } );
$self->add_bib1_field_map('keyword' => 'stocknumber' => 'biblioserver' => { '1' => '1062' } );
$self->add_search_field_alias( 'keyword' => 'stocknumber' => 'inv' );
$self->add_bib1_field_map('keyword' => 'stack' => 'biblioserver' => { '1' => '8018' } );
$self->add_bib1_field_map('keyword' => 'issues' => 'biblioserver' => { '1' => '8019' } );
$self->add_bib1_field_map('keyword' => 'renewals' => 'biblioserver' => { '1' => '8020' } );
$self->add_bib1_field_map('keyword' => 'reserves' => 'biblioserver' => { '1' => '8021' } );
$self->add_bib1_field_map('keyword' => 'local-classification' => 'biblioserver' => { '1' => '8022' } );
$self->add_bib1_field_map('keyword' => 'barcode' => 'biblioserver' => { '1' => '8023' } );
$self->add_search_field_alias( 'keyword' => 'barcode' => 'bc' );
$self->add_bib1_field_map('keyword' => 'onloan' => 'biblioserver' => { '1' => '8024' } );
$self->add_bib1_field_map('keyword' => 'datelastseen' => 'biblioserver' => { '1' => '8025' } );
$self->add_bib1_field_map('keyword' => 'datelastborrowed' => 'biblioserver' => { '1' => '8026' } );
$self->add_bib1_field_map('keyword' => 'copynumber' => 'biblioserver' => { '1' => '8027' } );
$self->add_bib1_field_map('keyword' => 'uri' => 'biblioserver' => { '1' => '8028' } );
$self->add_bib1_field_map('keyword' => 'replacementprice' => 'biblioserver' => { '1' => '8029' } );
$self->add_bib1_field_map('keyword' => 'replacementpricedate' => 'biblioserver' => { '1' => '8030' } );
$self->add_bib1_field_map('keyword' => 'itype' => 'biblioserver' => { '1' => '8031' } );
$self->add_search_field_alias( 'keyword' => 'itype' => 'mc-itype' );
$self->add_bib1_field_map('keyword' => 'ff8-22' => 'biblioserver' => { '1' => '8822' } );
$self->add_bib1_field_map('keyword' => 'ff8-23' => 'biblioserver' => { '1' => '8823' } );
$self->add_bib1_field_map('keyword' => 'ff8-34' => 'biblioserver' => { '1' => '8834' } );
# Audience
$self->add_bib1_field_map('keyword' => 'audience' => 'biblioserver' => { '1' => '8822' } );
$self->add_search_field_alias( 'keyword' => 'audience' => 'aud' );
# Content and Literary form
$self->add_bib1_field_map('keyword' => 'fiction' => 'biblioserver' => { '1' => '8833' } );
$self->add_search_field_alias( 'keyword' => 'fiction' => 'fic' );
$self->add_bib1_field_map('keyword' => 'biography' => 'biblioserver' => { '1' => '8834' } );
$self->add_search_field_alias( 'keyword' => 'biography' => 'bio' );
# Format
$self->add_bib1_field_map('keyword' => 'format' => 'biblioserver' => { '1' => '8823' } );
# format used as a limit FIXME: needed?
$self->add_bib1_field_map('keyword' => 'l-format' => 'biblioserver' => { '1' => '8703' } );
$self->add_bib1_field_map('keyword' => 'illustration-code' => 'biblioserver' => { '1' => 'Illustration-code ' } );
# Lexile Number
$self->add_bib1_field_map('keyword' => 'lex' => 'biblioserver' => { '1' => '9903 r=r' } );
#Accelerated Reader Level
$self->add_bib1_field_map('keyword' => 'arl' => 'biblioserver' => { '1' => '9904 r=r' } );
#Accelerated Reader Point
$self->add_bib1_field_map('keyword' => 'arp' => 'biblioserver' => { '1' => '9014 r=r' } );
# Curriculum
$self->add_bib1_field_map('keyword' => 'curriculum' => 'biblioserver' => { '1' => '9658' } );
## Statuses
$self->add_bib1_field_map('keyword' => 'popularity' => 'biblioserver' => { '1' => 'issues' } );
## Type Limits
$self->add_bib1_field_map('keyword' => 'dt-bks' => 'biblioserver' => { '1' => '8700' } );
$self->add_bib1_field_map('keyword' => 'dt-vis' => 'biblioserver' => { '1' => '8700' } );
$self->add_bib1_field_map('keyword' => 'dt-sr' => 'biblioserver' => { '1' => '8700' } );
$self->add_bib1_field_map('keyword' => 'dt-cf' => 'biblioserver' => { '1' => '8700' } );
$self->add_bib1_field_map('keyword' => 'dt-map' => 'biblioserver' => { '1' => '8700' } );
$self->add_bib1_field_map('keyword' => 'name' => 'biblioserver' => { '1' => '1002' } );
$self->add_bib1_field_map('keyword' => 'item' => 'biblioserver' => { '1' => '9520' } );
$self->add_bib1_field_map('keyword' => 'host-item-number' => 'biblioserver' => { '1' => '8911' } );
$self->add_search_field_alias( 'keyword' => 'host-item-number' => 'hi' );
$self->add_bib1_field_map('keyword' => 'alwaysmatch' => 'biblioserver' => { '1' => '_ALLRECORDS', '2' => '103' } );
$self->add_bib1_field_map('subject' => 'complete' => 'biblioserver' => { '1' => '21', '3' => '1', '4' => '1', '5' => '100', '6' => '3' } );
$self->add_bib1_modifier_map('relevance' => 'biblioserver' => { '2' => '102' } );
$self->add_bib1_modifier_map('title-sort-za' => 'biblioserver' => { '7' => '2', '1' => '36', '' => '0', 'op' => '@or' } );
$self->add_bib1_modifier_map('title-sort-az' => 'biblioserver' => { '7' => '1', '1' => '36', '' => '0', 'op' => '@or' } );
$self->add_bib1_modifier_map('relevance_dsc' => 'biblioserver' => { '2' => '102' } );
$self->add_bib1_modifier_map('title_dsc' => 'biblioserver' => { '7' => '2', '1' => '4', '' => '0', 'op' => '@or' } );
$self->add_bib1_modifier_map('title_asc' => 'biblioserver' => { '7' => '1', '1' => '4', '' => '0', 'op' => '@or' } );
$self->add_bib1_modifier_map('author_asc' => 'biblioserver' => { '7' => '2', '1' => '1003', '' => '0', 'op' => '@or' } );
$self->add_bib1_modifier_map('author_dsc' => 'biblioserver' => { '7' => '1', '1' => '1003', '' => '0', 'op' => '@or' } );
$self->add_bib1_modifier_map('popularity_asc' => 'biblioserver' => { '7' => '2', '1' => '9003', '' => '0', 'op' => '@or' } );
$self->add_bib1_modifier_map('popularity_dsc' => 'biblioserver' => { '7' => '1', '1' => '9003', '' => '0', 'op' => '@or' } );
$self->add_bib1_modifier_map('call_number_asc' => 'biblioserver' => { '7' => '2', '1' => '8007', '' => '0', 'op' => '@or' } );
$self->add_bib1_modifier_map('call_number_dsc' => 'biblioserver' => { '7' => '1', '1' => '8007', '' => '0', 'op' => '@or' } );
$self->add_bib1_modifier_map('pubdate_asc' => 'biblioserver' => { '7' => '2', '1' => '31', '' => '0', 'op' => '@or' } );
$self->add_bib1_modifier_map('pubdate_dsc' => 'biblioserver' => { '7' => '1', '1' => '31', '' => '0', 'op' => '@or' } );
$self->add_bib1_modifier_map('acqdate_asc' => 'biblioserver' => { '7' => '2', '1' => '32', '' => '0', 'op' => '@or' } );
$self->add_bib1_modifier_map('acqdate_dsc' => 'biblioserver' => { '7' => '1', '1' => '32', '' => '0', 'op' => '@or' } );
$self->add_bib1_modifier_map('title_za' => 'biblioserver' => { '7' => '2', '1' => '4', '' => '0', 'op' => '@or' } );
$self->add_bib1_modifier_map('title_az' => 'biblioserver' => { '7' => '1', '1' => '4', '' => '0', 'op' => '@or' } );
$self->add_bib1_modifier_map('author_za' => 'biblioserver' => { '7' => '2', '1' => '1003', '' => '0', 'op' => '@or' } );
$self->add_bib1_modifier_map('author_az' => 'biblioserver' => { '7' => '1', '1' => '1003', '' => '0', 'op' => '@or' } );
$self->add_bib1_modifier_map('ascending' => 'biblioserver' => { '7' => '1' } );
$self->add_bib1_modifier_map('descending' => 'biblioserver' => { '7' => '2' } );
$self->add_bib1_field_map('title' => 'exacttitle' => 'biblioserver' => { '1' => '4', '4' => '1', '6' => '3' } );
$self->add_search_field_alias( 'title' => 'exacttitle' => 'ti,ext' );
$self->add_bib1_field_map('author' => 'exactauthor' => 'biblioserver' => { '1' => '1003', '4' => '1', '6' => '3' } );
$self->add_search_field_alias( 'author' => 'exactauthor' => 'au,ext' );
$self->add_bib1_field_map('subject' => 'headingmain' => 'authorityserver' => { '1' => 'Heading-Main' } );
$self->add_bib1_field_map('subject' => 'heading' => 'authorityserver' => { '1' => 'Heading' } );
$self->add_bib1_field_map('subject' => 'matchheading' => 'authorityserver' => { '1' => 'Match-heading' } );
$self->add_bib1_field_map('subject' => 'seefrom' => 'authorityserver' => { '1' => 'Match-heading-see-from' } );
$self->add_bib1_field_map('subject' => '' => 'authorityserver' => { '1' => 'Match-heading' } );
$self->add_bib1_field_map('keyword' => 'alwaysmatch' => 'authorityserver' => { '1' => '_ALLRECORDS', '2' => '103' } );
$self->add_bib1_field_map('keyword' => 'match' => 'authorityserver' => { '1' => 'Match' } );
$self->add_bib1_field_map('keyword' => 'thesaurus' => 'authorityserver' => { '1' => 'Subject-heading-thesaurus' } );
$self->add_bib1_field_map('keyword' => 'authtype' => 'authorityserver' => { '1' => 'authtype', '5' => '100' } );
$self->add_bib1_field_map('keyword' => '' => 'authorityserver' => { '1' => 'Any' } );
$self->add_search_field_alias( 'subject' => 'headingmain' => 'mainmainentry' );
$self->add_search_field_alias( 'subject' => 'heading' => 'mainentry' );
$self->add_search_field_alias( 'subject' => 'heading' => 'he' );
$self->add_search_field_alias( 'subject' => 'matchheading' => 'match-heading' );
$self->add_search_field_alias( 'keyword' => '' => 'any' );
$self->add_search_field_alias( 'keyword' => 'match' => 'match' );
$self->add_search_field_alias( 'subject' => 'seefrom' => 'see-from' );
$self->add_search_field_alias( 'keyword' => 'thesaurus' => 'thesaurus' );
$self->add_search_field_alias( 'keyword' => 'alwaysmatch' => 'all' );
$self->add_search_field_alias( 'keyword' => 'authtype' => 'authtype' );
$self->add_search_field_alias( 'keyword' => 'authtype' => 'at' );
$self->add_bib1_field_map('subject' => 'start' => 'authorityserver' => { '3' => '2', '4' => '1', '5' => '1' } );
$self->add_bib1_field_map('subject' => 'exact' => 'authorityserver' => { '4' => '1', '5' => '100', '6' => '3' } );
$self->add_bib1_modifier_map('HeadingAsc' => 'authorityserver' => { '7' => '1', '1' => 'Heading', '' => '0', 'op' => '@or' } );
$self->add_bib1_modifier_map('HeadingDsc' => 'authorityserver' => { '7' => '2', '1' => 'Heading', '' => '0', 'op' => '@or' } );
$self->add_bib1_modifier_map('AuthidAsc' => 'authorityserver' => { '7' => '1', '1' => 'Local-Number', '' => '0', 'op' => '@or' } );
$self->add_bib1_modifier_map('AuthidDsc' => 'authorityserver' => { '7' => '2', '1' => 'Local-Number', '' => '0', 'op' => '@or' } );
$self->add_bib1_modifier_map('Relevance' => 'authorityserver' => { '2' => '102' } );
return $self;
}
1;

View File

@ -1,54 +0,0 @@
package Koha::QueryParser::Driver::PQF::Util;
# This file is part of Koha.
#
# Copyright 2012 C & P Bibliography Services
#
# Koha is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Koha is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Koha; if not, see <http://www.gnu.org/licenses>.
use Scalar::Util qw(looks_like_number);
use strict;
use warnings;
=head1 NAME
Koha::QueryParser::Driver::PQF::Util - Utility module for PQF QueryParser driver
=head1 FUNCTIONS
=head2 attributes_to_attr_string
Koha::QueryParser::Driver::PQF::Util(%attributes);
Koha::QueryParser::Driver::PQF::Util({ '1' => '1003', '4' => '6' });
Convert a hashref with a Bib-1 mapping into its PQF string representation.
=cut
sub attributes_to_attr_string {
my ($attributes) = @_;
my $attr_string = '';
foreach my $key ( sort keys %{$attributes} ) {
next unless looks_like_number($key);
$attr_string .= ' @attr ' . $key . '=' . $attributes->{ $key } . ' ';
}
$attr_string =~ s/^\s*//;
$attr_string =~ s/\s*$//;
$attr_string .= ' ' . $attributes->{''} if defined $attributes->{''};
return $attr_string;
}
1;

View File

@ -1,70 +0,0 @@
package Koha::QueryParser::Driver::PQF::query_plan;
# This file is part of Koha.
#
# Copyright 2012 C & P Bibliography Services
#
# Koha is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Koha is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Koha; if not, see <http://www.gnu.org/licenses>.
use base 'OpenILS::QueryParser::query_plan';
use strict;
use warnings;
=head1 NAME
Koha::QueryParser::Driver::PQF::query_plan - query_plan subclass for PQF driver
=head1 FUNCTIONS
=head2 Koha::QueryParser::Driver::PQF::query_plan::target_syntax
my $pqf = $query_plan->target_syntax($server);
Transforms an OpenILS::QueryParser::query_plan object into PQF. Do not use directly.
=cut
sub target_syntax {
my ($self, $server) = @_;
my $pqf = '';
my $node_pqf;
my $node_count = 0;
for my $node ( @{$self->query_nodes} ) {
if (ref($node)) {
$node_pqf = $node->target_syntax($server);
$node_count++ if $node_pqf;
$pqf .= $node_pqf;
}
}
$pqf = ($self->joiner eq '|' ? ' @or ' : ' @and ') x ($node_count - 1) . $pqf if $node_count > 1;
$node_count = ($node_count ? '1' : '0');
for my $node ( @{$self->filters} ) {
if (ref($node)) {
$node_pqf = $node->target_syntax($server);
$node_count++ if $node_pqf;
$pqf .= $node_pqf;
}
}
$pqf = ($self->joiner eq '|' ? ' @or ' : ' @and ') x ($node_count - 1) . $pqf if $node_count > 1;
foreach my $modifier ( @{$self->modifiers} ) {
my $modifierpqf = $modifier->target_syntax($server, $self);
$pqf = $modifierpqf . ' ' . $pqf if $modifierpqf;
}
return ($self->negate ? '@not @attr 1=_ALLRECORDS @attr 2=103 "" ' : '') . $pqf;
}
1;

View File

@ -1,46 +0,0 @@
package Koha::QueryParser::Driver::PQF::query_plan::facet;
# This file is part of Koha.
#
# Copyright 2012 C & P Bibliography Services
#
# Koha is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Koha is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Koha; if not, see <http://www.gnu.org/licenses>.
use base 'OpenILS::QueryParser::query_plan::facet';
use strict;
use warnings;
=head1 NAME
Koha::QueryParser::Driver::PQF::query_plan::facet - facet subclass for PQF driver
=head1 FUNCTIONS
=head2 Koha::QueryParser::Driver::PQF::query_plan::facet::target_syntax
my $pqf = $facet->target_syntax($server);
Transforms an OpenILS::QueryParser::query_plan::facet object into PQF. Do not use
directly.
=cut
sub target_syntax {
my ($self, $server) = @_;
return '';
}
1;

View File

@ -1,51 +0,0 @@
package Koha::QueryParser::Driver::PQF::query_plan::filter;
# This file is part of Koha.
#
# Copyright 2012 C & P Bibliography Services
#
# Koha is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Koha is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Koha; if not, see <http://www.gnu.org/licenses>.
use base 'OpenILS::QueryParser::query_plan::filter';
use strict;
use warnings;
=head1 NAME
Koha::QueryParser::Driver::PQF::query_plan::filter - filter subclass for PQF driver
=head1 FUNCTIONS
=head2 Koha::QueryParser::Driver::PQF::query_plan::filter::target_syntax
my $pqf = $filter->target_syntax($server);
Transforms an OpenILS::QueryParser::query_plan::filter object into PQF. Do not use
directly.
=cut
sub target_syntax {
my ($self, $server) = @_;
my $attributes = $self->plan->QueryParser->bib1_mapping_by_name( 'filter', $self->name, $server );
if ($attributes->{'target_syntax_callback'}) {
return $attributes->{'target_syntax_callback'}->($self->plan->QueryParser, $self->name, $self->args, $self->negate, $server);
} else {
return '';
}
}
1;

View File

@ -1,50 +0,0 @@
package Koha::QueryParser::Driver::PQF::query_plan::modifier;
# This file is part of Koha.
#
# Copyright 2012 C & P Bibliography Services
#
# Koha is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Koha is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Koha; if not, see <http://www.gnu.org/licenses>.
use base 'OpenILS::QueryParser::query_plan::modifier';
use strict;
use warnings;
=head1 NAME
Koha::QueryParser::Driver::PQF::query_plan::modifer - modifier subclass for PQF driver
=head1 FUNCTIONS
=head2 Koha::QueryParser::Driver::PQF::query_plan::modifier::target_syntax
my $pqf = $modifier->target_syntax($server, $query_plan);
Transforms an OpenILS::QueryParser::query_plan::modifier object into PQF. Do not use
directly. The second argument points ot the query_plan, since modifiers do
not have a reference to their parent query_plan.
=cut
sub target_syntax {
my ($self, $server, $query_plan) = @_;
my $pqf = '';
my $attributes = $query_plan->QueryParser->bib1_mapping_by_name('modifier', $self->name, $server);
$pqf = ($attributes->{'op'} ? $attributes->{'op'} . ' ' : '') . ($self->negate ? '@not @attr 1=_ALLRECORDS @attr 2=103 "" ' : '') . $attributes->{'attr_string'};
return $pqf;
}
1;

View File

@ -1,106 +0,0 @@
package Koha::QueryParser::Driver::PQF::query_plan::node;
# This file is part of Koha.
#
# Copyright 2012 C & P Bibliography Services
#
# Koha is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Koha is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Koha; if not, see <http://www.gnu.org/licenses>.
use base 'OpenILS::QueryParser::query_plan::node';
use strict;
use warnings;
=head1 NAME
Koha::QueryParser::Driver::PQF::query_plan::node - node subclass for PQF driver
=head1 FUNCTIONS
=head2 Koha::QueryParser::Driver::PQF::query_plan::node::target_syntax
my $pqf = $node->target_syntax($server);
Transforms an OpenILS::QueryParser::query_plan::node object into PQF. Do not use directly.
=cut
sub target_syntax {
my ($self, $server) = @_;
my $pqf = '';
my $atom_content;
my $atom_count = 0;
my @fields = ();
my $fieldobj;
my $relbump;
if (scalar(@{$self->fields})) {
foreach my $field (@{$self->fields}) {
$fieldobj = $self->plan->QueryParser->bib1_mapping_by_name('field', $self->classname, $field, $server);
$relbump = $self->plan->QueryParser->bib1_mapping_by_name('relevance_bump', $self->classname, $field, $server);
if ($relbump && defined $relbump->{'attr_string'}) {
$fieldobj->{'attr_string'} .= ' ' . $relbump->{'attr_string'};
}
push @fields, $fieldobj unless (!defined($fieldobj) || ($field eq $self->classname && @{$self->fields} > 1));
}
} else {
$fieldobj = $self->plan->QueryParser->bib1_mapping_by_name('field', $self->classname, $self->classname, $server);
my $relbumps = $self->plan->QueryParser->bib1_mapping_by_name('relevance_bump', $self->classname, '', $server);
push @fields, $fieldobj;
if ($relbumps) {
foreach my $field (keys %$relbumps) {
$relbump = $relbumps->{$field};
$fieldobj = $self->plan->QueryParser->bib1_mapping_by_name('field', $relbump->{'classname'}, $relbump->{'field'}, $server);
$fieldobj->{'attr_string'} ||= '';
$fieldobj->{'attr_string'} .= ' ' . $relbump->{$server}{'attr_string'} if $relbump->{$server}{'attr_string'};
push @fields, $fieldobj;
}
}
}
if (@{$self->phrases}) {
foreach my $phrase (@{$self->phrases}) {
if ($phrase) {
$phrase =~ s/"/\\"/g;
$pqf .= ' @or ' x (scalar(@fields) - 1);
foreach my $attributes (@fields) {
$attributes->{'attr_string'} ||= '';
$pqf .= $attributes->{'attr_string'} . ($attributes->{'4'} ? '' : ' @attr 4=1') . ' "' . $phrase . '" ';
}
$atom_count++;
}
}
} else {
foreach my $atom (@{$self->query_atoms}) {
if (ref($atom)) {
$atom_content = $atom->target_syntax($server);
if ($atom_content) {
$pqf .= ' @or ' x (scalar(@fields) - 1);
foreach my $attributes (@fields) {
$attributes->{'attr_string'} ||= '';
if ($self->plan->QueryParser->custom_data->{'QueryAutoTruncate'} || $atom->suffix eq '*') {
$attributes->{'attr_string'} .= ($attributes->{'5'} ? '' : ' @attr 5=1 ');
}
$pqf .= $attributes->{'attr_string'} . ($attributes->{'4'} ? '' : ' @attr 4=6 ') . $atom_content . ' ';
}
$atom_count++;
}
}
}
}
$pqf = (OpenILS::QueryParser::_util::default_joiner eq '|' ? ' @or ' : ' @and ') x ($atom_count - 1) . $pqf if $atom_count > 1;
return ($self->negate ? '@not @attr 1=_ALLRECORDS @attr 2=103 "" ' : '') . $pqf;
}
1;

View File

@ -1,49 +0,0 @@
package Koha::QueryParser::Driver::PQF::query_plan::node::atom;
# This file is part of Koha.
#
# Copyright 2012 C & P Bibliography Services
#
# Koha is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Koha is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Koha; if not, see <http://www.gnu.org/licenses>.
use base 'OpenILS::QueryParser::query_plan::node::atom';
use strict;
use warnings;
=head1 NAME
Koha::QueryParser::Driver::PQF::query_plan::node::atom - atom subclass for PQF driver
=head1 FUNCTIONS
=head2 Koha::QueryParser::Driver::PQF::query_plan::node::atom::target_syntax
my $pqf = $atom->target_syntax($server);
Transforms an OpenILS::QueryParser::query_plan::node::atom object into PQF. Do not use
directly.
=cut
sub target_syntax {
my ($self, $server) = @_;
my $content = $self->content;
$content =~ s/"/\\"/g;
return ' "' . $content . '" ';
}
1;

File diff suppressed because it is too large Load Diff

View File

@ -230,35 +230,6 @@ if ( ! C4::Context->config('tmp_path') ) {
}
}
# Test QueryParser configuration sanity
if ( C4::Context->preference( 'UseQueryParser' ) ) {
# Get the QueryParser configuration file name
my $queryparser_file = C4::Context->config( 'queryparser_config' );
my $queryparser_fallback_file = '/etc/koha/searchengine/queryparser.yaml';
# Check QueryParser is functional
my $QParser = C4::Context->queryparser();
my $queryparser_error = {};
if ( ! defined $QParser || ref($QParser) ne 'Koha::QueryParser::Driver::PQF' ) {
# Error initializing the QueryParser object
# Get the used queryparser.yaml file path to report the user
$queryparser_error->{ fallback } = ( defined $queryparser_file ) ? 0 : 1;
$queryparser_error->{ file } = ( defined $queryparser_file )
? $queryparser_file
: $queryparser_fallback_file;
# Report error data to the template
$template->param( QueryParserError => $queryparser_error );
} else {
# Check for an absent queryparser_config entry in koha-conf.xml
if ( ! defined $queryparser_file ) {
# Not an error but a warning for the missing entry in koha-conf-xml
push @xml_config_warnings, {
error => 'queryparser_entry_missing',
file => $queryparser_fallback_file
};
}
}
}
# Test Zebra facets configuration
if ( !defined C4::Context->config('use_zebra_facets') ) {
push @xml_config_warnings, { error => 'use_zebra_facets_entry_missing' };

View File

@ -68,21 +68,14 @@ if ($query) {
# build query
my @operands = $query;
my $QParser;
$QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser'));
my $builtquery;
my $query_cgi;
my $builder = Koha::SearchEngine::QueryBuilder->new(
{ index => $Koha::SearchEngine::BIBLIOS_INDEX } );
my $searcher = Koha::SearchEngine::Search->new(
{ index => $Koha::SearchEngine::BIBLIOS_INDEX } );
if ($QParser) {
$builtquery = $query;
$query_cgi = "q=".uri_escape_utf8($query);
} else {
( undef, $builtquery, undef, $query_cgi, undef, undef, undef, undef, undef, undef ) =
$builder->build_query_compat( undef, \@operands, undef, undef, undef, 0, $lang );
}
( undef, $builtquery, undef, $query_cgi, undef, undef, undef, undef, undef, undef ) =
$builder->build_query_compat( undef, \@operands, undef, undef, undef, 0, $lang );
$template->param( search_query => $builtquery ) if C4::Context->preference('DumpSearchQueryTemplate');

View File

@ -172,15 +172,8 @@ my $launcher = sub {
my $startfrom = $query->param('startfrom');
my $resultsperpage = $query->param('resultsperpage') || 20;
my $orderby;
my $QParser;
$QParser = C4::Context->queryparser if ( C4::Context->preference('UseQueryParser') );
my $op;
my $op = 'and';
if ($QParser) {
$op = '&&';
} else {
$op = 'and';
}
my $searcher = Koha::SearchEngine::Search->new(
{ index => $Koha::SearchEngine::BIBLIOS_INDEX } );
$search = 'kw:' . $search . " $op mc-itemtype:" . $itype if $itype;

View File

@ -359,14 +359,7 @@ sub plugin {
my $startfrom = $query->param('startfrom');
my $resultsperpage = $query->param('resultsperpage') || 20;
my $orderby;
my $QParser;
$QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser'));
my $op;
if ($QParser) {
$op = '&&';
} else {
$op = 'and';
}
my $op = 'and';
$search = 'kw:'.$search." $op mc-itemtype:".$itype if $itype;
my $searcher = Koha::SearchEngine::Search->new({index => $Koha::SearchEngine::BIBLIOS_INDEX});
my ( $errors, $results, $total_hits ) = $searcher->simple_search_compat($search, $startfrom * $resultsperpage, $resultsperpage );

View File

@ -304,7 +304,6 @@ __END_SRU_PUBLICSERVER__
<zebra_lockdir>/var/lock/koha/__KOHASITE__</zebra_lockdir>
<use_zebra_facets>1</use_zebra_facets>
<zebra_max_record_size>1024</zebra_max_record_size>
<queryparser_config>/etc/koha/searchengine/queryparser.yaml</queryparser_config>
<log4perl_conf>__KOHA_CONF_DIR__/log4perl.conf</log4perl_conf>
<!-- Uncomment/edit next setting if you want to adjust zebra log levels.
Default is: none,fatal,warn.

View File

@ -121,7 +121,6 @@ __PAZPAR2_TOGGLE_XML_POST__
<zebra_lockdir>__ZEBRA_LOCK_DIR__</zebra_lockdir>
<use_zebra_facets>1</use_zebra_facets>
<zebra_max_record_size>1024</zebra_max_record_size>
<queryparser_config>__KOHA_CONF_DIR__/searchengine/queryparser.yaml</queryparser_config>
<log4perl_conf>__KOHA_CONF_DIR__/log4perl.conf</log4perl_conf>
<!-- Uncomment/edit next setting if you want to adjust zebra log levels.
Default is: none,fatal,warn.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
$DBversion = 'XXX'; # will be replaced by the RM
if( CheckVersion( $DBversion ) ) {
$dbh->do( q|
DELETE FROM systempreferences WHERE variable="UseQueryParser"
|);
SetVersion( $DBversion );
print "Upgrade to $DBversion done (Bug XXXXX - Remove UseQueryParser system preference)\n";
}

View File

@ -673,7 +673,6 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `
('UseEmailReceipts','0','','Send email receipts for payments and write-offs','YesNo'),
('UseICU','0','1','Tell Koha if ICU indexing is in use for Zebra or not.','YesNo'),
('UseKohaPlugins','0','','Enable or disable the ability to use Koha Plugins.','YesNo'),
('UseQueryParser','0',NULL,'If enabled, try to use QueryParser for queries.','YesNo'),
('UseTransportCostMatrix','0','','Use Transport Cost Matrix when filling holds','YesNo'),
('UseWYSIWYGinSystemPreferences','0','','Show WYSIWYG editor when editing certain HTML system preferences.','YesNo'),
('viewISBD','1','','Allow display of ISBD view of bibiographic records','YesNo'),

View File

@ -184,7 +184,7 @@
</div>
<div id="sysinfo">
[% IF warnPrefBiblioAddsAuthorities || warnPrefEasyAnalyticalRecords || warnPrefAnonymousPatronOPACPrivacy || warnPrefAnonymousPatronAnonSuggestions || warnPrefAnonymousPatronOPACPrivacy_PatronDoesNotExist || warnPrefAnonymousPatronAnonSuggestions_PatronDoesNotExist || warnNoActiveCurrency || QueryParserError || warnIsRootUser || xml_config_warnings.size || AutoSelfCheckPatronDoesNotHaveSelfCheckPerm || AutoSelfCheckPatronHasTooManyPerm || warnStatisticsFieldsError || warnNoTemplateCaching || warnILLConfiguration || has_ai_issues || oauth2_missing_deps || bad_yaml_prefs || warnRelationships %]
[% IF warnPrefBiblioAddsAuthorities || warnPrefEasyAnalyticalRecords || warnPrefAnonymousPatronOPACPrivacy || warnPrefAnonymousPatronAnonSuggestions || warnPrefAnonymousPatronOPACPrivacy_PatronDoesNotExist || warnPrefAnonymousPatronAnonSuggestions_PatronDoesNotExist || warnNoActiveCurrency || warnIsRootUser || xml_config_warnings.size || AutoSelfCheckPatronDoesNotHaveSelfCheckPerm || AutoSelfCheckPatronHasTooManyPerm || warnStatisticsFieldsError || warnNoTemplateCaching || warnILLConfiguration || has_ai_issues || oauth2_missing_deps || bad_yaml_prefs || warnRelationships %]
[% IF (warnIsRootUser) %]
<h2>Warning regarding current user</h2>
<p>You are logged in as the database administrative user. This is not recommended because some parts of Koha will not function as expected when using this account.</p>
@ -246,7 +246,7 @@
[% END %]
[% END %]
[% IF warnPrefBiblioAddsAuthorities || warnPrefEasyAnalyticalRecords || warnPrefAnonymousPatronOPACPrivacy || warnPrefAnonymousPatronAnonSuggestions || warnPrefAnonymousPatronOPACPrivacy_PatronDoesNotExist || warnPrefAnonymousPatronAnonSuggestions_PatronDoesNotExist || warnNoActiveCurrency || QueryParserError || AutoSelfCheckPatronDoesNotHaveSelfCheckPerm || AutoSelfCheckPatronHasTooManyPerm || warnStatisticsFieldsError || warnNoTemplateCaching || warnILLConfiguration || oauth2_missing_deps || bad_yaml_prefs || warnIssuingRules %]
[% IF warnPrefBiblioAddsAuthorities || warnPrefEasyAnalyticalRecords || warnPrefAnonymousPatronOPACPrivacy || warnPrefAnonymousPatronAnonSuggestions || warnPrefAnonymousPatronOPACPrivacy_PatronDoesNotExist || warnPrefAnonymousPatronAnonSuggestions_PatronDoesNotExist || warnNoActiveCurrency || AutoSelfCheckPatronDoesNotHaveSelfCheckPerm || AutoSelfCheckPatronHasTooManyPerm || warnStatisticsFieldsError || warnNoTemplateCaching || warnILLConfiguration || oauth2_missing_deps || bad_yaml_prefs || warnIssuingRules %]
<h2>Warnings regarding the system configuration</h2>
<table>
<caption>Preferences and parameters</caption>
@ -274,18 +274,6 @@
[% IF warnStatisticsFieldsError %]
<tr><th scope="row"><b>Warning</b> </th><td>System preference 'StatisticsFields' contains field names not belonging to the items database table: [% warnStatisticsFieldsError | html %] </td></tr>
[% END %]
[% IF QueryParserError %]
<tr><th scope="row"><b>Warning</b> </th><td>
You have set UseQueryParser but there was a problem inititializing QueryParser.
[% IF QueryParserError.fallback %]
The 'queryparser_config' entry is missing in your configuration file.
The following configuration file was used without success: [% QueryParserError.file | html %].
[% ELSE %]
The following configuration file was used without success: [% QueryParserError.file | html %].
[% END %]
</td>
</tr>
[% END %]
[% IF AutoSelfCheckPatronDoesNotHaveSelfCheckPerm %]
<tr><th scope="row"><b>Warning</b> </th><td>
The patron used for the self checkout module at the OPAC does not have the self_check => self_checkout_module permission.
@ -357,13 +345,6 @@
<a href="https://wiki.koha-community.org/wiki/Switching_to_dom_indexing">Switching to dom indexing</a>
</td>
</tr>
[% ELSIF config_entry.error == 'queryparser_entry_missing' %]
<tr>
<th scope="row"><b>Warning</b></th>
<td>You have set UseQueryParser but the 'queryparser_config' entry is missing in your configuration
file. [% config_entry.file | html %] is used as a fallback.
</td>
</tr>
[% ELSIF config_entry.error == 'use_zebra_facets_entry_missing' %]
<tr>
<th scope="row"><b>Warning</b></th>

View File

@ -258,7 +258,7 @@ Cataloging:
choices:
yes: "do"
no: "don't"
- attempt to match aggressively by trying all variations of the ISBNs in the imported record as a phrase in the ISBN fields of already cataloged records. Note that this preference has no effect if UseQueryParser is on.
- attempt to match aggressively by trying all variations of the ISBNs in the imported record as a phrase in the ISBN fields of already cataloged records.
-
- Display the MARC field/subfields
- pref: AdditionalFieldsInZ3950ResultSearch
@ -269,7 +269,7 @@ Cataloging:
choices:
yes: "do"
no: "don't"
- attempt to match aggressively by trying all variations of the ISSNs in the imported record as a phrase in the ISSN fields of already cataloged records. Note that this preference has no effect if UseQueryParser is on.
- attempt to match aggressively by trying all variations of the ISSNs in the imported record as a phrase in the ISSN fields of already cataloged records.
Exporting:
-

View File

@ -65,13 +65,6 @@ Searching:
yes: Using
no: "Not using"
- 'ICU Zebra indexing. Please note: This setting will not affect Zebra indexing, it should only be used to tell Koha that you have activated ICU indexing if you have actually done so, since there is no way for Koha to figure this out on its own.'
-
- pref: UseQueryParser
default: 1
choices:
yes: Try
no: "Do not try"
- 'to use the QueryParser module for parsing queries. Please note: enabling this will have no impact if you do not have QueryParser installed, and everything will continue to work as usual.'
-
- pref: IncludeSeeFromInSearches
default: 0
@ -250,7 +243,7 @@ Searching:
choices:
yes: "search"
no: "don't search"
- on all variations of the ISBN. Note that this preference has no effect if UseQueryParser is on.
- on all variations of the ISBN.
Did you Mean/Spell checking:
-
- "Swedish service for spellchecking.<br/>"

View File

@ -67,8 +67,6 @@ my $display_columns = [ {_add => {label => "Add Item", link_fi
];
if ( $op eq "do_search" ) {
my $QParser;
$QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser'));
$idx = $query->param('idx');
$ccl_textbox = $query->param('ccl_textbox');
if ( $ccl_textbox && $idx ) {
@ -82,14 +80,8 @@ if ( $op eq "do_search" ) {
$datefrom = eval { dt_from_string ( $datefrom ) };
if ($datefrom) {
$datefrom = output_pref( { dt => $datefrom, dateonly => 1, dateformat => 'iso' } );
if ($QParser) {
$ccl_query .= ' && ' if $ccl_textbox;
$ccl_query .=
"acqdate(" . $datefrom . '-)';
} else {
$ccl_query .= ' and ' if $ccl_textbox;
$ccl_query .= "acqdate,ge,st-date-normalized=" . $datefrom;
}
$ccl_query .= ' and ' if $ccl_textbox;
$ccl_query .= "acqdate,ge,st-date-normalized=" . $datefrom;
}
}
@ -97,13 +89,8 @@ if ( $op eq "do_search" ) {
$dateto = eval { dt_from_string ( $dateto ) };
if ($dateto) {
$dateto = output_pref( { dt => $dateto, dateonly => 1, dateformat => 'iso' } );
if ($QParser) {
$ccl_query .= ' && ' if ( $ccl_textbox || $datefrom );
$ccl_query .= "acqdate(-" . $dateto . ')';
} else {
$ccl_query .= ' and ' if ( $ccl_textbox || $datefrom );
$ccl_query .= "acqdate,le,st-date-normalized=" . $dateto;
}
$ccl_query .= ' and ' if ( $ccl_textbox || $datefrom );
$ccl_query .= "acqdate,le,st-date-normalized=" . $dateto;
}
}

View File

@ -598,14 +598,7 @@ sub build_query {
my $string = build_simplequery($matchingpoint,$record);
push @searchstrings,$string if (length($string)>0);
}
my $QParser;
$QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser'));
my $op;
if ($QParser) {
$op = '&&';
} else {
$op = 'and';
}
my $op = 'and';
return join(" $op ",@searchstrings);
}
sub build_simplequery {
@ -621,14 +614,7 @@ sub build_simplequery {
}
}
}
my $QParser;
$QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser'));
my $op;
if ($QParser) {
$op = '&&';
} else {
$op = 'and';
}
my $op = 'and';
return join(" $op ",@searchstrings);
}
sub report_item_errors {

View File

@ -92,7 +92,7 @@ if ( $op eq "do_search" && $query ) {
# add the limits if applicable
my $itemtypelimit = $input->param('itemtypelimit');
my $ccodelimit = $input->param('ccodelimit');
my $op = C4::Context->preference('UseQueryParser') ? '&&' : 'and';
my $op = 'and';
$query .= " $op $itype_or_itemtype:$itemtypelimit" if $itemtypelimit;
$query .= " $op ccode:$ccodelimit" if $ccodelimit;
$debug && warn $query;

View File

@ -1,136 +0,0 @@
#!/usr/bin/perl
use strict;
use warnings;
use Test::More;
use Test::Deep;
use Module::Load::Conditional qw(can_load);
BEGIN {
use_ok( 'Koha::QueryParser::Driver::PQF' );
}
my $QParser = Koha::QueryParser::Driver::PQF->new();
ok(defined $QParser, 'Successfully created empty QP object');
ok($QParser->load_config('./etc/searchengine/queryparser.yaml'), 'Loaded QP config');
is($QParser->search_class_count, 4, 'Initialized 4 search classes');
is (scalar(@{$QParser->search_fields()->{'keyword'}}), 111, "Correct number of search fields for 'keyword' class");
# Set keyword search as the default
$QParser->default_search_class('keyword');
my $kwd_search = q/@attr 1=1016 @attr 4=6/;
my $weight1 = q/@attr 2=102 @attr 9=20 @attr 4=6/;
my $weight2 = q/@attr 2=102 @attr 9=34 @attr 4=6/;
like( $QParser->target_syntax('biblioserver', 'smith'),
qr/\@or \@or $kwd_search "smith" ($weight1 "smith" $weight2 "smith"|$weight2 "smith" $weight1 "smith")/,
'super simple keyword query');
is($QParser->target_syntax('biblioserver', 'au:smith'),
'@attr 1=1003 @attr 4=6 "smith"', 'simple author query');
is($QParser->target_syntax('biblioserver', 'keyword|publisher:smith'),
'@attr 1=1018 @attr 4=6 "smith"', 'fielded publisher query');
is($QParser->target_syntax('biblioserver', 'ti:"little engine that could"'),
'@attr 1=4 @attr 4=1 "little engine that could"', 'phrase query');
is($QParser->target_syntax('biblioserver', 'keyword|titlekw:smith'),
'@attr 1=4 @attr 2=102 @attr 9=20 @attr 4=6 "smith"',
'relevance-bumped query');
is($QParser->target_syntax('biblioserver', 'au:smith && johnson'),
'@and @attr 1=1003 @attr 4=6 "smith" @attr 1=1003 @attr 4=6 "johnson"',
'query with boolean &&');
is($QParser->target_syntax('biblioserver', 'au:smith && ti:johnson'),
'@and @attr 1=1003 @attr 4=6 "smith" @attr 1=4 @attr 4=6 "johnson"', 'query with boolean &&');
is($QParser->target_syntax('biblioserver', 'au:smith pubdate(-2008)'),
'@and @attr 1=1003 @attr 4=6 "smith" @attr 1=31 @attr 4=4 @attr 2=2 "2008"',
'keyword search with pubdate limited to -2008');
is($QParser->target_syntax('biblioserver', 'au:smith pubdate(2008-)'),
'@and @attr 1=1003 @attr 4=6 "smith" @attr 1=31 @attr 4=4 @attr 2=4 "2008"',
'keyword search with pubdate limited to 2008-');
is($QParser->target_syntax('biblioserver', 'au:smith pubdate(2008)'),
'@and @attr 1=1003 @attr 4=6 "smith" @attr 1=31 @attr 4=4 "2008"',
'keyword search with pubdate limited to 2008');
is($QParser->target_syntax('biblioserver', 'au:smith pubdate(1980,2008)'),
'@and @attr 1=1003 @attr 4=6 "smith" @or @attr 1=31 @attr 4=4 "1980" @attr 1=31 @attr 4=4 "2008"',
'keyword search with pubdate limited to 1980, 2008');
is($QParser->target_syntax('biblioserver', 'au:smith #acqdate_dsc'),
'@or @attr 1=32 @attr 7=1 0 @attr 1=1003 @attr 4=6 "smith"',
'keyword search sorted by acqdate descending');
is($QParser->bib1_mapping_by_attr('field', 'biblioserver', {'1' => '1004'})->{'field'},
'personal', 'retrieve field by attr');
is($QParser->bib1_mapping_by_attr_string('field', 'biblioserver', '@attr 1=1004')->{'field'},
'personal', 'retrieve field by attrstring');
is ($QParser->clear_all_mappings, $QParser, 'clear all mappings returns self');
is ($QParser->clear_all_configuration, $QParser, 'clear all configuration returns self');
is (scalar(keys(%{$QParser->search_fields})), 0, "All mapping erased");
$QParser->add_bib1_field_map('author' => 'personal' => 'biblioserver' => { '1' => '1004' } );
$QParser->add_bib1_modifier_map('relevance' => 'biblioserver' => { '2' => '102' } );
my $desired_config = {
'field_mappings' => {
'author' => {
'personal' => {
'aliases' => [ ],
'bib1_mapping' => {
'biblioserver' => {
'1' => '1004'
}
},
'enabled' => '1',
'index' => 'personal',
'label' => 'Personal'
}
}
},
'filter_mappings' => {},
'modifier_mappings' => {
'relevance' => {
'bib1_mapping' => {
'biblioserver' => {
'2' => '102'
}
},
'enabled' => 1,
'label' => 'Relevance'
}
},
'relevance_bumps' => {}
};
SKIP: {
my $got_config;
skip 'YAML is unavailable', 2 unless can_load('modules' => { 'YAML::Any' => undef });
$got_config = YAML::Any::Load($QParser->serialize_mappings());
ok(ref $got_config, 'serialized YAML valid');
is_deeply($got_config, $desired_config, 'Mappings serialized correctly to YAML');
skip 'JSON is unavailable', 2 unless can_load('modules' => { 'JSON' => undef });
undef $got_config;
eval {
$got_config = JSON::from_json($QParser->serialize_mappings('json'));
};
is($@, '', 'serialized JSON valid');
is_deeply($got_config, $desired_config, 'Mappings serialized correctly to JSON');
}
$QParser->clear_all_mappings;
is($QParser->TEST_SETUP, $QParser, 'TEST_SETUP returns self');
is($QParser->search_class_count, 4, 'Initialized 4 search classes in test setup');
done_testing();

View File

@ -1,70 +0,0 @@
#!/usr/bin/perl
# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Koha is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Koha; if not, see <http://www.gnu.org/licenses>.
use Modern::Perl;
use Test::More tests => 7;
use File::Basename;
use t::lib::Mocks;
use C4::Context;
t::lib::Mocks::mock_preference( "UseQueryParser", 1 );
my $QParser = C4::Context->queryparser();
# Check initialization correctly parsed the config file
ok( defined $QParser && ref($QParser) eq "Koha::QueryParser::Driver::PQF"
, 'C4::Context successfully created a QP object' );
is( $QParser->search_class_count, 4,
"Initialized 4 search classes" );
is( scalar(@{$QParser->search_fields()->{'keyword'}}), 111,
"Correct number of search fields for 'keyword' class");
is( scalar(@{$QParser->search_fields()->{'author'}}), 5,
"Correct number of search fields for 'author' class");
is( scalar(@{$QParser->search_fields()->{'subject'}}), 12,
"Correct number of search fields for 'subject' class");
is( scalar(@{$QParser->search_fields()->{'title'}}), 5,
"Correct number of search fields for 'title' class");
# Load C4::Context 4 times with different randomization seeds
$ENV{ PERL_PERTURB_KEYS } = "1";
my $hash_seed = "AB123";
my $default_search_class1 = get_default_search_class();
$hash_seed = "CD456";
my $default_search_class2 = get_default_search_class();
$hash_seed = "ABCDE";
my $default_search_class3 = get_default_search_class();
$hash_seed = "123456";
my $default_search_class4 = get_default_search_class();
ok( $default_search_class1 eq 'keyword' &&
$default_search_class2 eq 'keyword' &&
$default_search_class3 eq 'keyword' &&
$default_search_class4 eq 'keyword',
"C4::Context correctly sets the default search class to 'keyword' (Bug 12738)");
sub get_default_search_class {
# get the default search class from a forked proccess
# that just loads C4::Context
$ENV{ PERL_HASH_SEED } = $hash_seed;
my $running_dir = dirname(__FILE__);
my $default_search_class = qx/$running_dir\/default_search_class.pl/;
return $default_search_class;
}

View File

@ -22,6 +22,7 @@ use utf8;
use YAML;
use C4::Debug;
use C4::AuthoritiesMarc qw( SearchAuthorities );
use C4::XSLT;
require C4::Context;
@ -97,7 +98,6 @@ our $QueryStemming = 0;
our $QueryAutoTruncate = 0;
our $QueryWeightFields = 0;
our $QueryFuzzy = 0;
our $UseQueryParser = 0;
our $SearchEngine = 'Zebra';
our $marcflavour = 'MARC21';
our $htdocs = File::Spec->rel2abs(dirname($0));
@ -118,8 +118,6 @@ $contextmodule->mock('preference', sub {
return $QueryWeightFields;
} elsif ($pref eq 'QueryFuzzy') {
return $QueryFuzzy;
} elsif ($pref eq 'UseQueryParser') {
return $UseQueryParser;
} elsif ($pref eq 'SearchEngine') {
return $SearchEngine;
} elsif ($pref eq 'maxRecordsForFacets') {
@ -196,11 +194,6 @@ $contextmodule->mock('preference', sub {
return 0;
}
});
$contextmodule->mock('queryparser', sub {
my $QParser = Koha::QueryParser::Driver::PQF->new();
$QParser->load_config("$datadir/etc/searchengine/queryparser.yaml");
return $QParser;
});
our $bibliomodule = new Test::MockModule('C4::Biblio');
@ -269,7 +262,6 @@ sub run_marc21_search_tests {
$QueryAutoTruncate = 0;
$QueryWeightFields = 0;
$QueryFuzzy = 0;
$UseQueryParser = 0;
$marcflavour = 'MARC21';
my $indexes = C4::Search::getIndexes();
@ -485,19 +477,6 @@ ok(MARC::Record::new_from_xml($results_hashref->{biblioserver}->{RECORDS}->[0],'
is($results_hashref->{biblioserver}->{hits}, 12,
'search using index whose name contains "ns" returns expected results (bug 10271)');
$UseQueryParser = 1;
( $error, $query, $simple_query, $query_cgi,
$query_desc, $limit, $limit_cgi, $limit_desc,
$query_type ) = buildQuery([], [ 'book' ], [ 'kw' ], [], [], 0, 'en');
($error, $results_hashref, $facets_loop) = getRecords($query,$simple_query,[ ], [ 'biblioserver' ],20,0,\%branches,\%itemtypes,$query_type,0);
is($results_hashref->{biblioserver}->{hits}, 101, "Search for 'book' with index set to 'kw' returns 101 hits");
( $error, $query, $simple_query, $query_cgi,
$query_desc, $limit, $limit_cgi, $limit_desc,
$query_type ) = buildQuery([ 'and' ], [ 'book', 'another' ], [ 'kw', 'kw' ], [], [], 0, 'en');
($error, $results_hashref, $facets_loop) = getRecords($query,$simple_query,[ ], [ 'biblioserver' ],20,0,\%branches,\%itemtypes,$query_type,0);
is($results_hashref->{biblioserver}->{hits}, 1, "Search for 'kw:book && kw:another' returns 1 hit");
$UseQueryParser = 0;
( $error, $query, $simple_query, $query_cgi,
$query_desc, $limit, $limit_cgi, $limit_desc,
$query_type ) = buildQuery([], [ '' ], [ 'kw' ], [ 'available' ], [], 0, 'en');
@ -700,66 +679,6 @@ ok(MARC::Record::new_from_xml($results_hashref->{biblioserver}->{RECORDS}->[0],'
return '', [ $record->as_usmarc() ], 1;
});
$UseQueryParser = 1;
$term = 'Arizona';
( $error, $query, $simple_query, $query_cgi,
$query_desc, $limit, $limit_cgi, $limit_desc,
$query_type ) = buildQuery([], [ $term ], [ 'su-br' ], [ ], [], 0, 'en');
matchesExplodedTerms("Advanced search for broader subjects", $query, 'Arizona', 'United States');
( $error, $query, $simple_query, $query_cgi,
$query_desc, $limit, $limit_cgi, $limit_desc,
$query_type ) = buildQuery([], [ $term ], [ 'su-na' ], [ ], [], 0, 'en');
matchesExplodedTerms("Advanced search for narrower subjects", $query, 'Arizona', 'Maricopa County', 'Navajo County', 'Pima County');
( $error, $query, $simple_query, $query_cgi,
$query_desc, $limit, $limit_cgi, $limit_desc,
$query_type ) = buildQuery([], [ $term ], [ 'su-rl' ], [ ], [], 0, 'en');
matchesExplodedTerms("Advanced search for related subjects", $query, 'Arizona', 'United States', 'Maricopa County', 'Navajo County', 'Pima County');
( $error, $query, $simple_query, $query_cgi,
$query_desc, $limit, $limit_cgi, $limit_desc,
$query_type ) = buildQuery([], [ "$term", 'history' ], [ 'su-rl', 'kw' ], [ ], [], 0, 'en');
matchesExplodedTerms("Advanced search for related subjects and keyword 'history' searches related subjects", $query, 'Arizona', 'United States', 'Maricopa County', 'Navajo County', 'Pima County');
like($query, qr/history/, "Advanced search for related subjects and keyword 'history' searches for 'history'");
( $error, $query, $simple_query, $query_cgi,
$query_desc, $limit, $limit_cgi, $limit_desc,
$query_type ) = buildQuery([], [ 'history', "$term" ], [ 'kw', 'su-rl' ], [ ], [], 0, 'en');
matchesExplodedTerms("Order of terms doesn't matter for advanced search", $query, 'Arizona', 'United States', 'Maricopa County', 'Navajo County', 'Pima County');
like($query, qr/history/, "Order of terms doesn't matter for advanced search");
( $error, $query, $simple_query, $query_cgi,
$query_desc, $limit, $limit_cgi, $limit_desc,
$query_type ) = buildQuery([], [ "su-br($term)" ], [ ], [ ], [], 0, 'en');
matchesExplodedTerms("Simple search for broader subjects", $query, 'Arizona', 'United States');
( $error, $query, $simple_query, $query_cgi,
$query_desc, $limit, $limit_cgi, $limit_desc,
$query_type ) = buildQuery([], [ "su-na($term)" ], [ ], [ ], [], 0, 'en');
matchesExplodedTerms("Simple search for narrower subjects", $query, 'Arizona', 'Maricopa County', 'Navajo County', 'Pima County');
( $error, $query, $simple_query, $query_cgi,
$query_desc, $limit, $limit_cgi, $limit_desc,
$query_type ) = buildQuery([], [ "su-rl($term)" ], [ ], [ ], [], 0, 'en');
matchesExplodedTerms("Simple search for related subjects", $query, 'Arizona', 'United States', 'Maricopa County', 'Navajo County', 'Pima County');
( $error, $query, $simple_query, $query_cgi,
$query_desc, $limit, $limit_cgi, $limit_desc,
$query_type ) = buildQuery([], [ "history && su-rl($term)" ], [ ], [ ], [], 0, 'en');
matchesExplodedTerms("Simple search for related subjects and keyword 'history' searches related subjects", $query, 'Arizona', 'United States', 'Maricopa County', 'Navajo County', 'Pima County');
like($query, qr/history/, "Simple search for related subjects and keyword 'history' searches for 'history'");
sub matchesExplodedTerms {
my ($message, $query, @terms) = @_;
my $match = '(' . join ('|', map { " \@attr 1=Subject \@attr 4=1 \"$_\"" } @terms) . "){" . scalar(@terms) . "}";
like($query, qr/$match/, $message);
}
# authority records
use_ok('C4::AuthoritiesMarc');
$UseQueryParser = 0;
my ($auths, $count) = SearchAuthorities(
['mainentry'], ['and'], [''], ['starts'],
['shakespeare'], 0, 10, '', '', 1
@ -791,29 +710,6 @@ ok(MARC::Record::new_from_xml($results_hashref->{biblioserver}->{RECORDS}->[0],'
);
is($count, 1, 'MARC21 authorities: one hit on "all" (entire record) contains "professional wrestler"');
$UseQueryParser = 1;
($auths, $count) = SearchAuthorities(
['mainentry'], ['and'], [''], ['starts'],
['shakespeare'], 0, 10, '', '', 1
);
is($count, 1, 'MARC21 authorities: one hit on mainentry starts with "shakespeare" (QP)');
($auths, $count) = SearchAuthorities(
['mainentry'], ['and'], [''], ['starts'],
['shakespeare'], 0, 10, '', 'HeadingAsc', 1
);
is($count, 1, 'MARC21 authorities: one hit on mainentry starts with "shakespeare" sorted by heading ascending (QP)');
($auths, $count) = SearchAuthorities(
['mainentry'], ['and'], [''], ['starts'],
['shakespeare'], 0, 10, '', 'HeadingDsc', 1
);
is($count, 1, 'MARC21 authorities: one hit on mainentry starts with "shakespeare" sorted by heading descending (QP)');
($auths, $count) = SearchAuthorities(
['match'], ['and'], [''], ['contains'],
['沙士北亞威廉姆'], 0, 10, '', '', 1
);
is($count, 1, 'MARC21 authorities: one hit on match contains "沙士北亞威廉姆" (QP)');
# retrieve records that are larger than the MARC limit of 99,999 octets
( undef, $results_hashref, $facets_loop ) =
getRecords('ti:marc the large record', '', [], [ 'biblioserver' ], '20', 0, \%branches, \%itemtypes, 'ccl', undef);
@ -899,7 +795,6 @@ sub run_unimarc_search_tests {
$QueryAutoTruncate = 0;
$QueryWeightFields = 0;
$QueryFuzzy = 0;
$UseQueryParser = 0;
$marcflavour = 'UNIMARC';
index_sample_records_and_launch_zebra($datadir, 'unimarc');
@ -917,7 +812,6 @@ sub run_unimarc_search_tests {
# authority records
use_ok('C4::AuthoritiesMarc');
$UseQueryParser = 0;
my ($auths, $count) = SearchAuthorities(
['mainentry'], ['and'], [''], ['contains'],
@ -971,7 +865,7 @@ sub run_unimarc_search_tests {
}
subtest 'MARC21 + DOM' => sub {
plan tests => 112;
plan tests => 84;
run_marc21_search_tests();
};

View File

@ -566,7 +566,6 @@ sub mocking_systempreferences_to_a_set_value {
TraceCompleteSubfields
TraceSubjectSubdivisions
UseICU
UseQueryParser
defaultSortField
displayFacetCount
OPACdefaultSortField

View File

@ -1,37 +0,0 @@
#!/usr/bin/perl
# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Koha is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Koha; if not, see <http://www.gnu.org/licenses>.
use Modern::Perl;
=head1 default_search_class.pl
The only purpose of this script is to load C4::Context and print
the default search class from the QueryParser object
=cut
use t::lib::Mocks;
use C4::Context;
t::lib::Mocks::mock_preference("UseQueryParser","1");
my $QParser = C4::Context->queryparser();
my $default_search_class = $QParser->default_search_class();
print $default_search_class;
exit 0;

View File

@ -49,7 +49,6 @@ $ENV{'__DB_USER__'} = C4::Context->config('user') // 'kohaadmin';
$ENV{'__DB_PASS__'} = C4::Context->config('pass') // 'katikoan';
my @files = ( "$source/etc/koha-conf.xml",
"$source/etc/searchengine/queryparser.yaml",
);
find(sub { push @files, $File::Find::name if ( -f $File::Find::name ); }, "$source/etc/zebradb");