View | Details | Raw Unified | Return to bug 14026
Collapse All | Expand All

(-)a/C4/AuthoritiesMarc.pm (-21 / +32 lines)
Lines 680-691 sub AddAuthority { Link Here
680
    return ( $authid );
680
    return ( $authid );
681
}
681
}
682
682
683
684
=head2 DelAuthority
683
=head2 DelAuthority
685
684
686
  $authid= &DelAuthority($authid)
685
  $authid = DelAuthority( $authid )
687
686
688
Deletes $authid
687
Deletes $authid and calls merge to cleanup in linked biblio records
689
688
690
=cut
689
=cut
691
690
Lines 693-702 sub DelAuthority { Link Here
693
    my ($authid) = @_;
692
    my ($authid) = @_;
694
    my $dbh=C4::Context->dbh;
693
    my $dbh=C4::Context->dbh;
695
694
695
    unless( C4::Context->preference('dontmerge') eq '1' ) {
696
        &merge( $authid, GetAuthority($authid) );
697
    } else {
698
        # save a record in need_merge_authorities table
699
        my $sqlinsert="INSERT INTO need_merge_authorities (authid, done) VALUES (?,?)";
700
        $dbh->do( $sqlinsert, undef, $authid, 0 );
701
    }
702
    $dbh->do( "DELETE FROM auth_header WHERE authid=?", undef, $authid );
696
    logaction( "AUTHORITIES", "DELETE", $authid, "authority" ) if C4::Context->preference("AuthoritiesLog");
703
    logaction( "AUTHORITIES", "DELETE", $authid, "authority" ) if C4::Context->preference("AuthoritiesLog");
697
    ModZebra($authid,"recordDelete","authorityserver",GetAuthority($authid),undef);
704
    ModZebra( $authid, "recordDelete", "authorityserver", undef);
698
    my $sth = $dbh->prepare("DELETE FROM auth_header WHERE authid=?");
699
    $sth->execute($authid);
700
}
705
}
701
706
702
=head2 ModAuthority
707
=head2 ModAuthority
Lines 1382-1413 sub AddAuthorityTrees{ Link Here
1382
1387
1383
=head2 merge
1388
=head2 merge
1384
1389
1385
  $ref= &merge(mergefrom,$MARCfrom,$mergeto,$MARCto)
1390
  $count = merge ( mergefrom, $MARCfrom, [$mergeto, $MARCto] )
1391
1392
Merge biblios linked to authority $mergefrom.
1393
If $mergeto equals mergefrom, the linked biblio field is updated.
1394
If $mergeto is different, the biblio field will be linked to $mergeto.
1395
If $mergeto is missing, the biblio field is deleted.
1386
1396
1387
Could add some feature : Migrating from a typecode to an other for instance.
1397
Note: Although $mergefrom and $mergeto will normally be of the same
1388
Then we should add some new parameter : bibliotargettag, authtargettag
1398
authority type, merge also supports moving to another authority type.
1389
1399
1390
=cut
1400
=cut
1391
1401
1392
sub merge {
1402
sub merge {
1393
    my ($mergefrom,$MARCfrom,$mergeto,$MARCto) = @_;
1403
    my ($mergefrom,$MARCfrom,$mergeto,$MARCto) = @_;
1404
    return 0 unless $mergefrom > 0; # prevent abuse
1394
    my ($counteditedbiblio,$countunmodifiedbiblio,$counterrors)=(0,0,0);        
1405
    my ($counteditedbiblio,$countunmodifiedbiblio,$counterrors)=(0,0,0);        
1395
    my $dbh=C4::Context->dbh;
1406
    my $dbh=C4::Context->dbh;
1396
    my $authfrom = Koha::Authorities->find($mergefrom);
1407
    my $authfrom = Koha::Authorities->find($mergefrom);
1397
    my $authto = Koha::Authorities->find($mergeto);
1408
    my $authto = Koha::Authorities->find($mergeto);
1398
    my $authtypefrom = Koha::Authority::Types->find($authfrom->authtypecode);
1409
    my $authtypefrom = $authfrom ? Koha::Authority::Types->find($authfrom->authtypecode) : undef;
1399
    my $authtypeto   = Koha::Authority::Types->find($authto->authtypecode);
1410
    my $authtypeto   = $authto ? Koha::Authority::Types->find($authto->authtypecode) : undef;
1400
1411
1401
    return "error MARCFROM not a marcrecord ".Data::Dumper::Dumper($MARCfrom) if scalar($MARCfrom->fields()) == 0;
1402
    return "error MARCTO not a marcrecord".Data::Dumper::Dumper($MARCto) if scalar($MARCto->fields()) == 0;
1403
    # search the tag to report
1412
    # search the tag to report
1404
    my $auth_tag_to_report_from = $authtypefrom->auth_tag_to_report;
1413
    my $auth_tag_to_report_from = $authtypefrom ? $authtypefrom->auth_tag_to_report : '';
1405
    my $auth_tag_to_report_to   = $authtypeto->auth_tag_to_report;
1414
    my $auth_tag_to_report_to   = $authtypeto ? $authtypeto->auth_tag_to_report : '';
1406
1415
1407
    my @record_to;
1416
    my @record_to;
1408
    @record_to = $MARCto->field($auth_tag_to_report_to)->subfields() if $MARCto->field($auth_tag_to_report_to);
1417
    @record_to = $MARCto->field($auth_tag_to_report_to)->subfields() if $auth_tag_to_report_to && $MARCto && $MARCto->field($auth_tag_to_report_to);
1409
    my @record_from;
1418
    my @record_from;
1410
    @record_from = $MARCfrom->field($auth_tag_to_report_from)->subfields() if $MARCfrom->field($auth_tag_to_report_from);
1419
    @record_from = $MARCfrom->field($auth_tag_to_report_from)->subfields() if $auth_tag_to_report_from && $MARCfrom && $MARCfrom->field($auth_tag_to_report_from);
1411
    
1420
    
1412
    my @reccache;
1421
    my @reccache;
1413
    # search all biblio tags using this authority.
1422
    # search all biblio tags using this authority.
Lines 1440-1449 sub merge { Link Here
1440
    $oResult->destroy();
1449
    $oResult->destroy();
1441
    # Get All candidate Tags for the change 
1450
    # Get All candidate Tags for the change 
1442
    # (This will reduce the search scope in marc records).
1451
    # (This will reduce the search scope in marc records).
1452
    # For a deleted authority record, we scan all auth controlled fields
1443
    my $sql = "SELECT DISTINCT tagfield FROM marc_subfield_structure WHERE authtypecode=?";
1453
    my $sql = "SELECT DISTINCT tagfield FROM marc_subfield_structure WHERE authtypecode=?";
1444
    my $tags_using_authtype = $dbh->selectcol_arrayref( $sql, undef, ( $authtypefrom->authtypecode ));
1454
    my $tags_using_authtype = $authtypefrom ? $dbh->selectcol_arrayref( $sql, undef, ( $authtypefrom->authtypecode )) : $dbh->selectcol_arrayref( "SELECT DISTINCT tagfield FROM marc_subfield_structure WHERE authtypecode IS NOT NULL AND authtypecode<>''" );
1445
    my $tags_new;
1455
    my $tags_new;
1446
    if ($authtypeto->authtypecode ne $authtypefrom->authtypecode){
1456
    if( $authtypefrom && $authtypeto && $authtypeto->authtypecode ne $authtypefrom->authtypecode ) {
1447
        $tags_new = $dbh->selectcol_arrayref( $sql, undef, ( $authtypeto->authtypecode ));
1457
        $tags_new = $dbh->selectcol_arrayref( $sql, undef, ( $authtypeto->authtypecode ));
1448
    }  
1458
    }  
1449
1459
Lines 1466-1473 sub merge { Link Here
1466
                my $tag         = $field->tag();
1476
                my $tag         = $field->tag();
1467
                next if !defined($auth_number) || $auth_number ne $mergefrom;
1477
                next if !defined($auth_number) || $auth_number ne $mergefrom;
1468
                $countfrom++;
1478
                $countfrom++;
1469
                if ( $overwrite && $countfrom > 1 ) {
1479
                if ( !$mergeto || ( $overwrite && $countfrom > 1 ) ) {
1470
                    # remove this duplicate in strict mode
1480
                    # if mergeto is missing, this indicates a delete
1481
                    # Or: remove this duplicate in strict mode
1471
                    $marcrecord->delete_field($field);
1482
                    $marcrecord->delete_field($field);
1472
                    $update = 1;
1483
                    $update = 1;
1473
                    next;
1484
                    next;
(-)a/misc/migration_tools/merge_authority.pl (-3 / +6 lines)
Lines 84-92 if ($batch) { Link Here
84
  foreach(@$authref) {
84
  foreach(@$authref) {
85
      my $authid=$_->[0];
85
      my $authid=$_->[0];
86
      print "managing $authid\n" if $verbose;
86
      print "managing $authid\n" if $verbose;
87
      my $MARCauth = GetAuthority($authid) ;
87
      my $MARCauth = GetAuthority( $authid );
88
      next unless ($MARCauth);
88
      if( $MARCauth ) {
89
      merge($authid,$MARCauth,$authid,$MARCauth) if ($MARCauth);
89
          merge( $authid, $MARCauth, $authid, $MARCauth );
90
      } else {
91
          merge( $authid, undef ); # handle a delete
92
      }
90
  }
93
  }
91
  $dbh->do("update need_merge_authorities set done=1 where done=2"); #DONE
94
  $dbh->do("update need_merge_authorities set done=1 where done=2"); #DONE
92
} else {
95
} else {
(-)a/t/db_dependent/Authorities/Merge.t (-6 / +30 lines)
Lines 217-223 subtest 'Test merge A1 to B1 (changing authtype)' => sub { Link Here
217
};
217
};
218
218
219
subtest 'Merging authorities should handle deletes (BZ 14026)' => sub {
219
subtest 'Merging authorities should handle deletes (BZ 14026)' => sub {
220
    plan tests => 1;
220
    plan tests => 2;
221
222
    # For this test we need dontmerge OFF
223
    t::lib::Mocks::mock_preference('dontmerge', '0');
221
224
222
    # Add authority and linked biblio, delete authority
225
    # Add authority and linked biblio, delete authority
223
    my $auth1 = MARC::Record->new;
226
    my $auth1 = MARC::Record->new;
Lines 229-240 subtest 'Merging authorities should handle deletes (BZ 14026)' => sub { Link Here
229
        MARC::Field->new( '609', '', '', a => 'DEL', 9 => "$authid1" ),
232
        MARC::Field->new( '609', '', '', a => 'DEL', 9 => "$authid1" ),
230
    );
233
    );
231
    my ( $biblionumber ) = C4::Biblio::AddBiblio( $bib1, '' );
234
    my ( $biblionumber ) = C4::Biblio::AddBiblio( $bib1, '' );
232
    DelAuthority( $authid1 );
235
    @zebrarecords = ( $bib1 );
236
    $index = 0;
237
    DelAuthority( $authid1 ); # this triggers a merge call
233
238
234
    # See what happened
239
    # See what happened in the biblio record
235
    my $marc1 = C4::Biblio::GetMarcBiblio( $biblionumber );
240
    my $marc1 = C4::Biblio::GetMarcBiblio( $biblionumber );
236
    is( $marc1->field('609') && $marc1->field('609')->subfield('9'),
241
    is( $marc1->field('609'), undef, 'Merge should have removed the 609' );
237
        $authid1, 'FIXME: Merge should be called to remove this subfield' );
242
243
    # Now we simulate the delete as done from the cron job (with dontmerge)
244
    # First, restore auth1 and add 609 back in bib1
245
    $auth1 = MARC::Record->new;
246
    $auth1->append_fields( MARC::Field->new( '109', '', '', 'a' => 'DEL'));
247
    $authid1 = AddAuthority( $auth1, undef, $authtype1 );
248
    $marc1->append_fields(
249
        MARC::Field->new( '609', '', '', a => 'DEL', 9 => "$authid1" ),
250
    );
251
    ModBiblio( $marc1, $biblionumber, '' );
252
    # Instead of going through DelAuthority, we manually delete the auth
253
    # record and call merge afterwards.
254
    # This mimics deleting an authority and calling merge later in the
255
    # merge_authority.pl cron job (when dontmerge is enabled).
256
    C4::Context->dbh->do( "DELETE FROM auth_header WHERE authid=?", undef, $authid1 );
257
    @zebrarecords = ( $marc1 );
258
    $index = 0;
259
    merge( $authid1, undef );
260
    # Final check
261
    $marc1 = C4::Biblio::GetMarcBiblio( $biblionumber );
262
    is( $marc1->field('609'), undef, 'Merge removed the 609 again even after deleting the authority record' );
238
};
263
};
239
264
240
sub set_mocks {
265
sub set_mocks {
241
- 

Return to bug 14026