Bug 29697: Replace GetMarcBiblio occurrences with $biblio->metadata->record
[srvgit] / cataloguing / addbiblio.pl
index 11c6d38..92abe81 100755 (executable)
 
 use Modern::Perl;
 
-use CGI q(-utf8);
-use C4::Output;
-use C4::Auth;
-use C4::Biblio;
-use C4::Search;
-use C4::AuthoritiesMarc;
+use CGI;
+use C4::Output qw( output_html_with_http_headers );
+use C4::Auth qw( get_template_and_user haspermission );
+use C4::Biblio qw(
+    AddBiblio
+    DelBiblio
+    GetFrameworkCode
+    GetMarcFromKohaField
+    GetMarcStructure
+    GetUsedMarcStructure
+    ModBiblio
+    prepare_host_field
+    PrepHostMarcField
+    TransformHtmlToMarc
+);
+use C4::Search qw( FindDuplicate enabled_staff_search_views );
+use C4::Auth qw( get_template_and_user haspermission );
 use C4::Context;
 use MARC::Record;
-use C4::Log;
-use C4::Koha;
-use C4::ClassSource;
-use C4::ImportBatch;
-use C4::Charset;
+use C4::ClassSource qw( GetClassSources );
+use C4::ImportBatch qw( GetImportRecordMarc );
+use C4::Charset qw( SetMarcUnicodeFlag );
 use Koha::BiblioFrameworks;
-use Koha::DateUtils;
+use Koha::DateUtils qw( dt_from_string );
 
+use Koha::Biblios;
 use Koha::ItemTypes;
 use Koha::Libraries;
 
 use Koha::BiblioFrameworks;
+use Koha::Patrons;
 
-use Date::Calc qw(Today);
 use MARC::File::USMARC;
 use MARC::File::XML;
-use URI::Escape;
+use URI::Escape qw( uri_escape_utf8 );
 
 if ( C4::Context->preference('marcflavour') eq 'UNIMARC' ) {
     MARC::File::XML->default_record_format('UNIMARC');
@@ -72,7 +82,7 @@ sub MARCfindbreeding {
     # remove the - in isbn, koha store isbn without any -
     if ($marc) {
         my $record = MARC::Record->new_from_usmarc($marc);
-        my ($isbnfield,$isbnsubfield) = GetMarcFromKohaField('biblioitems.isbn','');
+        my ($isbnfield,$isbnsubfield) = GetMarcFromKohaField( 'biblioitems.isbn' );
         if ( $record->field($isbnfield) ) {
             foreach my $field ( $record->field($isbnfield) ) {
                 foreach my $subfield ( $field->subfield($isbnsubfield) ) {
@@ -105,7 +115,7 @@ sub MARCfindbreeding {
                 and C4::Context->preference("z3950AuthorAuthFields")
                 and C4::Context->preference("marcflavour") eq 'UNIMARC' )
             {
-                my ( $tag, $subfield ) = GetMarcFromKohaField("biblio.author", '');
+                my ( $tag, $subfield ) = GetMarcFromKohaField( "biblio.author" );
 
                 my $auth_fields =
                   C4::Context->preference("z3950AuthorAuthFields");
@@ -170,14 +180,15 @@ sub build_authorized_values_list {
     # builds list, depending on authorised value...
 
     #---- branch
-    if ( $tagslib->{$tag}->{$subfield}->{'authorised_value'} eq "branches" ) {
+    my $category = $tagslib->{$tag}->{$subfield}->{authorised_value};
+    if ( $category eq "branches" ) {
         my $libraries = Koha::Libraries->search_filtered({}, {order_by => ['branchname']});
         while ( my $l = $libraries->next ) {
             push @authorised_values, $l->branchcode;;
             $authorised_lib{$l->branchcode} = $l->branchname;
         }
     }
-    elsif ( $tagslib->{$tag}->{$subfield}->{authorised_value} eq "itemtypes" ) {
+    elsif ( $category eq "itemtypes" ) {
         push @authorised_values, "";
 
         my $itemtype;
@@ -188,7 +199,7 @@ sub build_authorized_values_list {
         }
         $value = $itemtype unless ($value);
     }
-    elsif ( $tagslib->{$tag}->{$subfield}->{authorised_value} eq "cn_source" ) {
+    elsif ( $category eq "cn_source" ) {
         push @authorised_values, "";
 
         my $class_sources = GetClassSources();
@@ -219,6 +230,7 @@ sub build_authorized_values_list {
         }
     }
     $authorised_values_sth->finish;
+
     return {
         type     => 'select',
         id       => "tag_".$tag."_subfield_".$subfield."_".$index_tag."_".$index_subfield,
@@ -226,6 +238,7 @@ sub build_authorized_values_list {
         default  => $value,
         values   => \@authorised_values,
         labels   => \%authorised_lib,
+        ( ( grep { $_ eq $category } ( qw(branches itemtypes cn_source) ) ) ? () : ( category => $category ) ),
     };
 
 }
@@ -249,11 +262,11 @@ sub CreateKey {
 
 sub GetMandatoryFieldZ3950 {
     my $frameworkcode = shift;
-    my @isbn   = GetMarcFromKohaField('biblioitems.isbn',$frameworkcode);
-    my @title  = GetMarcFromKohaField('biblio.title',$frameworkcode);
-    my @author = GetMarcFromKohaField('biblio.author',$frameworkcode);
-    my @issn   = GetMarcFromKohaField('biblioitems.issn',$frameworkcode);
-    my @lccn   = GetMarcFromKohaField('biblioitems.lccn',$frameworkcode);
+    my @isbn   = GetMarcFromKohaField( 'biblioitems.isbn' );
+    my @title  = GetMarcFromKohaField( 'biblio.title' );
+    my @author = GetMarcFromKohaField( 'biblio.author' );
+    my @issn   = GetMarcFromKohaField( 'biblioitems.issn' );
+    my @lccn   = GetMarcFromKohaField( 'biblioitems.lccn' );
     
     return {
         $isbn[0].$isbn[1]     => 'isbn',
@@ -271,29 +284,30 @@ sub GetMandatoryFieldZ3950 {
 =cut
 
 sub create_input {
-    my ( $tag, $subfield, $value, $index_tag, $tabloop, $rec, $authorised_values_sth,$cgi ) = @_;
+    my ( $tag, $subfield, $value, $index_tag, $rec, $authorised_values_sth,$cgi ) = @_;
     
     my $index_subfield = CreateKey(); # create a specifique key for each subfield
 
-    $value =~ s/"/"/g;
-
-    # if there is no value provided but a default value in parameters, get it
-    if ( $value eq '' ) {
+    # Apply optional framework default value when it is a new record
+    # Substitute date parts, user name
+    if ( $value eq '' && !$cgi->param('biblionumber') ) {
         $value = $tagslib->{$tag}->{$subfield}->{defaultvalue} // q{};
 
-        # get today date & replace <<YYYY>>, <<MM>>, <<DD>> if provided in the default value
+        # get today date & replace <<YYYY>>, <<YY>>, <<MM>>, <<DD>> if provided in the default value
         my $today_dt = dt_from_string;
         my $year = $today_dt->strftime('%Y');
+        my $shortyear = $today_dt->strftime('%y');
         my $month = $today_dt->strftime('%m');
         my $day = $today_dt->strftime('%d');
         $value =~ s/<<YYYY>>/$year/g;
+        $value =~ s/<<YY>>/$shortyear/g;
         $value =~ s/<<MM>>/$month/g;
         $value =~ s/<<DD>>/$day/g;
         # And <<USER>> with surname (?)
         my $username=(C4::Context->userenv?C4::Context->userenv->{'surname'}:"superlibrarian");
         $value=~s/<<USER>>/$username/g;
-    
     }
+
     my $dbh = C4::Context->dbh;
 
     # map '@' as "subfield" label for fixed fields
@@ -307,6 +321,7 @@ sub create_input {
         marc_lib       => $tagslib->{$tag}->{$subfield}->{lib},
         tag_mandatory  => $tagslib->{$tag}->{mandatory},
         mandatory      => $tagslib->{$tag}->{$subfield}->{mandatory},
+        important      => $tagslib->{$tag}->{$subfield}->{important},
         repeatable     => $tagslib->{$tag}->{$subfield}->{repeatable},
         kohafield      => $tagslib->{$tag}->{$subfield}->{kohafield},
         index          => $index_tag,
@@ -320,13 +335,15 @@ sub create_input {
         $subfield_data{z3950_mandatory} = $mandatory_z3950->{$tag.$subfield};
     }
     # Subfield is hidden depending of hidden and mandatory flag, and is always
-    # shown if it contains anything or if its field is mandatory.
+    # shown if it contains anything or if its field is mandatory or important.
     my $tdef = $tagslib->{$tag};
     $subfield_data{visibility} = "display:none;"
         if $tdef->{$subfield}->{hidden} % 2 == 1 &&
            $value eq '' &&
            !$tdef->{$subfield}->{mandatory} &&
-           !$tdef->{mandatory};
+           !$tdef->{mandatory} &&
+           !$tdef->{$subfield}->{important} &&
+           !$tdef->{important};
     # expand all subfields of 773 if there is a host item provided in the input
     $subfield_data{visibility} ="" if ($tag eq 773 and $cgi->param('hostitemnumber'));
 
@@ -337,13 +354,14 @@ sub create_input {
           build_authorized_values_list( $tag, $subfield, $value, $dbh,
             $authorised_values_sth,$index_tag,$index_subfield );
 
-    # it's a subfield $9 linking to an authority record - see bug 2206
+    # it's a subfield $9 linking to an authority record - see bug 2206 and 28022
     }
     elsif ($subfield eq "9" and
            exists($tagslib->{$tag}->{'a'}->{authtypecode}) and
            defined($tagslib->{$tag}->{'a'}->{authtypecode}) and
-           $tagslib->{$tag}->{'a'}->{authtypecode} ne '') {
-
+           $tagslib->{$tag}->{'a'}->{authtypecode} ne '' and
+           $tagslib->{$tag}->{'a'}->{hidden} > -4 and
+           $tagslib->{$tag}->{'a'}->{hidden} < 5) {
         $subfield_data{marc_value} = {
             type      => 'text',
             id        => $subfield_data{id},
@@ -378,7 +396,7 @@ sub create_input {
             name => $tagslib->{$tag}->{$subfield}->{'value_builder'},
         });
         my $pars= { dbh => $dbh, record => $rec, tagslib => $tagslib,
-            id => $subfield_data{id}, tabloop => $tabloop };
+            id => $subfield_data{id} };
         $plugin->build( $pars );
         if( !$plugin->errstr ) {
             $subfield_data{marc_value} = {
@@ -389,6 +407,7 @@ sub create_input {
                 size           => 67,
                 maxlength      => $subfield_data{maxlength},
                 javascript     => $plugin->javascript,
+                plugin         => $plugin->name,
                 noclick        => $plugin->noclick,
             };
         } else {
@@ -483,7 +502,7 @@ sub build_tabs {
     $query .= qq{ LEFT JOIN authorised_values_branches ON ( id = av_id )} if $branch_limit;
     $query .= " WHERE category = ?";
     $query .= " AND ( branchcode = ? OR branchcode IS NULL )" if $branch_limit;
-    $query .= " GROUP BY lib ORDER BY lib, lib_opac";
+    $query .= " GROUP BY authorised_value,lib ORDER BY lib, lib_opac";
     my $authorised_values_sth = $dbh->prepare( $query );
 
     # in this array, we will push all the 10 tabs
@@ -491,16 +510,19 @@ sub build_tabs {
     my @BIG_LOOP;
     my %seen;
     my @tab_data; # all tags to display
-    
+
+    my $max_num_tab=-1;
+    my ( $itemtag, $itemsubfield ) = GetMarcFromKohaField( "items.itemnumber" );
     foreach my $used ( @$usedTagsLib ){
+
         push @tab_data,$used->{tagfield} if not $seen{$used->{tagfield}};
         $seen{$used->{tagfield}}++;
-    }
-        
-    my $max_num_tab=-1;
-    foreach(@$usedTagsLib){
-        if($_->{tab} > -1 && $_->{tab} >= $max_num_tab && $_->{tagfield} != '995'){ # FIXME : MARC21 ?
-            $max_num_tab = $_->{tab}; 
+
+        if (   $used->{tab} > -1
+            && $used->{tab} >= $max_num_tab
+            && $used->{tagfield} ne $itemtag )
+        {
+            $max_num_tab = $used->{tab};
         }
     }
     if($max_num_tab >= 9){
@@ -510,7 +532,7 @@ sub build_tabs {
     for ( my $tabloop = 0 ; $tabloop <= $max_num_tab ; $tabloop++ ) {
         my @loop_data = (); #innerloop in the template.
         my $i = 0;
-        foreach my $tag (@tab_data) {
+        foreach my $tag (sort @tab_data) {
             $i++;
             next if ! $tag;
             my ($indicator1, $indicator2);
@@ -547,7 +569,7 @@ sub build_tabs {
                         push(
                             @subfields_data,
                             &create_input(
-                                $tag, $subfield, $value, $index_tag, $tabloop, $record,
+                                $tag, $subfield, $value, $index_tag, $record,
                                 $authorised_values_sth,$input
                             )
                         );
@@ -558,11 +580,11 @@ sub build_tabs {
                             my $subfield = $subfields[$subfieldcount][0];
                             my $value    = $subfields[$subfieldcount][1];
                             next if ( length $subfield != 1 );
-                            next if ( $tagslib->{$tag}->{$subfield}->{tab} ne $tabloop );
+                            next if ( !defined $tagslib->{$tag}->{$subfield} || $tagslib->{$tag}->{$subfield}->{tab} ne $tabloop );
                             push(
                                 @subfields_data,
                                 &create_input(
-                                    $tag, $subfield, $value, $index_tag, $tabloop,
+                                    $tag, $subfield, $value, $index_tag,
                                     $record, $authorised_values_sth,$input
                                 )
                             );
@@ -581,16 +603,18 @@ sub build_tabs {
                             and not ( $subfield eq "9" and
                                       exists($tagslib->{$tag}->{'a'}->{authtypecode}) and
                                       defined($tagslib->{$tag}->{'a'}->{authtypecode}) and
-                                      $tagslib->{$tag}->{'a'}->{authtypecode} ne ""
+                                      $tagslib->{$tag}->{'a'}->{authtypecode} ne "" and
+                                      $tagslib->{$tag}->{'a'}->{hidden} > -4 and
+                                      $tagslib->{$tag}->{'a'}->{hidden} < 5
                                     )
                           ;    #check for visibility flag
                                # if subfield is $9 in a field whose $a is authority-controlled,
-                               # always include in the form regardless of the hidden setting - bug 2206
+                               # always include in the form regardless of the hidden setting - bug 2206 and 28022
                         next if ( defined( $field->subfield($subfield) ) );
                         push(
                             @subfields_data,
                             &create_input(
-                                $tag, $subfield, '', $index_tag, $tabloop, $record,
+                                $tag, $subfield, '', $index_tag, $record,
                                 $authorised_values_sth,$input
                             )
                         );
@@ -606,6 +630,7 @@ sub build_tabs {
                             tag_lib       => $tagslib->{$tag}->{lib},
                             repeatable       => $tagslib->{$tag}->{repeatable},
                             mandatory       => $tagslib->{$tag}->{mandatory},
+                            important       => $tagslib->{$tag}->{important},
                             subfield_loop => \@subfields_data,
                             fixedfield    => $tag < 10?1:0,
                             random        => CreateKey,
@@ -622,25 +647,30 @@ sub build_tabs {
             }
             else {
                 my @subfields_data;
-                foreach my $subfield ( sort( keys %{ $tagslib->{$tag} } ) ) {
-                    next if ( length $subfield != 1 );
+                foreach my $subfield (
+                    sort { $a->{display_order} <=> $b->{display_order} || $a->{subfield} cmp $b->{subfield} }
+                    grep { ref($_) && %$_ } # Not a subfield (values for "important", "lib", "mandatory", etc.) or empty
+                    values %{ $tagslib->{$tag} } )
+                {
                     next
-                      if ( ( $tagslib->{$tag}->{$subfield}->{hidden} <= -4 )
-                        or ( $tagslib->{$tag}->{$subfield}->{hidden} >= 5 ) )
-                      and not ( $subfield eq "9" and
+                      if ( ( $subfield->{hidden} <= -4 )
+                        or ( $subfield->{hidden} >= 5 ) )
+                      and not ( $subfield->{subfield} eq "9" and
                                 exists($tagslib->{$tag}->{'a'}->{authtypecode}) and
                                 defined($tagslib->{$tag}->{'a'}->{authtypecode}) and
-                                $tagslib->{$tag}->{'a'}->{authtypecode} ne ""
+                                $tagslib->{$tag}->{'a'}->{authtypecode} ne "" and
+                                $tagslib->{$tag}->{'a'}->{hidden} > -4 and
+                                $tagslib->{$tag}->{'a'}->{hidden} < 5
                               )
                       ;    #check for visibility flag
                            # if subfield is $9 in a field whose $a is authority-controlled,
-                           # always include in the form regardless of the hidden setting - bug 2206
+                           # always include in the form regardless of the hidden setting - bug 2206 and 28022
                     next
-                      if ( $tagslib->{$tag}->{$subfield}->{tab} ne $tabloop );
+                      if ( $subfield->{tab} ne $tabloop );
                        push(
                         @subfields_data,
                         &create_input(
-                            $tag, $subfield, '', $index_tag, $tabloop, $record,
+                            $tag, $subfield->{subfield}, '', $index_tag, $record,
                             $authorised_values_sth,$input
                         )
                     );
@@ -652,6 +682,7 @@ sub build_tabs {
                         tag_lib          => $tagslib->{$tag}->{lib},
                         repeatable       => $tagslib->{$tag}->{repeatable},
                         mandatory       => $tagslib->{$tag}->{mandatory},
+                        important       => $tagslib->{$tag}->{important},
                         indicator1       => ( $indicator1 || $tagslib->{$tag}->{ind1_defaultvalue} ), #if not set, try to load the default value
                         indicator2       => ( $indicator2 || $tagslib->{$tag}->{ind2_defaultvalue} ), #use short-circuit operator for efficiency
                         subfield_loop    => \@subfields_data,
@@ -677,7 +708,7 @@ sub build_tabs {
 # ========================
 #          MAIN
 #=========================
-my $input = new CGI;
+my $input = CGI->new;
 my $error = $input->param('error');
 my $biblionumber  = $input->param('biblionumber'); # if biblionumber exists, it's a modif, not a new biblio.
 my $parentbiblio  = $input->param('parentbiblionumber');
@@ -687,7 +718,7 @@ my $op            = $input->param('op') // q{};
 my $mode          = $input->param('mode');
 my $frameworkcode = $input->param('frameworkcode');
 my $redirect      = $input->param('redirect');
-my $searchid      = $input->param('searchid');
+my $searchid      = $input->param('searchid') // "";
 my $dbh           = C4::Context->dbh;
 my $hostbiblionumber = $input->param('hostbiblionumber');
 my $hostitemnumber = $input->param('hostitemnumber');
@@ -714,14 +745,14 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
         template_name   => "cataloguing/addbiblio.tt",
         query           => $input,
         type            => "intranet",
-        authnotrequired => 0,
         flagsrequired   => { editcatalogue => $userflags },
     }
 );
 
+my $biblio;
 if ($biblionumber){
-    my $does_bib_exist = Koha::Biblios->find($biblionumber);
-    if (!defined $does_bib_exist){
+    $biblio = Koha::Biblios->find($biblionumber);
+    unless ( $biblio ) {
         $biblionumber = undef;
         $template->param( bib_doesnt_exist => 1 );
     }
@@ -736,11 +767,15 @@ if ($frameworkcode eq 'FA'){
         'stickyduedate'      => $fa_stickyduedate,
         'duedatespec'        => $fa_duedatespec,
     );
-} elsif ( $op ne "delete" && C4::Context->preference('EnableAdvancedCatalogingEditor') && $input->cookie( 'catalogue_editor_' . $loggedinuser ) eq 'advanced' && !$breedingid ) {
+} elsif ( $op ne "delete" &&
+            C4::Context->preference('EnableAdvancedCatalogingEditor') &&
+            C4::Auth::haspermission(C4::Context->userenv->{id},{'editcatalogue'=>'advanced_editor'}) &&
+            $input->cookie( 'catalogue_editor_' . $loggedinuser ) eq 'advanced' &&
+            !$breedingid ) {
     # Only use the advanced editor for non-fast-cataloging.
     # breedingid is not handled because those would only come off a Z39.50
     # search initiated by the basic editor.
-    print $input->redirect( '/cgi-bin/koha/cataloguing/editor.pl' . ( $biblionumber ? ( '#catalog/' . $biblionumber ) : '' ) );
+    print $input->redirect( '/cgi-bin/koha/cataloguing/editor.pl' . ( $biblionumber ? ( ($op eq 'duplicate'?'#duplicate/':'#catalog/') . $biblionumber ) : '' ) );
     exit;
 }
 
@@ -766,8 +801,8 @@ my (
        $biblioitemnumber
 );
 
-if (($biblionumber) && !($breedingid)){
-    $record = GetMarcBiblio({ biblionumber => $biblionumber });
+if ( $biblio && !$breedingid ) {
+    $record = $biblio->metadata->record;
 }
 if ($breedingid) {
     ( $record, $encoding ) = MARCfindbreeding( $breedingid ) ;
@@ -803,10 +838,10 @@ if ($biblionumber) {
 
     # if it's a modif, retrieve bibli and biblioitem numbers for the future modification of old-DB.
     ( $biblionumbertagfield, $biblionumbertagsubfield ) =
-       &GetMarcFromKohaField( "biblio.biblionumber", $frameworkcode );
+        &GetMarcFromKohaField( "biblio.biblionumber" );
     ( $biblioitemnumtagfield, $biblioitemnumtagsubfield ) =
-       &GetMarcFromKohaField( "biblioitems.biblioitemnumber", $frameworkcode );
-           
+        &GetMarcFromKohaField( "biblioitems.biblioitemnumber" );
+
     # search biblioitems value
     my $sth =  $dbh->prepare("select biblioitemnumber from biblioitems where biblionumber=?");
     $sth->execute($biblionumber);
@@ -831,11 +866,20 @@ if ( $op eq "addbiblio" ) {
     # it is not a duplicate (determined either by Koha itself or by user checking it's not a duplicate)
     if ( !$duplicatebiblionumber or $confirm_not_duplicate ) {
         my $oldbibitemnum;
-        if (C4::Context->preference("BiblioAddsAuthorities")){
-            BiblioAutoLink( $record, $frameworkcode );
-        } 
         if ( $is_a_modif ) {
-            ModBiblio( $record, $biblionumber, $frameworkcode );
+            my $member = Koha::Patrons->find($loggedinuser);
+            ModBiblio(
+                $record,
+                $biblionumber,
+                $frameworkcode,
+                {
+                    overlay_context => {
+                        source       => $z3950 ? 'z39.50' : 'intranet',
+                        categorycode => $member->categorycode,
+                        userid       => $member->userid
+                    }
+                }
+            );
         }
         else {
             ( $biblionumber, $oldbibitemnum ) = AddBiblio( $record, $frameworkcode );
@@ -918,7 +962,7 @@ elsif ( $op eq "delete" ) {
        exit;
     }
     
-    print $input->redirect('/cgi-bin/koha/catalogue/search.pl');
+    print $input->redirect('/cgi-bin/koha/catalogue/search.pl' . ($searchid ? "?searchid=$searchid" : ""));
     exit;
     
 } else {
@@ -928,6 +972,7 @@ elsif ( $op eq "delete" ) {
     $template->param(
         biblionumberdata => $biblionumber,
         op               => $op,
+        z3950            => $z3950
     );
     if ( $op eq "duplicate" ) {
         $biblionumber = "";