return ( $authid );
}
-
=head2 DelAuthority
- $authid= &DelAuthority($authid)
+ $authid = DelAuthority( $authid )
-Deletes $authid
+Deletes $authid and calls merge to cleanup in linked biblio records
=cut
my ($authid) = @_;
my $dbh=C4::Context->dbh;
+ unless( C4::Context->preference('dontmerge') eq '1' ) {
+ &merge( $authid, GetAuthority($authid) );
+ } else {
+ # save a record in need_merge_authorities table
+ my $sqlinsert="INSERT INTO need_merge_authorities (authid, done) VALUES (?,?)";
+ $dbh->do( $sqlinsert, undef, $authid, 0 );
+ }
+ $dbh->do( "DELETE FROM auth_header WHERE authid=?", undef, $authid );
logaction( "AUTHORITIES", "DELETE", $authid, "authority" ) if C4::Context->preference("AuthoritiesLog");
- ModZebra($authid,"recordDelete","authorityserver",GetAuthority($authid),undef);
- my $sth = $dbh->prepare("DELETE FROM auth_header WHERE authid=?");
- $sth->execute($authid);
+ ModZebra( $authid, "recordDelete", "authorityserver", undef);
}
=head2 ModAuthority
=head2 merge
- $ref= &merge(mergefrom,$MARCfrom,$mergeto,$MARCto)
+ $count = merge ( mergefrom, $MARCfrom, [$mergeto, $MARCto] )
+
+Merge biblios linked to authority $mergefrom.
+If $mergeto equals mergefrom, the linked biblio field is updated.
+If $mergeto is different, the biblio field will be linked to $mergeto.
+If $mergeto is missing, the biblio field is deleted.
-Could add some feature : Migrating from a typecode to an other for instance.
-Then we should add some new parameter : bibliotargettag, authtargettag
+Note: Although $mergefrom and $mergeto will normally be of the same
+authority type, merge also supports moving to another authority type.
=cut
sub merge {
my ($mergefrom,$MARCfrom,$mergeto,$MARCto) = @_;
+ return 0 unless $mergefrom > 0; # prevent abuse
my ($counteditedbiblio,$countunmodifiedbiblio,$counterrors)=(0,0,0);
my $dbh=C4::Context->dbh;
my $authfrom = Koha::Authorities->find($mergefrom);
my $authto = Koha::Authorities->find($mergeto);
- my $authtypefrom = Koha::Authority::Types->find($authfrom->authtypecode);
- my $authtypeto = Koha::Authority::Types->find($authto->authtypecode);
+ my $authtypefrom = $authfrom ? Koha::Authority::Types->find($authfrom->authtypecode) : undef;
+ my $authtypeto = $authto ? Koha::Authority::Types->find($authto->authtypecode) : undef;
- return "error MARCFROM not a marcrecord ".Data::Dumper::Dumper($MARCfrom) if scalar($MARCfrom->fields()) == 0;
- return "error MARCTO not a marcrecord".Data::Dumper::Dumper($MARCto) if scalar($MARCto->fields()) == 0;
# search the tag to report
- my $auth_tag_to_report_from = $authtypefrom->auth_tag_to_report;
- my $auth_tag_to_report_to = $authtypeto->auth_tag_to_report;
+ my $auth_tag_to_report_from = $authtypefrom ? $authtypefrom->auth_tag_to_report : '';
+ my $auth_tag_to_report_to = $authtypeto ? $authtypeto->auth_tag_to_report : '';
my @record_to;
- @record_to = $MARCto->field($auth_tag_to_report_to)->subfields() if $MARCto->field($auth_tag_to_report_to);
+ @record_to = $MARCto->field($auth_tag_to_report_to)->subfields() if $auth_tag_to_report_to && $MARCto && $MARCto->field($auth_tag_to_report_to);
my @record_from;
- @record_from = $MARCfrom->field($auth_tag_to_report_from)->subfields() if $MARCfrom->field($auth_tag_to_report_from);
+ @record_from = $MARCfrom->field($auth_tag_to_report_from)->subfields() if $auth_tag_to_report_from && $MARCfrom && $MARCfrom->field($auth_tag_to_report_from);
my @reccache;
# search all biblio tags using this authority.
$oResult->destroy();
# Get All candidate Tags for the change
# (This will reduce the search scope in marc records).
+ # For a deleted authority record, we scan all auth controlled fields
my $sql = "SELECT DISTINCT tagfield FROM marc_subfield_structure WHERE authtypecode=?";
- my $tags_using_authtype = $dbh->selectcol_arrayref( $sql, undef, ( $authtypefrom->authtypecode ));
+ 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<>''" );
my $tags_new;
- if ($authtypeto->authtypecode ne $authtypefrom->authtypecode){
+ if( $authtypefrom && $authtypeto && $authtypeto->authtypecode ne $authtypefrom->authtypecode ) {
$tags_new = $dbh->selectcol_arrayref( $sql, undef, ( $authtypeto->authtypecode ));
}
my $tag = $field->tag();
next if !defined($auth_number) || $auth_number ne $mergefrom;
$countfrom++;
- if ( $overwrite && $countfrom > 1 ) {
- # remove this duplicate in strict mode
+ if ( !$mergeto || ( $overwrite && $countfrom > 1 ) ) {
+ # if mergeto is missing, this indicates a delete
+ # Or: remove this duplicate in strict mode
$marcrecord->delete_field($field);
$update = 1;
next;
};
subtest 'Merging authorities should handle deletes (BZ 18070)' => sub {
- plan tests => 1;
+ plan tests => 2;
+
+ # For this test we need dontmerge OFF
+ t::lib::Mocks::mock_preference('dontmerge', '0');
# Add authority and linked biblio, delete authority
my $auth1 = MARC::Record->new;
MARC::Field->new( '609', '', '', a => 'DEL', 9 => "$authid1" ),
);
my ( $biblionumber ) = C4::Biblio::AddBiblio( $bib1, '' );
- DelAuthority( $authid1 );
+ @zebrarecords = ( $bib1 );
+ $index = 0;
+ DelAuthority( $authid1 ); # this triggers a merge call
- # See what happened
+ # See what happened in the biblio record
my $marc1 = C4::Biblio::GetMarcBiblio( $biblionumber );
is( $marc1->field('609'), undef, 'Field 609 should be gone too' );
+
+ # Now we simulate the delete as done from the cron job (with dontmerge)
+ # First, restore auth1 and add 609 back in bib1
+ $auth1 = MARC::Record->new;
+ $auth1->append_fields( MARC::Field->new( '109', '', '', 'a' => 'DEL'));
+ $authid1 = AddAuthority( $auth1, undef, $authtype1 );
+ $marc1->append_fields(
+ MARC::Field->new( '609', '', '', a => 'DEL', 9 => "$authid1" ),
+ );
+ ModBiblio( $marc1, $biblionumber, '' );
+ # Instead of going through DelAuthority, we manually delete the auth
+ # record and call merge afterwards.
+ # This mimics deleting an authority and calling merge later in the
+ # merge_authority.pl cron job (when dontmerge is enabled).
+ C4::Context->dbh->do( "DELETE FROM auth_header WHERE authid=?", undef, $authid1 );
+ @zebrarecords = ( $marc1 );
+ $index = 0;
+ merge( $authid1, undef );
+ # Final check
+ $marc1 = C4::Biblio::GetMarcBiblio( $biblionumber );
+ is( $marc1->field('609'), undef, 'Merge removed the 609 again even after deleting the authority record' );
};
sub set_mocks {