X-Git-Url: http://koha-dev.rot13.org:8081/gitweb/?a=blobdiff_plain;f=C4%2FHeading.pm;h=4d67cd56241a52eaa70bb89d1b05cafeb4968304;hb=eded6edacc5e3bf8dd0be21ed05842c3b78aadce;hp=d9e13d422323ad0d38398bf461650b58384bdcfd;hpb=58c46b27af601a893e1eabdfb5bd7d4d0d887f24;p=koha-ffzg.git diff --git a/C4/Heading.pm b/C4/Heading.pm index d9e13d4223..4d67cd5624 100644 --- a/C4/Heading.pm +++ b/C4/Heading.pm @@ -1,31 +1,28 @@ package C4::Heading; # Copyright (C) 2008 LibLime -# +# # 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 2 of the License, or (at your option) any later -# version. +# 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. +# 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, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl; -use strict; -#use warnings; FIXME - Bug 2505 -use MARC::Record; use MARC::Field; use C4::Context; -use C4::Heading::MARC21; -use Carp; +use Module::Load qw( load ); -our $VERSION = 3.00; =head1 NAME @@ -34,11 +31,11 @@ C4::Heading =head1 SYNOPSIS use C4::Heading; - my $heading = C4::Heading->new_from_bib_field($field); + my $heading = C4::Heading->new_from_field($field, $frameworkcode); my $thesaurus = $heading->thesaurus(); my $type = $heading->type(); - my $display_heading = $heading->display(); - my $search_string = $heading->search_string(); + my $display_heading = $heading->display_form(); + my $search_form = $heading->search_form(); =head1 DESCRIPTION @@ -47,41 +44,69 @@ headings found in bibliographic and authority records. =head1 METHODS -=head2 new_from_bib_field +=head2 new_from_field - my $heading = C4::Heading->new_from_bib_field($field[, $marc_flavour]); + my $heading = C4::Heading->new_from_field($field, $frameworkcode, [, $auth]); Given a C object containing a heading from a bib record, create a C object. -The optional second parameter is the MARC flavour (i.e., MARC21 -or UNIMARC); if this parameter is not supplied, it is -taken from the Koha application context. +The optional third parameter is 'auth' - it is handled as boolean. If supplied we treat the field as an auth record field. Otherwise if it is a bib field. The fields checked are the same in a UNIMARC system and this parameter is ignored If the MARC field supplied is not a valid heading, undef is returned. =cut -sub new_from_bib_field { - my $class = shift; - my $field = shift; - my $marcflavour = @_ ? shift : C4::Context->preference('marcflavour'); - +sub new_from_field { + my $class = shift; + my $field = shift; + my $frameworkcode = shift; #FIXME this is not used? + my $auth = shift; + my $marcflavour = C4::Context->preference('marcflavour'); my $marc_handler = _marc_format_handler($marcflavour); my $tag = $field->tag(); - return unless $marc_handler->valid_bib_heading_tag($tag); + return unless $marc_handler->valid_heading_tag( $tag, $frameworkcode, $auth ); my $self = {}; - - ($self->{'auth_type'}, $self->{'subject_added_entry'}, $self->{'series_added_entry'}, $self->{'main_entry'}, - $self->{'thesaurus'}, $self->{'search_form'}, $self->{'display_form'}) = - $marc_handler->parse_heading($field); + + $self->{'field'} = $field; + ( + $self->{'auth_type'}, $self->{'thesaurus'}, + $self->{'search_form'}, $self->{'display_form'}, + $self->{'match_type'} + ) = $marc_handler->parse_heading($field, $auth ); bless $self, $class; return $self; } +=head2 auth_type + + my $auth_type = $heading->auth_type(); + +Return the auth_type of the heading. + +=cut + +sub auth_type { + my $self = shift; + return $self->{'auth_type'}; +} + +=head2 field + + my $field = $heading->field(); + +Return the MARC::Field the heading is based on. + +=cut + +sub field { + my $self = shift; + return $self->{'field'}; +} + =head2 display_form my $display = $heading->display_form(); @@ -95,24 +120,33 @@ sub display_form { return $self->{'display_form'}; } +=head2 search_form + + my $search_form = $heading->search_form(); + +Return the "canonical" search form of the heading. + +=cut + +sub search_form { + my $self = shift; + return $self->{'search_form'}; +} + =head2 authorities - my $authorities = $heading->authorities; + my $authorities = $heading->authorities([$skipmetadata]); Return a list of authority records for this -heading. +heading. If passed a true value for $skipmetadata, +SearchAuthorities will return only authids. =cut sub authorities { - my $self = shift; - my $query = qq(Match-heading,do-not-truncate,ext="$self->{'search_form'}"); - $query .= $self->_query_limiters(); - require C4::Search; - my ($error, $results, $total_hits) = C4::Search::SimpleSearch( $query, undef, undef, [ "authorityserver" ] ); - if (defined $error) { - carp "Error:$error from search $query"; - } + my $self = shift; + my $skipmetadata = shift; + my ( $results, $total ) = _search( $self, 'match-heading', $skipmetadata ); return $results; } @@ -127,37 +161,77 @@ that are a preferred form of the heading. sub preferred_authorities { my $self = shift; - my $query = "Match-heading-see-from,do-not-truncate,ext='$self->{'search_form'}'"; - $query .= $self->_query_limiters(); - require C4::Search; - my ($error, $results, $total_hits) = C4::Search::SimpleSearch( $query, undef, undef, [ "authorityserver" ] ); - if (defined $error) { - carp "Error:$error from search $query"; - } + my $skipmetadata = shift || undef; + my ( $results, $total ) = _search( 'see-from', $skipmetadata ); return $results; } -=head1 INTERNAL METHODS +=head2 valid_heading_subfield + + if (C4::Heading::valid_heading_subfield('100', 'e', '')) ... -=head2 _query_limiters +Check if the given subfield is valid for the given field. =cut -sub _query_limiters { - my $self = shift; +sub valid_heading_subfield { + my $tag = shift; + my $subfield = shift; + my $marcflavour = C4::Context->preference('marcflavour'); + my $auth = shift; - my $limiters = " AND at='$self->{'auth_type'}'"; - if ($self->{'subject_added_entry'}) { - $limiters .= " AND Heading-use-subject-added-entry=a"; # FIXME -- is this properly in C4::Heading::MARC21? - $limiters .= " AND Subject-heading-thesaurus=$self->{'thesaurus'}"; - } - if ($self->{'series_added_entry'}) { - $limiters .= " AND Heading-use-series-added-entry=a"; # FIXME -- is this properly in C4::Heading::MARC21? - } - if (not $self->{'subject_added_entry'} and not $self->{'series_added_entry'}) { - $limiters .= " AND Heading-use-main-or-added-entry=a" # FIXME -- is this properly in C4::Heading::MARC21? + my $marc_handler = _marc_format_handler($marcflavour); + return $marc_handler->valid_heading_subfield( $tag, $subfield, $auth ); +} + +=head1 INTERNAL METHODS + +=head2 _search + +=cut + +sub _search { + my $self = shift; + my $index = shift || undef; + my $skipmetadata = shift || undef; + my @marclist; + my @and_or; + my @excluding = []; + my @operator; + my @value; + + if ($index) { + push @marclist, $index; + push @and_or, 'AND'; + push @operator, $self->{'match_type'}; + push @value, $self->{'search_form'}; } - return $limiters; + + # if ($self->{'thesaurus'}) { + # push @marclist, 'thesaurus'; + # push @and_or, 'AND'; + # push @excluding, ''; + # push @operator, 'is'; + # push @value, $self->{'thesaurus'}; + # } + + require Koha::SearchEngine::QueryBuilder; + require Koha::SearchEngine::Search; + + # Use state variables to avoid recreating the objects every time. + # With Elasticsearch this also avoids creating a massive amount of + # ES connectors that would eventually run out of file descriptors. + state $builder = Koha::SearchEngine::QueryBuilder->new( + { index => $Koha::SearchEngine::AUTHORITIES_INDEX } ); + state $searcher = Koha::SearchEngine::Search->new( + {index => $Koha::SearchEngine::AUTHORITIES_INDEX} ); + + my $search_query = $builder->build_authorities_query_compat( + \@marclist, \@and_or, \@excluding, \@operator, + \@value, $self->{'auth_type'}, + 'AuthidAsc' + ); + return $searcher->search_auth_compat( $search_query, 0, 20, $skipmetadata ); } =head1 INTERNAL FUNCTIONS @@ -170,14 +244,10 @@ depending on the selected MARC flavour. =cut sub _marc_format_handler { - my $marcflavour = shift; - - if ($marcflavour eq 'UNIMARC') { - return C4::Heading::UNIMARC->new(); - } else { - return C4::Heading::MARC21->new(); - } - + my $marcflavour = uc shift; + my $pname = "C4::Heading::$marcflavour"; + load $pname; + return $pname->new(); } =head1 AUTHOR