Bug 17801: Use issuedate for limits in Most Circulated Items
[srvgit] / C4 / Biblio.pm
index eae7cd5..97fa95a 100644 (file)
@@ -30,7 +30,6 @@ BEGIN {
         AddBiblio
         GetBiblioData
         GetMarcBiblio
-        GetRecordValue
         GetISBDView
         GetMarcControlnumber
         GetMarcNotes
@@ -39,7 +38,6 @@ BEGIN {
         GetMarcSubjects
         GetMarcAuthors
         GetMarcSeries
-        GetMarcHosts
         GetMarcUrls
         GetUsedMarcStructure
         GetXmlBiblio
@@ -55,7 +53,6 @@ BEGIN {
         TransformKohaToMarc
         PrepHostMarcField
         CountItemsIssued
-        CountBiblioInOrders
         ModBiblio
         ModZebra
         UpdateTotalIssues
@@ -67,7 +64,6 @@ BEGIN {
         TransformHtmlToMarc
         TransformHtmlToXml
         prepare_host_field
-        SplitKohaField
     );
 
     # Internal functions
@@ -389,13 +385,6 @@ sub DelBiblio {
 
     return $error if $error;
 
-    # We delete attached subscriptions
-    require C4::Serials;
-    my $subscriptions = C4::Serials::GetFullSubscriptionsFromBiblionumber($biblionumber);
-    foreach my $subscription (@$subscriptions) {
-        C4::Serials::DelSubscription( $subscription->{subscriptionid} );
-    }
-
     # We delete any existing holds
     my $holds = $biblio->holds;
     while ( my $hold = $holds->next ) {
@@ -504,7 +493,7 @@ sub LinkBibHeadingsToAuthorities {
     $allowrelink = 1 unless defined $allowrelink;
     my $num_headings_changed = 0;
     foreach my $field ( $bib->fields() ) {
-        my $heading = C4::Heading->new_from_bib_field( $field, $frameworkcode );
+        my $heading = C4::Heading->new_from_field( $field, $frameworkcode );
         next unless defined $heading;
 
         # check existing $9
@@ -516,7 +505,7 @@ sub LinkBibHeadingsToAuthorities {
             next;
         }
 
-        my ( $authid, $fuzzy ) = $linker->get_link($heading);
+        my ( $authid, $fuzzy, $match_count ) = $linker->get_link($heading);
         if ($authid) {
             $results{ $fuzzy ? 'fuzzy' : 'linked' }
               ->{ $heading->display_form() }++;
@@ -536,7 +525,7 @@ sub LinkBibHeadingsToAuthorities {
                 if ( _check_valid_auth_link( $current_link, $field ) ) {
                     $results{'linked'}->{ $heading->display_form() }++;
                 }
-                else {
+                elsif ( !$match_count ) {
                     my $authority_type = Koha::Authority::Types->find( $heading->auth_type() );
                     my $marcrecordauth = MARC::Record->new();
                     if ( C4::Context->preference('marcflavour') eq 'MARC21' ) {
@@ -545,16 +534,22 @@ sub LinkBibHeadingsToAuthorities {
                     }
                     $field->delete_subfield( code => '9' )
                       if defined $current_link;
-                    my $authfield =
-                      MARC::Field->new( $authority_type->auth_tag_to_report,
-                        '', '', "a" => "" . $field->subfield('a') );
-                    map {
-                        $authfield->add_subfields( $_->[0] => $_->[1] )
-                          if ( $_->[0] =~ /[A-z]/ && $_->[0] ne "a"
-                            && C4::Heading::valid_bib_heading_subfield(
-                                $authority_type->auth_tag_to_report, $_->[0] )
-                            );
-                    } $field->subfields();
+                    my @auth_subfields;
+                    foreach my $subfield ( $field->subfields() ){
+                        if ( $subfield->[0] =~ /[A-z]/
+                            && C4::Heading::valid_heading_subfield(
+                                $field->tag, $subfield->[0] )
+                           ){
+                            push @auth_subfields, $subfield->[0] => $subfield->[1];
+                        }
+                    }
+                    # Bib headings contain some ending punctuation that should NOT
+                    # be included in the authority record. Strip those before creation
+                    next unless @auth_subfields; # Don't try to create a record if we have no fields;
+                    my $last_sub = pop @auth_subfields;
+                    $last_sub =~ s/[\s]*[,.:=;!%\/][\s]*$//;
+                    push @auth_subfields, $last_sub;
+                    my $authfield = MARC::Field->new( $authority_type->auth_tag_to_report, '', '', @auth_subfields );
                     $marcrecordauth->insert_fields_ordered($authfield);
 
 # bug 2317: ensure new authority knows it's using UTF-8; currently
@@ -643,38 +638,6 @@ sub _check_valid_auth_link {
    return ($field->as_string('abcdefghijklmnopqrstuvwxyz') eq $authorized_heading);
 }
 
-=head2 GetRecordValue
-
-  my $values = GetRecordValue($field, $record);
-
-Get MARC fields from the record using the framework mappings for biblio fields.
-
-=cut
-
-sub GetRecordValue {
-    my ( $field, $record ) = @_;
-
-    if (!$record) {
-        carp 'GetRecordValue called with undefined record';
-        return;
-    }
-
-    my @result;
-    my @mss = GetMarcSubfieldStructureFromKohaField("biblio.$field");
-    foreach my $fldhash ( @mss ) {
-        my $tag = $fldhash->{tagfield};
-        my $sub = $fldhash->{tagsubfield};
-        foreach my $fld ( $record->field($tag) ) {
-            if( $sub eq '@' || $fld->is_control_field ) {
-                push @result, $fld->data if $fld->data;
-            } else {
-                push @result, grep { $_ } $fld->subfield($sub);
-            }
-        }
-    }
-    return \@result;
-}
-
 =head2 GetBiblioData
 
   $data = &GetBiblioData($biblionumber);
@@ -859,7 +822,7 @@ sub GetISBDView {
         # Process subfield
     }
 
-GetMarcStructure creates keys (lib, tab, mandatory, repeatable) for a display purpose.
+GetMarcStructure creates keys (lib, tab, mandatory, repeatable, important) for a display purpose.
 These different values should not be processed as valid subfields.
 
 =cut
@@ -897,25 +860,26 @@ sub GetMarcStructure {
 
     my $dbh = C4::Context->dbh;
     my $sth = $dbh->prepare(
-        "SELECT tagfield,liblibrarian,libopac,mandatory,repeatable,ind1_defaultvalue,ind2_defaultvalue
+        "SELECT tagfield,liblibrarian,libopac,mandatory,repeatable,important,ind1_defaultvalue,ind2_defaultvalue
         FROM marc_tag_structure 
         WHERE frameworkcode=? 
         ORDER BY tagfield"
     );
     $sth->execute($frameworkcode);
-    my ( $liblibrarian, $libopac, $tag, $res, $tab, $mandatory, $repeatable, $ind1_defaultvalue, $ind2_defaultvalue );
+    my ( $liblibrarian, $libopac, $tag, $res, $tab, $mandatory, $repeatable, $important, $ind1_defaultvalue, $ind2_defaultvalue );
 
-    while ( ( $tag, $liblibrarian, $libopac, $mandatory, $repeatable, $ind1_defaultvalue, $ind2_defaultvalue ) = $sth->fetchrow ) {
+    while ( ( $tag, $liblibrarian, $libopac, $mandatory, $repeatable, $important, $ind1_defaultvalue, $ind2_defaultvalue ) = $sth->fetchrow ) {
         $res->{$tag}->{lib}        = ( $forlibrarian or !$libopac ) ? $liblibrarian : $libopac;
         $res->{$tag}->{tab}        = "";
         $res->{$tag}->{mandatory}  = $mandatory;
+        $res->{$tag}->{important}  = $important;
         $res->{$tag}->{repeatable} = $repeatable;
     $res->{$tag}->{ind1_defaultvalue} = $ind1_defaultvalue;
     $res->{$tag}->{ind2_defaultvalue} = $ind2_defaultvalue;
     }
 
     $sth = $dbh->prepare(
-        "SELECT tagfield,tagsubfield,liblibrarian,libopac,tab,mandatory,repeatable,authorised_value,authtypecode,value_builder,kohafield,seealso,hidden,isurl,link,defaultvalue,maxlength
+        "SELECT tagfield,tagsubfield,liblibrarian,libopac,tab,mandatory,repeatable,authorised_value,authtypecode,value_builder,kohafield,seealso,hidden,isurl,link,defaultvalue,maxlength,important
          FROM   marc_subfield_structure 
          WHERE  frameworkcode=? 
          ORDER BY tagfield,tagsubfield
@@ -939,13 +903,14 @@ sub GetMarcStructure {
     while (
         (   $tag,          $subfield,      $liblibrarian, $libopac, $tab,    $mandatory, $repeatable, $authorised_value,
             $authtypecode, $value_builder, $kohafield,    $seealso, $hidden, $isurl,     $link,       $defaultvalue,
-            $maxlength
+            $maxlength, $important
         )
         = $sth->fetchrow
       ) {
         $res->{$tag}->{$subfield}->{lib}              = ( $forlibrarian or !$libopac ) ? $liblibrarian : $libopac;
         $res->{$tag}->{$subfield}->{tab}              = $tab;
         $res->{$tag}->{$subfield}->{mandatory}        = $mandatory;
+        $res->{$tag}->{$subfield}->{important}        = $important;
         $res->{$tag}->{$subfield}->{repeatable}       = $repeatable;
         $res->{$tag}->{$subfield}->{authorised_value} = $authorised_value;
         $res->{$tag}->{$subfield}->{authtypecode}     = $authtypecode;
@@ -1185,7 +1150,7 @@ sub GetMarcBiblio {
 
     if ($marcxml) {
         $record = eval {
-            MARC::Record::new_from_xml( $marcxml, "utf8",
+            MARC::Record::new_from_xml( $marcxml, "UTF-8",
                 C4::Context->preference('marcflavour') );
         };
         if ($@) { warn " problem with :$biblionumber : $@ \n$marcxml"; }
@@ -1529,7 +1494,7 @@ sub GetMarcISSN {
 =cut
 
 sub GetMarcNotes {
-    my ( $record, $marcflavour ) = @_;
+    my ( $record, $marcflavour, $opac ) = @_;
     if (!$record) {
         carp 'GetMarcNotes called on undefined record';
         return;
@@ -1537,11 +1502,22 @@ sub GetMarcNotes {
 
     my $scope = $marcflavour eq "UNIMARC"? '3..': '5..';
     my @marcnotes;
-    my %blacklist = map { $_ => 1 }
-        split( /,/, C4::Context->preference('NotesBlacklist'));
+
+    #MARC21 specs indicate some notes should be private if first indicator 0
+    my %maybe_private = (
+        541 => 1,
+        542 => 1,
+        561 => 1,
+        583 => 1,
+        590 => 1
+    );
+
+    my %hiddenlist = map { $_ => 1 }
+        split( /,/, C4::Context->preference('NotesToHide'));
     foreach my $field ( $record->field($scope) ) {
         my $tag = $field->tag();
-        next if $blacklist{ $tag };
+        next if $hiddenlist{ $tag };
+        next if $opac && $maybe_private{$tag} && !$field->indicator(1);
         if( $marcflavour ne 'UNIMARC' && $field->subfield('u') ) {
             # Field 5XX$u always contains URI
             # Examples: 505u, 506u, 510u, 514u, 520u, 530u, 538u, 540u, 542u, 552u, 555u, 561u, 563u, 583u
@@ -1884,53 +1860,6 @@ sub GetMarcSeries {
     return \@marcseries;
 }    #end getMARCseriess
 
-=head2 GetMarcHosts
-
-  $marchostsarray = GetMarcHosts($record,$marcflavour);
-
-Get all host records (773s MARC21, 461 UNIMARC) from the MARC record and returns them in an array.
-
-=cut
-
-sub GetMarcHosts {
-    my ( $record, $marcflavour ) = @_;
-    if (!$record) {
-        carp 'GetMarcHosts called on undefined record';
-        return;
-    }
-
-    my ( $tag,$title_subf,$bibnumber_subf,$itemnumber_subf);
-    $marcflavour ||="MARC21";
-    if ( $marcflavour eq "MARC21" || $marcflavour eq "NORMARC" ) {
-        $tag = "773";
-        $title_subf = "t";
-        $bibnumber_subf ="0";
-        $itemnumber_subf='9';
-    }
-    elsif ($marcflavour eq "UNIMARC") {
-        $tag = "461";
-        $title_subf = "t";
-        $bibnumber_subf ="0";
-        $itemnumber_subf='9';
-    };
-
-    my @marchosts;
-
-    foreach my $field ( $record->field($tag)) {
-
-        my @fields_loop;
-
-        my $hostbiblionumber = $field->subfield("$bibnumber_subf");
-        my $hosttitle = $field->subfield($title_subf);
-        my $hostitemnumber=$field->subfield($itemnumber_subf);
-        push @fields_loop, { hostbiblionumber => $hostbiblionumber, hosttitle => $hosttitle, hostitemnumber => $hostitemnumber};
-        push @marchosts, { MARCHOSTS_FIELDS_LOOP => \@fields_loop };
-
-        }
-    my $marchostsarray = \@marchosts;
-    return $marchostsarray;
-}
-
 =head2 UpsertMarcSubfield
 
     my $record = C4::Biblio::UpsertMarcSubfield($MARC::Record, $fieldTag, $subfieldCode, $subfieldContent);
@@ -2006,16 +1935,18 @@ sub TransformKohaToMarc {
 
     # In the next call we use the Default framework, since it is considered
     # authoritative for Koha to Marc mappings.
-    my $mss = GetMarcSubfieldStructure( '', { unsafe => 1 } ); # do not change framewok
+    my $mss = GetMarcSubfieldStructure( '', { unsafe => 1 } ); # do not change framework
     my $tag_hr = {};
     while ( my ($kohafield, $value) = each %$hash ) {
         foreach my $fld ( @{ $mss->{$kohafield} } ) {
             my $tagfield    = $fld->{tagfield};
             my $tagsubfield = $fld->{tagsubfield};
             next if !$tagfield;
-            my @values = $params->{no_split}
-                ? ( $value )
-                : split(/\s?\|\s?/, $value, -1);
+
+            # BZ 21800: split value if field is repeatable.
+            my @values = _check_split($params, $fld, $value)
+                ? split(/\s?\|\s?/, $value, -1)
+                : ( $value );
             foreach my $value ( @values ) {
                 next if $value eq '';
                 $tag_hr->{$tagfield} //= [];
@@ -2036,6 +1967,25 @@ sub TransformKohaToMarc {
     return $record;
 }
 
+sub _check_split {
+# Checks if $value must be split; may consult passed framework
+    my ($params, $fld, $value) = @_;
+    return if index($value,'|') == -1; # nothing to worry about
+    return if $params->{no_split};
+
+    # if we did not get a specific framework, check default in $mss
+    return $fld->{repeatable} if !$params->{framework};
+
+    # here we need to check the specific framework
+    my $mss = GetMarcSubfieldStructure($params->{framework}, { unsafe => 1 });
+    foreach my $fld2 ( @{ $mss->{ $fld->{kohafield} } } ) {
+        next if $fld2->{tagfield} ne $fld->{tagfield};
+        next if $fld2->{tagsubfield} ne $fld->{tagsubfield};
+        return 1 if $fld2->{repeatable};
+    }
+    return;
+}
+
 =head2 PrepHostMarcField
 
     $hostfield = PrepHostMarcField ( $hostbiblionumber,$hostitemnumber,$marcflavour )
@@ -2148,7 +2098,6 @@ sub TransformHtmlToXml {
     # MARC::Record->new_from_xml will fail (and Koha will die)
     my $unimarc_and_100_exist = 0;
     $unimarc_and_100_exist = 1 if $auth_type eq 'ITEM';    # if we rebuild an item, no need of a 100 field
-    my $prevvalue;
     my $prevtag = -1;
     my $first   = 1;
     my $j       = -1;
@@ -2375,6 +2324,7 @@ sub TransformHtmlToMarc {
         }
     }
 
+    @fields = sort { $a->tag() cmp $b->tag() } @fields;
     $record->append_fields(@fields);
     return $record;
 }
@@ -2547,8 +2497,8 @@ $op is specialUpdate or recordDelete, and is used to know what we want to do
 
 $server is the server that we want to update
 
-$record is the update MARC record if it's available. If it's not supplied
-and is needed, it'll be loaded from the database.
+$record is the updated MARC record. If it's not supplied
+and is needed it will be loaded from the database.
 
 =cut
 
@@ -2573,7 +2523,6 @@ sub ModZebra {
                     biblionumber => $biblionumber,
                     embed_items  => 1 });
             }
-            my $records = [$record];
             $indexer->update_index_background( [$biblionumber], [$record] );
         }
         elsif ( $op eq 'recordDelete' ) {
@@ -3203,26 +3152,6 @@ sub ModBiblioMarc {
     return $biblionumber;
 }
 
-=head2 CountBiblioInOrders
-
-    $count = &CountBiblioInOrders( $biblionumber);
-
-This function return count of biblios in orders with $biblionumber 
-
-=cut
-
-sub CountBiblioInOrders {
- my ($biblionumber) = @_;
-    my $dbh            = C4::Context->dbh;
-    my $query          = "SELECT count(*)
-          FROM  aqorders 
-          WHERE biblionumber=? AND (datecancellationprinted IS NULL OR datecancellationprinted='0000-00-00')";
-    my $sth = $dbh->prepare($query);
-    $sth->execute($biblionumber);
-    my $count = $sth->fetchrow;
-    return ($count);
-}
-
 =head2 prepare_host_field
 
 $marcfield = prepare_host_field( $hostbiblioitem, $marcflavour );
@@ -3453,25 +3382,6 @@ sub RemoveAllNsb {
     return $record;
 }
 
-=head2 SplitKohaField
-
-    $subtitles = SplitKohaField($biblio->subtitle());
-
-Splits a Koha field with multiple values to an array. Multiple matches for a
-Koha field (according to the bibliographic framework) are concatenated with
-' | ', but in many cases it's not optimal for display and an array is
-preferred.
-
-=cut
-
-sub SplitKohaField {
-    my $field = shift;
-
-    my @parts = split(/ \| /, $field // '' );
-
-    return \@parts;
-}
-
 1;
 
 
@@ -3487,26 +3397,15 @@ sub _after_biblio_action_hooks {
     my $biblio_id = $args->{biblio_id};
     my $action    = $args->{action};
 
-    if ( C4::Context->preference('UseKohaPlugins') && C4::Context->config("enable_plugins") ) {
-
-        my @plugins = Koha::Plugins->new->GetPlugins({
-            method => 'after_biblio_action',
-        });
-
-        if (@plugins) {
-
-            my $biblio = Koha::Biblios->find( $biblio_id );
-
-            foreach my $plugin ( @plugins ) {
-                try {
-                    $plugin->after_biblio_action({ action => $action, biblio => $biblio, biblio_id => $biblio_id });
-                }
-                catch {
-                    warn "$_";
-                };
-            }
+    my $biblio = Koha::Biblios->find( $biblio_id );
+    Koha::Plugins->call(
+        'after_biblio_action',
+        {
+            action    => $action,
+            biblio    => $biblio,
+            biblio_id => $biblio_id,
         }
-    }
+    );
 }
 
 __END__