Bugzilla – Attachment 16181 Details for
Bug 9239
Koha should share Evergreen's QueryParser module for parsing queries
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 9239: Introduce QueryParser driver for PQF
Bug-9239-Introduce-QueryParser-driver-for-PQF.patch (text/plain), 87.59 KB, created by
Jared Camins-Esakov
on 2013-03-17 01:26:58 UTC
(
hide
)
Description:
Bug 9239: Introduce QueryParser driver for PQF
Filename:
MIME Type:
Creator:
Jared Camins-Esakov
Created:
2013-03-17 01:26:58 UTC
Size:
87.59 KB
patch
obsolete
>From 9e66b5fbc21a5408467f0a9b6f607f419216b1ee Mon Sep 17 00:00:00 2001 >From: Jared Camins-Esakov <jcamins@cpbibliography.com> >Date: Tue, 2 Oct 2012 17:06:47 -0400 >Subject: [PATCH] Bug 9239: Introduce QueryParser driver for PQF > >Since the most expressive query language supported by Zebra is PQF, this >patch adds a PQF driver for QueryParser which will translate QueryParser >queries into standard PQF (guided by mappings which have been written to >match Koha's existing Zebra configuration) which can then be sent to >Zebra. This driver, Koha::QueryParser::Driver::PQF(::*) extends the >OpenILS::QueryParser(::*) class(es), so as to preserve maximum >interoperability between the various users of the QueryParser driver. > >Initially, search syntax is as follows: >* AND operator: && >* OR operator: || >* GROUPING operators: ( ) > >Fields can mostly be searched using the ccl prefixes they have now. The >exception is the various date limits which are searched with a syntax >like this: pubdate(2008) > >For sorting, you can simply add #title-sort-az (etc.) to your query. > >Signed-off-by: Chris Cormack <chris@bigballofwax.co.nz> >Signed-off-by: Elliott Davis <elliott@bywatersolions.com> >Test Passed successfully after installing missing dep for Test::Deep > >Signed-off-by: Katrin Fischer <Katrin.Fischer.83@web.de> >Signed-off-by: Jared Camins-Esakov <jcamins@cpbibliography.com> >--- > Koha/QueryParser/Driver/PQF.pm | 913 ++++++++++++ > Koha/QueryParser/Driver/PQF/Util.pm | 22 + > Koha/QueryParser/Driver/PQF/query_plan.pm | 46 + > Koha/QueryParser/Driver/PQF/query_plan/facet.pm | 22 + > Koha/QueryParser/Driver/PQF/query_plan/filter.pm | 27 + > Koha/QueryParser/Driver/PQF/query_plan/modifier.pm | 27 + > Koha/QueryParser/Driver/PQF/query_plan/node.pm | 76 + > .../QueryParser/Driver/PQF/query_plan/node/atom.pm | 22 + > etc/searchengine/queryparser.yaml | 1487 ++++++++++++++++++++ > t/QueryParser.t | 95 ++ > 10 files changed, 2737 insertions(+) > create mode 100644 Koha/QueryParser/Driver/PQF.pm > create mode 100644 Koha/QueryParser/Driver/PQF/Util.pm > create mode 100644 Koha/QueryParser/Driver/PQF/query_plan.pm > create mode 100644 Koha/QueryParser/Driver/PQF/query_plan/facet.pm > create mode 100644 Koha/QueryParser/Driver/PQF/query_plan/filter.pm > create mode 100644 Koha/QueryParser/Driver/PQF/query_plan/modifier.pm > create mode 100644 Koha/QueryParser/Driver/PQF/query_plan/node.pm > create mode 100644 Koha/QueryParser/Driver/PQF/query_plan/node/atom.pm > create mode 100644 etc/searchengine/queryparser.yaml > create mode 100644 t/QueryParser.t > >diff --git a/Koha/QueryParser/Driver/PQF.pm b/Koha/QueryParser/Driver/PQF.pm >new file mode 100644 >index 0000000..3007333 >--- /dev/null >+++ b/Koha/QueryParser/Driver/PQF.pm >@@ -0,0 +1,913 @@ >+package Koha::QueryParser::Driver::PQF; >+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 ); >+ $self->add_search_field_alias( $class => $field => $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 ); >+ } >+ $self->add_search_field_alias( $class => $field => >+ $field_mappings->{$class}->{$field}->{'index'} ); >+ foreach my $alias ( >+ @{ $field_mappings->{$class}->{$field}->{'aliases'} } ) >+ { >+ next >+ if ( $alias eq >+ $field_mappings->{$class}->{$field}->{'index'} ); >+ $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' => '9013 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; >diff --git a/Koha/QueryParser/Driver/PQF/Util.pm b/Koha/QueryParser/Driver/PQF/Util.pm >new file mode 100644 >index 0000000..f2e018b >--- /dev/null >+++ b/Koha/QueryParser/Driver/PQF/Util.pm >@@ -0,0 +1,22 @@ >+package Koha::QueryParser::Driver::PQF::Util; >+use Scalar::Util qw(looks_like_number); >+ >+use strict; >+use warnings; >+ >+sub attributes_to_attr_string { >+ my ($attributes) = @_; >+ my $attr_string = ''; >+ my $key; >+ my $value; >+ while (($key, $value) = each(%$attributes)) { >+ next unless looks_like_number($key); >+ $attr_string .= ' @attr ' . $key . '=' . $value . ' '; >+ } >+ $attr_string =~ s/^\s*//; >+ $attr_string =~ s/\s*$//; >+ $attr_string .= ' ' . $attributes->{''} if defined $attributes->{''}; >+ return $attr_string; >+} >+ >+1; >diff --git a/Koha/QueryParser/Driver/PQF/query_plan.pm b/Koha/QueryParser/Driver/PQF/query_plan.pm >new file mode 100644 >index 0000000..5435fe6 >--- /dev/null >+++ b/Koha/QueryParser/Driver/PQF/query_plan.pm >@@ -0,0 +1,46 @@ >+package Koha::QueryParser::Driver::PQF::query_plan; >+use base 'OpenILS::QueryParser::query_plan'; >+ >+use strict; >+use warnings; >+ >+=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; >+ $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; >+ 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; >diff --git a/Koha/QueryParser/Driver/PQF/query_plan/facet.pm b/Koha/QueryParser/Driver/PQF/query_plan/facet.pm >new file mode 100644 >index 0000000..0407e58 >--- /dev/null >+++ b/Koha/QueryParser/Driver/PQF/query_plan/facet.pm >@@ -0,0 +1,22 @@ >+package Koha::QueryParser::Driver::PQF::query_plan::facet; >+use base 'OpenILS::QueryParser::query_plan::facet'; >+ >+use strict; >+use warnings; >+ >+=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; >diff --git a/Koha/QueryParser/Driver/PQF/query_plan/filter.pm b/Koha/QueryParser/Driver/PQF/query_plan/filter.pm >new file mode 100644 >index 0000000..c632eee >--- /dev/null >+++ b/Koha/QueryParser/Driver/PQF/query_plan/filter.pm >@@ -0,0 +1,27 @@ >+package Koha::QueryParser::Driver::PQF::query_plan::filter; >+use base 'OpenILS::QueryParser::query_plan::filter'; >+ >+use strict; >+use warnings; >+ >+=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; >diff --git a/Koha/QueryParser/Driver/PQF/query_plan/modifier.pm b/Koha/QueryParser/Driver/PQF/query_plan/modifier.pm >new file mode 100644 >index 0000000..c3a66e4 >--- /dev/null >+++ b/Koha/QueryParser/Driver/PQF/query_plan/modifier.pm >@@ -0,0 +1,27 @@ >+package Koha::QueryParser::Driver::PQF::query_plan::modifier; >+use base 'OpenILS::QueryParser::query_plan::modifier'; >+ >+use strict; >+use warnings; >+ >+=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 @fields; >+ >+ 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; >diff --git a/Koha/QueryParser/Driver/PQF/query_plan/node.pm b/Koha/QueryParser/Driver/PQF/query_plan/node.pm >new file mode 100644 >index 0000000..62417a1 >--- /dev/null >+++ b/Koha/QueryParser/Driver/PQF/query_plan/node.pm >@@ -0,0 +1,76 @@ >+package Koha::QueryParser::Driver::PQF::query_plan::node; >+use base 'OpenILS::QueryParser::query_plan::node'; >+ >+use strict; >+use warnings; >+ >+=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) { >+ $fieldobj->{'attr_string'} .= ' ' . $relbump->{'attr_string'}; >+ } >+ push @fields, $fieldobj unless ($field eq $self->classname && scalar @fields); >+ } >+ } 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) { >+ $pqf .= ' @or ' x (scalar(@fields) - 1); >+ foreach my $attributes (@fields) { >+ $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) { >+ $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; >+ return ($self->negate ? '@not @attr 1=_ALLRECORDS @attr 2=103 "" ' : '') . $pqf; >+} >+ >+1; >diff --git a/Koha/QueryParser/Driver/PQF/query_plan/node/atom.pm b/Koha/QueryParser/Driver/PQF/query_plan/node/atom.pm >new file mode 100644 >index 0000000..afdb4c4 >--- /dev/null >+++ b/Koha/QueryParser/Driver/PQF/query_plan/node/atom.pm >@@ -0,0 +1,22 @@ >+package Koha::QueryParser::Driver::PQF::query_plan::node::atom; >+use base 'OpenILS::QueryParser::query_plan::node::atom'; >+ >+use strict; >+use warnings; >+ >+=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) = @_; >+ >+ return ' "' . $self->content . '" '; >+} >+ >+1; >diff --git a/etc/searchengine/queryparser.yaml b/etc/searchengine/queryparser.yaml >new file mode 100644 >index 0000000..94f9d8e >--- /dev/null >+++ b/etc/searchengine/queryparser.yaml >@@ -0,0 +1,1487 @@ >+--- >+field_mappings: >+ author: >+ 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 >+ corporate: >+ aliases: >+ - corporate >+ - cpn >+ bib1_mapping: >+ biblioserver: >+ 1: 1005 >+ enabled: 1 >+ index: corporate >+ label: Corporate >+ exactauthor: >+ aliases: >+ - exactauthor >+ - au,ext >+ bib1_mapping: >+ biblioserver: >+ 1: 1003 >+ 4: 1 >+ 6: 3 >+ enabled: 1 >+ index: exactauthor >+ label: Exactauthor >+ personal: >+ aliases: >+ - personal >+ bib1_mapping: >+ biblioserver: >+ 1: 1004 >+ enabled: 1 >+ index: personal >+ label: Personal >+ keyword: >+ keyword: >+ aliases: >+ - any >+ - kw >+ bib1_mapping: >+ authorityserver: >+ 1: Any >+ biblioserver: >+ 1: 1016 >+ enabled: 1 >+ index: 'keyword' >+ label: 'Keyword' >+ abstract: >+ aliases: >+ - abstract >+ - ab >+ bib1_mapping: >+ biblioserver: >+ 1: 62 >+ enabled: 1 >+ index: abstract >+ label: Abstract >+ acqsource: >+ aliases: >+ - acqsource >+ bib1_mapping: >+ biblioserver: >+ 1: 8015 >+ enabled: 1 >+ index: acqsource >+ label: Acqsource >+ alwaysmatch: >+ aliases: >+ - alwaysmatch >+ - all >+ bib1_mapping: >+ authorityserver: >+ 1: _ALLRECORDS >+ 2: 103 >+ biblioserver: >+ 1: _ALLRECORDS >+ 2: 103 >+ enabled: 1 >+ index: alwaysmatch >+ label: Alwaysmatch >+ arl: >+ aliases: >+ - arl >+ bib1_mapping: >+ biblioserver: >+ 1: 9904 r=r >+ enabled: 1 >+ index: arl >+ label: Arl >+ arp: >+ aliases: >+ - arp >+ bib1_mapping: >+ biblioserver: >+ 1: 9013 r=r >+ enabled: 1 >+ index: arp >+ label: Arp >+ audience: >+ aliases: >+ - audience >+ - aud >+ bib1_mapping: >+ biblioserver: >+ 1: 8822 >+ enabled: 1 >+ index: audience >+ label: Audience >+ authtype: >+ aliases: >+ - authtype >+ - at >+ bib1_mapping: >+ authorityserver: >+ 1: authtype >+ 5: 100 >+ enabled: 1 >+ index: authtype >+ label: Authtype >+ authorext: >+ alias: [] >+ bib1_mapping: >+ biblioserver: >+ 1: 1003 >+ 4: 1 >+ 6: 2 >+ enabled: 1 >+ index: author >+ label: Authorkw >+ authorkw: >+ alias: [] >+ bib1_mapping: >+ biblioserver: >+ 1: 1003 >+ enabled: 1 >+ index: author >+ label: Authorkw >+ barcode: >+ aliases: >+ - barcode >+ - bc >+ bib1_mapping: >+ biblioserver: >+ 1: 8023 >+ enabled: 1 >+ index: barcode >+ label: Barcode >+ bib-level: >+ bib1_mapping: >+ biblioserver: >+ 1: 1021 >+ enabled: 1 >+ index: bib-level >+ aliases: >+ - bib-level >+ label: Bib-level >+ biblionumber: >+ bib1_mapping: >+ biblioserver: >+ 1: 9002 >+ 5: 100 >+ enabled: 1 >+ index: biblionumber >+ aliases: >+ - biblionumber >+ label: Biblionumber >+ biography: >+ bib1_mapping: >+ biblioserver: >+ 1: 8834 >+ enabled: 1 >+ index: biography >+ aliases: >+ - biography >+ - bio >+ label: Biography >+ biography-code: >+ bib1_mapping: >+ biblioserver: >+ 1: Biography-code >+ enabled: 1 >+ index: biography-code >+ aliases: >+ - biography-code >+ label: Biography-code >+ ccode: >+ bib1_mapping: >+ biblioserver: >+ 1: 8009 >+ enabled: 1 >+ index: ccode >+ aliases: >+ - ccode >+ - mc-ccode >+ label: Ccode >+ classification-source: >+ bib1_mapping: >+ biblioserver: >+ 1: 8003 >+ enabled: 1 >+ index: classification-source >+ aliases: >+ - classification-source >+ label: Classification-source >+ cn-bib-sort: >+ bib1_mapping: >+ biblioserver: >+ 1: 9005 >+ enabled: 1 >+ index: cn-bib-sort >+ aliases: >+ - cn-bib-sort >+ label: Cn-bib-sort >+ cn-bib-source: >+ bib1_mapping: >+ biblioserver: >+ 1: 9004 >+ enabled: 1 >+ index: cn-bib-source >+ aliases: >+ - cn-bib-source >+ label: Cn-bib-source >+ cn-class: >+ bib1_mapping: >+ biblioserver: >+ 1: 9007 >+ enabled: 1 >+ index: cn-class >+ aliases: >+ - cn-class >+ label: Cn-class >+ cn-item: >+ bib1_mapping: >+ biblioserver: >+ 1: 9008 >+ enabled: 1 >+ index: cn-item >+ aliases: >+ - cn-item >+ label: Cn-item >+ cn-prefix: >+ bib1_mapping: >+ biblioserver: >+ 1: 9009 >+ enabled: 1 >+ index: cn-prefix >+ aliases: >+ - cn-prefix >+ label: Cn-prefix >+ cn-sort: >+ bib1_mapping: >+ biblioserver: >+ 1: 8007 >+ enabled: 1 >+ index: cn-sort >+ aliases: >+ - cn-sort >+ label: Cn-sort >+ cn-suffix: >+ bib1_mapping: >+ biblioserver: >+ 1: 9010 >+ enabled: 1 >+ index: cn-suffix >+ aliases: >+ - cn-suffix >+ label: Cn-suffix >+ code-institution: >+ bib1_mapping: >+ biblioserver: >+ 1: 56 >+ enabled: 1 >+ index: code-institution >+ aliases: >+ - code-institution >+ label: Code-institution >+ coded-location-qualifier: >+ bib1_mapping: >+ biblioserver: >+ 1: 8016 >+ enabled: 1 >+ index: coded-location-qualifier >+ aliases: >+ - coded-location-qualifier >+ label: Coded-location-qualifier >+ content-type: >+ bib1_mapping: >+ biblioserver: >+ 1: 1034 >+ enabled: 1 >+ index: content-type >+ aliases: >+ - content-type >+ - ctype >+ label: Content-type >+ control-number: >+ bib1_mapping: >+ biblioserver: >+ 1: 9001 >+ enabled: 1 >+ index: control-number >+ aliases: >+ - control-number >+ label: Control-number >+ copynumber: >+ bib1_mapping: >+ biblioserver: >+ 1: 8027 >+ enabled: 1 >+ index: copynumber >+ aliases: >+ - copynumber >+ label: Copynumber >+ curriculum: >+ bib1_mapping: >+ biblioserver: >+ 1: 9658 >+ enabled: 1 >+ index: curriculum >+ aliases: >+ - curriculum >+ label: Curriculum >+ damaged: >+ bib1_mapping: >+ biblioserver: >+ 1: 8005 >+ enabled: 1 >+ index: damaged >+ aliases: >+ - damaged >+ label: Damaged >+ date-entered-on-file: >+ bib1_mapping: >+ biblioserver: >+ 1: date-entered-on-file >+ enabled: 1 >+ index: date-entered-on-file >+ aliases: >+ - date-entered-on-file >+ label: Date-entered-on-file >+ datelastborrowed: >+ bib1_mapping: >+ biblioserver: >+ 1: 8026 >+ enabled: 1 >+ index: datelastborrowed >+ aliases: >+ - datelastborrowed >+ label: Datelastborrowed >+ datelastseen: >+ bib1_mapping: >+ biblioserver: >+ 1: 8025 >+ enabled: 1 >+ index: datelastseen >+ aliases: >+ - datelastseen >+ label: Datelastseen >+ dt-bks: >+ bib1_mapping: >+ biblioserver: >+ 1: 8700 >+ enabled: 1 >+ index: dt-bks >+ aliases: >+ - dt-bks >+ label: Dt-bks >+ dt-cf: >+ bib1_mapping: >+ biblioserver: >+ 1: 8700 >+ enabled: 1 >+ index: dt-cf >+ aliases: >+ - dt-cf >+ label: Dt-cf >+ dt-map: >+ bib1_mapping: >+ biblioserver: >+ 1: 8700 >+ enabled: 1 >+ index: dt-map >+ aliases: >+ - dt-map >+ label: Dt-map >+ dt-sr: >+ bib1_mapping: >+ biblioserver: >+ 1: 8700 >+ enabled: 1 >+ index: dt-sr >+ aliases: >+ - dt-sr >+ label: Dt-sr >+ dt-vis: >+ bib1_mapping: >+ biblioserver: >+ 1: 8700 >+ enabled: 1 >+ index: dt-vis >+ aliases: >+ - dt-vis >+ label: Dt-vis >+ ean: >+ bib1_mapping: >+ biblioserver: >+ 1: EAN >+ enabled: 1 >+ index: ean >+ aliases: >+ - ean >+ label: Ean >+ extent: >+ bib1_mapping: >+ biblioserver: >+ 1: Extent >+ enabled: 1 >+ index: extent >+ aliases: >+ - extent >+ label: Extent >+ ff8-22: >+ bib1_mapping: >+ biblioserver: >+ 1: 8822 >+ enabled: 1 >+ index: ff8-22 >+ aliases: >+ - ff8-22 >+ label: Ff8-22 >+ ff8-23: >+ bib1_mapping: >+ biblioserver: >+ 1: 8823 >+ enabled: 1 >+ index: ff8-23 >+ aliases: >+ - ff8-23 >+ label: Ff8-23 >+ ff8-34: >+ bib1_mapping: >+ biblioserver: >+ 1: 8834 >+ enabled: 1 >+ index: ff8-34 >+ aliases: >+ - ff8-34 >+ label: Ff8-34 >+ fiction: >+ bib1_mapping: >+ biblioserver: >+ 1: 8833 >+ enabled: 1 >+ index: fiction >+ aliases: >+ - fiction >+ - fic >+ label: Fiction >+ format: >+ bib1_mapping: >+ biblioserver: >+ 1: 8823 >+ enabled: 1 >+ index: format >+ aliases: >+ - format >+ label: Format >+ graphics-support: >+ bib1_mapping: >+ biblioserver: >+ 1: Graphic-support >+ enabled: 1 >+ index: graphics-support >+ aliases: >+ - graphics-support >+ label: Graphics-support >+ graphics-type: >+ bib1_mapping: >+ biblioserver: >+ 1: Graphic-type >+ enabled: 1 >+ index: graphics-type >+ aliases: >+ - graphics-type >+ label: Graphics-type >+ holdingbranch: >+ bib1_mapping: >+ biblioserver: >+ 1: 8012 >+ enabled: 1 >+ index: holdingbranch >+ aliases: >+ - holdingbranch >+ label: Holdingbranch >+ homebranch: >+ bib1_mapping: >+ biblioserver: >+ 1: homebranch >+ enabled: 1 >+ index: homebranch >+ aliases: >+ - homebranch >+ - branch >+ label: Homebranch >+ host-item: >+ bib1_mapping: >+ biblioserver: >+ 1: 1033 >+ enabled: 1 >+ index: host-item >+ aliases: >+ - host-item >+ label: Host-item >+ host-item-number: >+ bib1_mapping: >+ biblioserver: >+ 1: 8911 >+ enabled: 1 >+ index: host-item-number >+ aliases: >+ - host-item-number >+ - hi >+ label: Host-item-number >+ id-other: >+ bib1_mapping: >+ biblioserver: >+ 1: 9012 >+ enabled: 1 >+ index: id-other >+ aliases: >+ - id-other >+ label: Id-other >+ identifier-standard: >+ bib1_mapping: >+ biblioserver: >+ 1: 1007 >+ enabled: 1 >+ index: identifier-standard >+ aliases: >+ - identifier-standard >+ - ident >+ label: Identifier-standard >+ illustration-code: >+ bib1_mapping: >+ biblioserver: >+ 1: "Illustration-code " >+ enabled: 1 >+ index: illustration-code >+ aliases: >+ - illustration-code >+ label: Illustration-code >+ isbn: >+ bib1_mapping: >+ biblioserver: >+ 1: 7 >+ enabled: 1 >+ index: isbn >+ aliases: >+ - isbn >+ - nb >+ label: Isbn >+ issn: >+ bib1_mapping: >+ biblioserver: >+ 1: 8 >+ enabled: 1 >+ index: issn >+ aliases: >+ - issn >+ - ns >+ label: Issn >+ issues: >+ bib1_mapping: >+ biblioserver: >+ 1: 8019 >+ enabled: 1 >+ index: issues >+ aliases: >+ - issues >+ label: Issues >+ item: >+ bib1_mapping: >+ biblioserver: >+ 1: 9520 >+ enabled: 1 >+ index: item >+ aliases: >+ - item >+ label: Item >+ itemnumber: >+ bib1_mapping: >+ biblioserver: >+ 1: 8010 >+ enabled: 1 >+ index: itemnumber >+ aliases: >+ - itemnumber >+ label: Itemnumber >+ itemtype: >+ bib1_mapping: >+ biblioserver: >+ 1: 9006 >+ enabled: 1 >+ index: itemtype >+ aliases: >+ - itemtype >+ - mc-itemtype >+ label: Itemtype >+ itype: >+ bib1_mapping: >+ biblioserver: >+ 1: 8031 >+ enabled: 1 >+ index: itype >+ aliases: >+ - itype >+ - mc-itype >+ label: Itype >+ l-format: >+ bib1_mapping: >+ biblioserver: >+ 1: 8703 >+ enabled: 1 >+ index: l-format >+ aliases: >+ - l-format >+ label: L-format >+ language: >+ bib1_mapping: >+ biblioserver: >+ 1: 54 >+ enabled: 1 >+ index: language >+ aliases: >+ - language >+ - ln >+ label: Language >+ lc-card-number: >+ bib1_mapping: >+ biblioserver: >+ 1: 9 >+ enabled: 1 >+ index: lc-card-number >+ aliases: >+ - lc-card-number >+ - lc-card >+ label: Lc-card-number >+ lex: >+ bib1_mapping: >+ biblioserver: >+ 1: 9903 r=r >+ enabled: 1 >+ index: lex >+ aliases: >+ - lex >+ label: Lex >+ literature-code: >+ bib1_mapping: >+ biblioserver: >+ 1: Literature-Code >+ enabled: 1 >+ index: literature-code >+ aliases: >+ - literature-code >+ label: Literature-code >+ llength: >+ bib1_mapping: >+ biblioserver: >+ 1: llength >+ enabled: 1 >+ index: llength >+ aliases: >+ - llength >+ label: Llength >+ local-classification: >+ bib1_mapping: >+ biblioserver: >+ 1: 8022 >+ enabled: 1 >+ index: local-classification >+ aliases: >+ - local-classification >+ - lcn >+ - callnum >+ label: Local-classification >+ local-number: >+ bib1_mapping: >+ biblioserver: >+ 1: 12 >+ enabled: 1 >+ index: local-number >+ aliases: >+ - local-number >+ - sn >+ label: Local-number >+ location: >+ bib1_mapping: >+ biblioserver: >+ 1: 8013 >+ enabled: 1 >+ index: location >+ aliases: >+ - location >+ - mc-loc >+ label: Location >+ lost: >+ bib1_mapping: >+ biblioserver: >+ 1: 8002 >+ enabled: 1 >+ index: lost >+ aliases: >+ - lost >+ label: Lost >+ match: >+ bib1_mapping: >+ authorityserver: >+ 1: Match >+ enabled: 1 >+ index: match >+ aliases: >+ - match >+ label: Match >+ material-type: >+ bib1_mapping: >+ biblioserver: >+ 1: Material-type >+ enabled: 1 >+ index: material-type >+ aliases: >+ - material-type >+ label: Material-type >+ materials-specified: >+ bib1_mapping: >+ biblioserver: >+ 1: 8004 >+ enabled: 1 >+ index: materials-specified >+ aliases: >+ - materials-specified >+ label: Materials-specified >+ music: >+ bib1_mapping: >+ biblioserver: >+ 1: Music-number >+ enabled: 1 >+ index: music >+ aliases: >+ - music >+ label: Music >+ name: >+ bib1_mapping: >+ biblioserver: >+ 1: 1002 >+ enabled: 1 >+ index: name >+ aliases: >+ - name >+ label: Name >+ note: >+ bib1_mapping: >+ biblioserver: >+ 1: 63 >+ enabled: 1 >+ index: note >+ aliases: >+ - note >+ - nt >+ label: Note >+ notforloan: >+ bib1_mapping: >+ biblioserver: >+ 1: 8008 >+ 4: 109 >+ enabled: 1 >+ index: notforloan >+ aliases: >+ - notforloan >+ label: Notforloan >+ onloan: >+ bib1_mapping: >+ biblioserver: >+ 1: 8024 >+ enabled: 1 >+ index: onloan >+ aliases: >+ - onloan >+ label: Onloan >+ personal-name: >+ bib1_mapping: >+ biblioserver: >+ 1: Personal-name >+ enabled: 1 >+ index: personal-name >+ aliases: >+ - personal-name >+ - pn >+ label: Personal-name >+ place-publication: >+ bib1_mapping: >+ biblioserver: >+ 1: 59 >+ enabled: 1 >+ index: place-publication >+ aliases: >+ - place-publication >+ - pl >+ label: Place-publication >+ popularity: >+ bib1_mapping: >+ biblioserver: >+ 1: issues >+ enabled: 1 >+ index: popularity >+ aliases: >+ - popularity >+ label: Popularity >+ price: >+ bib1_mapping: >+ biblioserver: >+ 1: 8017 >+ enabled: 1 >+ index: price >+ aliases: >+ - price >+ label: Price >+ publisher: >+ bib1_mapping: >+ biblioserver: >+ 1: 1018 >+ enabled: 1 >+ index: publisher >+ aliases: >+ - publisher >+ - pb >+ label: Publisher >+ record-control-number: >+ bib1_mapping: >+ biblioserver: >+ 1: 1045 >+ enabled: 1 >+ index: record-control-number >+ aliases: >+ - record-control-number >+ - rcn >+ label: Record-control-number >+ record-type: >+ bib1_mapping: >+ biblioserver: >+ 1: 1001 >+ enabled: 1 >+ index: record-type >+ aliases: >+ - record-type >+ - rtype >+ - mc-rtype >+ - mus >+ label: Record-type >+ regularity-code: >+ bib1_mapping: >+ biblioserver: >+ 1: Regularity-code >+ enabled: 1 >+ index: regularity-code >+ aliases: >+ - regularity-code >+ label: Regularity-code >+ renewals: >+ bib1_mapping: >+ biblioserver: >+ 1: 8020 >+ enabled: 1 >+ index: renewals >+ aliases: >+ - renewals >+ label: Renewals >+ replacementprice: >+ bib1_mapping: >+ biblioserver: >+ 1: 8029 >+ enabled: 1 >+ index: replacementprice >+ aliases: >+ - replacementprice >+ label: Replacementprice >+ replacementpricedate: >+ bib1_mapping: >+ biblioserver: >+ 1: 8030 >+ enabled: 1 >+ index: replacementpricedate >+ aliases: >+ - replacementpricedate >+ label: Replacementpricedate >+ reserves: >+ bib1_mapping: >+ biblioserver: >+ 1: 8021 >+ enabled: 1 >+ index: reserves >+ aliases: >+ - reserves >+ label: Reserves >+ restricted: >+ bib1_mapping: >+ biblioserver: >+ 1: 8006 >+ enabled: 1 >+ index: restricted >+ aliases: >+ - restricted >+ label: Restricted >+ stack: >+ bib1_mapping: >+ biblioserver: >+ 1: 8018 >+ enabled: 1 >+ index: stack >+ aliases: >+ - stack >+ label: Stack >+ stock-number: >+ bib1_mapping: >+ biblioserver: >+ 1: 1028 >+ enabled: 1 >+ index: stock-number >+ aliases: >+ - stock-number >+ label: Stock-number >+ stocknumber: >+ bib1_mapping: >+ biblioserver: >+ 1: 1062 >+ enabled: 1 >+ index: stocknumber >+ aliases: >+ - stocknumber >+ - inv >+ label: Stocknumber >+ summary: >+ bib1_mapping: >+ biblioserver: >+ 1: Summary >+ enabled: 1 >+ index: summary >+ aliases: >+ - summary >+ label: Summary >+ suppress: >+ bib1_mapping: >+ biblioserver: >+ 1: 9011 >+ enabled: 1 >+ index: suppress >+ aliases: >+ - suppress >+ label: Suppress >+ titleext: >+ bib1_mapping: >+ biblioserver: >+ 1: 4 >+ 4: 1 >+ 6: 2 >+ enabled: 1 >+ index: title >+ aliases: [] >+ label: Title ext >+ titlekw: >+ bib1_mapping: >+ biblioserver: >+ 1: 4 >+ enabled: 1 >+ index: title >+ aliases: [] >+ label: Title kw >+ thesaurus: >+ bib1_mapping: >+ authorityserver: >+ 1: Subject-heading-thesaurus >+ enabled: 1 >+ index: thesaurus >+ aliases: >+ - thesaurus >+ label: Thesaurus >+ totalissues: >+ bib1_mapping: >+ biblioserver: >+ 1: 9003 >+ enabled: 1 >+ index: totalissues >+ aliases: >+ - totalissues >+ label: Totalissues >+ type-of-serial: >+ bib1_mapping: >+ biblioserver: >+ 1: Type-Of-Serial >+ enabled: 1 >+ index: type-of-serial >+ aliases: >+ - type-of-serial >+ label: Type-of-serial >+ upc: >+ bib1_mapping: >+ biblioserver: >+ 1: UPC >+ enabled: 1 >+ index: upc >+ aliases: >+ - upc >+ label: Upc >+ uri: >+ bib1_mapping: >+ biblioserver: >+ 1: 8028 >+ enabled: 1 >+ index: uri >+ aliases: >+ - uri >+ label: Uri >+ video-mt: >+ bib1_mapping: >+ biblioserver: >+ 1: Video-mt >+ enabled: 1 >+ index: video-mt >+ aliases: >+ - video-mt >+ label: Video-mt >+ withdrawn: >+ bib1_mapping: >+ biblioserver: >+ 1: 8001 >+ enabled: 1 >+ index: withdrawn >+ aliases: >+ - withdrawn >+ label: Withdrawn >+ subject: >+ subject: >+ bib1_mapping: >+ authorityserver: >+ 1: Match-heading >+ biblioserver: >+ 1: 21 >+ enabled: 1 >+ index: '' >+ label: '' >+ aliases: >+ - su >+ - su-to >+ - su-geo >+ - su-ut >+ authority-number: >+ bib1_mapping: >+ biblioserver: >+ 1: Koha-Auth-Number >+ enabled: 1 >+ index: authority-number >+ label: Authority-number >+ aliases: >+ - authority-number >+ - an >+ complete: >+ bib1_mapping: >+ biblioserver: >+ 1: 21 >+ 3: 1 >+ 4: 1 >+ 5: 100 >+ 6: 3 >+ enabled: 1 >+ index: complete >+ label: Complete >+ aliases: >+ - complete >+ exact: >+ bib1_mapping: >+ authorityserver: >+ 4: 1 >+ 5: 100 >+ 6: 3 >+ enabled: 1 >+ index: exact >+ label: Exact >+ aliases: >+ - exact >+ heading: >+ bib1_mapping: >+ authorityserver: >+ 1: Heading >+ enabled: 1 >+ index: heading >+ label: Heading >+ aliases: >+ - heading >+ - mainentry >+ - he >+ headingmain: >+ bib1_mapping: >+ authorityserver: >+ 1: Heading-Main >+ enabled: 1 >+ index: headingmain >+ label: Headingmain >+ aliases: >+ - headingmain >+ - mainmainentry >+ matchheading: >+ bib1_mapping: >+ authorityserver: >+ 1: Match-heading >+ enabled: 1 >+ index: matchheading >+ label: Matchheading >+ aliases: >+ - matchheading >+ - match-heading >+ name-personal: >+ bib1_mapping: >+ biblioserver: >+ 1: 1009 >+ enabled: 1 >+ index: name-personal >+ label: Name-personal >+ aliases: >+ - name-personal >+ - su-na >+ seefrom: >+ bib1_mapping: >+ authorityserver: >+ 1: Match-heading-see-from >+ enabled: 1 >+ index: seefrom >+ label: Seefrom >+ aliases: >+ - seefrom >+ - see-from >+ start: >+ bib1_mapping: >+ authorityserver: >+ 3: 2 >+ 4: 1 >+ 5: 1 >+ enabled: 1 >+ index: start >+ label: Start >+ aliases: >+ - start >+ title: >+ title: >+ bib1_mapping: >+ biblioserver: >+ 1: 4 >+ enabled: 1 >+ index: '' >+ label: '' >+ aliases: >+ - ti >+ cover: >+ bib1_mapping: >+ biblioserver: >+ 1: 36 >+ enabled: 1 >+ index: cover >+ label: Cover >+ aliases: >+ - cover >+ - title-cover >+ exacttitle: >+ bib1_mapping: >+ biblioserver: >+ 1: 4 >+ 4: 1 >+ 6: 3 >+ enabled: 1 >+ index: exacttitle >+ label: Exacttitle >+ aliases: >+ - exacttitle >+ - ti,ext >+ series: >+ bib1_mapping: >+ biblioserver: >+ 1: 5 >+ enabled: 1 >+ index: series >+ label: Series >+ aliases: >+ - series >+ - title-series >+ - se >+ uniform: >+ bib1_mapping: >+ biblioserver: >+ 1: Title-uniform >+ enabled: 1 >+ index: uniform >+ label: Uniform >+ aliases: >+ - uniform >+ - title-uniform >+filter_mappings: >+ acqdate: >+ bib1_mapping: >+ biblioserver: >+ 1: Date-of-acquisition >+ 4: 4 >+ target_syntax_callback: date_filter_target_callback >+ enabled: 1 >+ label: Acqdate >+ copydate: >+ bib1_mapping: >+ biblioserver: >+ 1: 30 >+ 4: 4 >+ target_syntax_callback: date_filter_target_callback >+ >+ enabled: 1 >+ label: Copydate >+ pubdate: >+ bib1_mapping: >+ biblioserver: >+ 1: pubdate >+ 4: 4 >+ target_syntax_callback: date_filter_target_callback >+ enabled: 1 >+ label: Pubdate >+modifier_mappings: >+ AuthidAsc: >+ bib1_mapping: >+ authorityserver: >+ "": 0 >+ 1: Local-Number >+ 7: 1 >+ op: "@or" >+ enabled: 1 >+ label: AuthidAsc >+ AuthidDsc: >+ bib1_mapping: >+ authorityserver: >+ "": 0 >+ 1: Local-Number >+ 7: 2 >+ op: "@or" >+ enabled: 1 >+ label: AuthidDsc >+ HeadingAsc: >+ bib1_mapping: >+ authorityserver: >+ "": 0 >+ 1: Heading >+ 7: 1 >+ op: "@or" >+ enabled: 1 >+ label: HeadingAsc >+ HeadingDsc: >+ bib1_mapping: >+ authorityserver: >+ "": 0 >+ 1: Heading >+ 7: 2 >+ op: "@or" >+ enabled: 1 >+ label: HeadingDsc >+ Relevance: >+ bib1_mapping: >+ authorityserver: >+ 2: 102 >+ enabled: 1 >+ label: Relevance >+ acqdate_asc: >+ bib1_mapping: >+ biblioserver: >+ "": 0 >+ 1: 32 >+ 7: 2 >+ op: "@or" >+ enabled: 1 >+ label: Acqdate_asc >+ acqdate_dsc: >+ bib1_mapping: >+ biblioserver: >+ "": 0 >+ 1: 32 >+ 7: 1 >+ op: "@or" >+ enabled: 1 >+ label: Acqdate_dsc >+ ascending: >+ bib1_mapping: >+ biblioserver: >+ 7: 1 >+ enabled: 1 >+ label: Ascending >+ author_asc: >+ bib1_mapping: >+ biblioserver: >+ "": 0 >+ 1: 1003 >+ 7: 2 >+ op: "@or" >+ enabled: 1 >+ label: Author_asc >+ author_az: >+ bib1_mapping: >+ biblioserver: >+ "": 0 >+ 1: 1003 >+ 7: 1 >+ op: "@or" >+ enabled: 1 >+ label: Author_az >+ author_dsc: >+ bib1_mapping: >+ biblioserver: >+ "": 0 >+ 1: 1003 >+ 7: 1 >+ op: "@or" >+ enabled: 1 >+ label: Author_dsc >+ author_za: >+ bib1_mapping: >+ biblioserver: >+ "": 0 >+ 1: 1003 >+ 7: 2 >+ op: "@or" >+ enabled: 1 >+ label: Author_za >+ call_number_asc: >+ bib1_mapping: >+ biblioserver: >+ "": 0 >+ 1: 8007 >+ 7: 2 >+ op: "@or" >+ enabled: 1 >+ label: Call_number_asc >+ call_number_dsc: >+ bib1_mapping: >+ biblioserver: >+ "": 0 >+ 1: 8007 >+ 7: 1 >+ op: "@or" >+ enabled: 1 >+ label: Call_number_dsc >+ descending: >+ bib1_mapping: >+ biblioserver: >+ 7: 2 >+ enabled: 1 >+ label: Descending >+ popularity_asc: >+ bib1_mapping: >+ biblioserver: >+ "": 0 >+ 1: 9003 >+ 7: 2 >+ op: "@or" >+ enabled: 1 >+ label: Popularity_asc >+ popularity_dsc: >+ bib1_mapping: >+ biblioserver: >+ "": 0 >+ 1: 9003 >+ 7: 1 >+ op: "@or" >+ enabled: 1 >+ label: Popularity_dsc >+ pubdate_asc: >+ bib1_mapping: >+ biblioserver: >+ "": 0 >+ 1: 31 >+ 7: 2 >+ op: "@or" >+ enabled: 1 >+ label: Pubdate_asc >+ pubdate_dsc: >+ bib1_mapping: >+ biblioserver: >+ "": 0 >+ 1: 31 >+ 7: 1 >+ op: "@or" >+ enabled: 1 >+ label: Pubdate_dsc >+ relevance: >+ bib1_mapping: >+ biblioserver: >+ 2: 102 >+ enabled: 1 >+ label: Relevance >+ relevance_dsc: >+ bib1_mapping: >+ biblioserver: >+ 2: 102 >+ enabled: 1 >+ label: Relevance_dsc >+ title-sort-az: >+ bib1_mapping: >+ biblioserver: >+ "": 0 >+ 1: 36 >+ 7: 1 >+ op: "@or" >+ enabled: 1 >+ label: Title-sort-az >+ title-sort-za: >+ bib1_mapping: >+ biblioserver: >+ "": 0 >+ 1: 36 >+ 7: 2 >+ op: "@or" >+ enabled: 1 >+ label: Title-sort-za >+ title_asc: >+ bib1_mapping: >+ biblioserver: >+ "": 0 >+ 1: 4 >+ 7: 1 >+ op: "@or" >+ enabled: 1 >+ label: Title_asc >+ title_az: >+ bib1_mapping: >+ biblioserver: >+ "": 0 >+ 1: 4 >+ 7: 1 >+ op: "@or" >+ enabled: 1 >+ label: Title_az >+ title_dsc: >+ bib1_mapping: >+ biblioserver: >+ "": 0 >+ 1: 4 >+ 7: 2 >+ op: "@or" >+ enabled: 1 >+ label: Title_dsc >+ title_za: >+ bib1_mapping: >+ biblioserver: >+ "": 0 >+ 1: 4 >+ 7: 2 >+ op: "@or" >+ enabled: 1 >+ label: Title_za >+relevance_bumps: >+ keyword: >+ titleext: >+ enabled: 1 >+ bib1_mapping: >+ biblioserver: 34 >+ titlekw: >+ enabled: 1 >+ bib1_mapping: >+ biblioserver: 20 >diff --git a/t/QueryParser.t b/t/QueryParser.t >new file mode 100644 >index 0000000..01e898a >--- /dev/null >+++ b/t/QueryParser.t >@@ -0,0 +1,95 @@ >+#!/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'}}), 107, "Correct number of search fields for 'keyword' class"); >+ >+is($QParser->target_syntax('biblioserver', 'smith'), '@or @or @attr 1=1016 @attr 4=6 "smith" @attr 9=20 @attr 2=102 @attr 4=6 "smith" @attr 9=34 @attr 2=102 @attr 4=6 "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 9=20 @attr 2=102 @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 pubdate(-2008)'), '@and @attr 1=1003 @attr 4=6 "smith" @attr 4=4 @attr 1=pubdate @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 4=4 @attr 1=pubdate @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 4=4 @attr 1=pubdate "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 4=4 @attr 1=pubdate "1980" @attr 4=4 @attr 1=pubdate "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' => [ >+ 'personal' >+ ], >+ '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(); >-- >1.7.9.5
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 9239
:
14020
|
14021
|
14022
|
14023
|
14172
|
14173
|
14174
|
14175
|
14180
|
14181
|
14182
|
14183
|
14847
|
14949
|
14950
|
14951
|
14952
|
14953
|
15121
|
15437
|
15865
|
15867
|
15929
|
15999
|
16004
|
16051
|
16125
|
16130
|
16131
|
16132
|
16133
|
16136
|
16140
|
16141
|
16142
|
16143
|
16144
|
16145
|
16146
|
16147
|
16148
|
16149
|
16150
|
16151
|
16152
|
16153
|
16154
|
16155
|
16180
| 16181 |
16182
|
16183
|
16184
|
16185
|
16186
|
16187
|
16188
|
16189
|
16190
|
16191
|
16192
|
16193
|
16194
|
16195