Bug 42032: (follow-up) Eliminate phantom indicator diffs on authority MODIFY
Authority MODIFY action log diffs were emitting bogus entries for every
field with a default ' ' indicator on every save, producing output like:
_marc.fields.1.040.ind1 ' ' ' '
_marc.fields.1.040.ind2 ' ' ' '
_marc.fields.2.150.ind1 ' ' ' '
_marc.fields.3.667.ind1 ' ' ' '
...
even when only a single subfield was edited.
Root cause: Struct::Diff treats a utf8-flagged ' ' as different from a
non-utf8 ' ' SV, even though Perl's eq returns true. ModAuthority was
sourcing the two sides of the diff from different parse paths:
- $oldrecord = GetAuthority($authid)
-> MARC::Record->new_from_xml(...) -> indicators arrive utf8-flagged
- $record (the "after" side) was the in-memory MARC built by the
editor from CGI parameters -> indicators are bare byte strings
The XML round-trip through AddAuthority normalises the stored copy, but
the in-memory $record we passed to logaction had not been re-parsed, so
every default indicator looked like a change to Struct::Diff.
Fix: after AddAuthority commits the new state, re-read it via
$new_authority->record and pass that to _authority_log_data. Both sides
of the diff now traverse the same new_from_xml path, utf8 flags match,
and Struct::Diff falls silent on unchanged indicators.
This is the symmetric counterpart of how biblios already work in
C4::Biblio: ModBiblio sources both $original_marc and $updated_marc_log
through Koha::Biblio::Metadata::record_strip_nonxml (which also calls
new_from_xml), so biblios don't hit this.
The deeper asymmetry between in-memory editor MARC and stored MARC
(default indicators only get normalised on the XML round-trip) is left
for a separate bug; this patch keeps the action log diff clean without
touching the storage path.
Test plan:
1. prove t/db_dependent/AuthoritiesMarc.t
2. Enable AuthoritiesLog. Edit any authority via the staff UI making a
single subfield change. Open Tools -> Log viewer for that authority
and verify the diff column lists only the changed subfield (plus the
005 timestamp), with no rows for ind1/ind2 of untouched fields.
3. Re-run the same edit a second time changing nothing else; the diff
should again be limited to 005 + the touched subfield.
Signed-off-by: Lisette Scheer <lisette@bywatersolutions.com>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This commit is contained in:
parent
9836498611
commit
4cead7f389
|
|
@ -821,9 +821,16 @@ sub ModAuthority {
|
|||
|
||||
if ( C4::Context->preference("AuthoritiesLog") ) {
|
||||
my $new_authority = Koha::Authorities->find($authid);
|
||||
|
||||
# Re-read the stored MARC so both sides of the diff come from the
|
||||
# same XML parse path. The in-memory $record carries non-utf8 SVs
|
||||
# for default indicators while GetAuthority/->record go through
|
||||
# MARC::Record->new_from_xml which utf8-flags them; Struct::Diff
|
||||
# treats those as different and emits phantom indicator entries.
|
||||
my $new_record = eval { $new_authority->record } // $record;
|
||||
logaction(
|
||||
"AUTHORITIES", "MODIFY", $authid,
|
||||
_authority_log_data( $new_authority, $record ),
|
||||
_authority_log_data( $new_authority, $new_record ),
|
||||
undef, $original_data
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -402,7 +402,7 @@ subtest 'DelAuthority() tests' => sub {
|
|||
};
|
||||
|
||||
subtest 'Authority action logs include MARC-in-JSON diff' => sub {
|
||||
plan tests => 23;
|
||||
plan tests => 25;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
|
|
@ -412,7 +412,10 @@ subtest 'Authority action logs include MARC-in-JSON diff' => sub {
|
|||
|
||||
# --- ADD ---
|
||||
my $add_record = MARC::Record->new;
|
||||
$add_record->add_fields( [ '151', ' ', ' ', a => 'France' ] );
|
||||
$add_record->add_fields(
|
||||
[ '151', ' ', ' ', a => 'France' ],
|
||||
[ '670', ' ', ' ', a => 'Source note' ],
|
||||
);
|
||||
my $auth_id = AddAuthority( $add_record, undef, $auth_type );
|
||||
|
||||
my $add_log = Koha::ActionLogs->search( { object => $auth_id, module => 'AUTHORITIES', action => 'ADD' } )->next;
|
||||
|
|
@ -437,8 +440,16 @@ subtest 'Authority action logs include MARC-in-JSON diff' => sub {
|
|||
ok( !exists $add_diff->{D}{authtrees}, 'MARC-derived authtrees column absent from diff' );
|
||||
|
||||
# --- MODIFY ---
|
||||
# Indicators below are bare ASCII strings (not utf8-flagged), as a CGI
|
||||
# form would supply them. The stored MARC, once re-read via
|
||||
# MARC::Record->new_from_xml, comes back utf8-flagged. Without the
|
||||
# symmetric-reload in ModAuthority, Struct::Diff would emit phantom
|
||||
# entries for every unchanged indicator.
|
||||
my $mod_record = MARC::Record->new;
|
||||
$mod_record->add_fields( [ '151', ' ', ' ', a => 'France (updated)' ] );
|
||||
$mod_record->add_fields(
|
||||
[ '151', ' ', ' ', a => 'France (updated)' ],
|
||||
[ '670', ' ', ' ', a => 'Source note' ],
|
||||
);
|
||||
ModAuthority( $auth_id, $mod_record, $auth_type, { skip_merge => 1 } );
|
||||
|
||||
my $mod_log = Koha::ActionLogs->search( { object => $auth_id, module => 'AUTHORITIES', action => 'MODIFY' } )->next;
|
||||
|
|
@ -456,6 +467,25 @@ subtest 'Authority action logs include MARC-in-JSON diff' => sub {
|
|||
like( $mod_log->diff, qr/France/, 'MODIFY: diff captures before value' );
|
||||
like( $mod_log->diff, qr/France.*updated/s, 'MODIFY: diff captures after value' );
|
||||
|
||||
my @changed_tags;
|
||||
for my $field_entry ( @{ $mod_diff->{D}{_marc}{D}{fields}{D} || [] } ) {
|
||||
next unless ref $field_entry->{D} eq 'HASH';
|
||||
push @changed_tags, keys %{ $field_entry->{D} };
|
||||
}
|
||||
|
||||
# 005 (timestamp) updates on every save and is expected; 151 is the
|
||||
# field we actually edited. Anything else is a phantom (typically
|
||||
# ind1/ind2 utf8-flag mismatches on untouched fields).
|
||||
my @phantom_tags = grep { $_ ne '005' && $_ ne '151' } @changed_tags;
|
||||
is_deeply(
|
||||
[ sort @phantom_tags ], [],
|
||||
'MODIFY: untouched fields produce no phantom diff entries'
|
||||
);
|
||||
unlike(
|
||||
$mod_log->diff, qr/Source note/,
|
||||
'MODIFY: untouched 670 field absent from diff'
|
||||
);
|
||||
|
||||
# --- DELETE ---
|
||||
DelAuthority( { authid => $auth_id, skip_merge => 1 } );
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue