Bug 40272: Add an alert for bad fixed-length control fields

Development wise it is much simpler to do this check in perl when
opening the editor than getting this logic into the template with
javascript. Furthermore, older data may be corrupted, but we trust
the current plugins to not insert such fields anymore.

Test plan:
Run t/db_dependent/Koha/Biblio/Metadata/Extractor/MARC/MARC21.t
Open an existing record in the basic editor. Shorten 008 without plugin.
Save and open the record again. Do you get the alert?

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Signed-off-by: Owen Leonard <oleonard@myacpl.org>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This commit is contained in:
Marcel de Rooy 2025-06-26 16:23:43 +02:00 committed by Lucas Gass
parent bfdb2cb4b0
commit 2c8ba37c0d
No known key found for this signature in database
GPG Key ID: 60B447398B0D36CA
4 changed files with 106 additions and 3 deletions

View File

@ -96,6 +96,60 @@ sub get_normalized_oclc {
}
}
=head2 check_fixed_length
my $info = $extractor->check_fixed_length;
Returns a hash containing passed and failed fixed-length control fields.
=cut
sub check_fixed_length {
my $self = shift;
my $len_ok = {
'005' => 16,
'006' => 18,
'007' => {
a => 8,
c => [ 6, 14 ],
d => 6,
f => 10,
g => 9,
h => 13,
k => 6,
m => [ 8, 23 ],
o => 2,
q => 2,
r => 11,
s => 14,
t => 2,
v => 9,
z => 2,
},
'008' => 40,
};
my $record = $self->metadata;
my $result = { passed => [], failed => [] };
foreach my $field ( $record->field( '005', '006', '007', '008' ) ) {
my ( $length, $pass );
if ( $field->tag ne '007' ) {
$length = $len_ok->{ $field->tag };
$pass = length( $field->data ) eq $length;
} else {
my $pos_0 = substr( $field->data, 0, 1 );
$length = $len_ok->{ $field->tag }->{$pos_0};
if ( ref($length) eq 'ARRAY' ) {
$pass = grep { $_ eq length( $field->data ) } @$length;
} else {
$pass = length( $field->data ) eq $length;
}
}
push @{ $result->{passed} }, $field->tag if $pass;
push @{ $result->{failed} }, $field->tag unless $pass;
}
return $result;
}
=head1 AUTHOR
Tomas Cohen Arazi, E<lt>tomascohen@theke.ioE<gt>

View File

@ -1,4 +1,4 @@
#!/usr/bin/perl
#!/usr/bin/perl
# Copyright 2000-2002 Katipo Communications
# Copyright 2004-2010 BibLibre
@ -52,7 +52,7 @@ use Koha::Biblios;
use Koha::ItemTypes;
use Koha::Libraries;
use Koha::BiblioFrameworks;
use Koha::Biblio::Metadata::Extractor::MARC::MARC21;
use Koha::Patrons;
use Koha::UI::Form::Builder::Biblio;
@ -834,6 +834,13 @@ if ( $op eq "cud-addbiblio" ) {
#----------------------------------------------------------------------------
# If we're in a duplication case, we have to set to "" the biblionumber
# as we'll save the biblio as a new one.
if ( C4::Context->preference('marcflavour') eq 'MARC21' ) {
my $fixed_length_info =
Koha::Biblio::Metadata::Extractor::MARC::MARC21->new( { biblio => $biblio } )->check_fixed_length;
$template->param( marc21_fixlen => $fixed_length_info ) if @{ $fixed_length_info->{failed} };
}
$template->param(
biblionumberdata => $biblionumber,
op => $op,

View File

@ -805,6 +805,10 @@
</div>
[% END %]
[% IF marc21_fixlen %]
<div class="alert alert-warning"><h1>WARNING</h1><p>The following fixed-length control field(s) have an invalid length: [% marc21_fixlen.failed.join(',') | html %]. Please fix.</p></div>
[% END %]
[% IF ( Koha.Preference('EnableAdvancedCatalogingEditor') && CAN_user_editcatalogue_advanced_editor ) %]
<div id="toggle-editor">
<label for="toggle-editor">Advanced editor: </label>

View File

@ -20,13 +20,15 @@
use Modern::Perl;
use Test::NoWarnings;
use Test::More tests => 4;
use Test::More tests => 5;
use Test::Exception;
use t::lib::TestBuilder;
use t::lib::Mocks;
use C4::Biblio qw(ModBiblio);
use Koha::Biblio::Metadata::Extractor;
use Koha::Biblio::Metadata::Extractor::MARC::MARC21;
my $schema = Koha::Database->schema;
my $builder = t::lib::TestBuilder->new;
@ -87,3 +89,39 @@ subtest 'get_normalized_oclc() tests' => sub {
is( $extractor->get_normalized_oclc, "" );
};
subtest 'check_fixed_length' => sub {
plan tests => 6;
$schema->storage->txn_begin;
my $record = MARC::Record->new;
$record->append_fields(
MARC::Field->new( '005', '0123456789012345' ),
);
my $biblio = $builder->build_sample_biblio;
ModBiblio( $record, $biblio->biblionumber );
my $extractor;
$extractor = Koha::Biblio::Metadata::Extractor::MARC::MARC21->new( { biblio => $biblio } );
my $result = $extractor->check_fixed_length;
is( $result->{passed}->[0], '005', 'Check first passed field' );
is( scalar @{ $result->{failed} }, 0, 'Check failed count' );
$record->append_fields(
MARC::Field->new( '006', '01234567890123456789' ), # too long
MARC::Field->new( '007', 'a1234567' ),
MARC::Field->new( '007', 'm12345678' ), # should be 8 or 23
MARC::Field->new( '007', 'm1234567890123456789012' ),
);
# Passing latest record changes via metadata now
$extractor = Koha::Biblio::Metadata::Extractor::MARC::MARC21->new( { metadata => $record } );
$result = $extractor->check_fixed_length;
is( $result->{passed}->[1], '007', 'Check second passed field' );
is( $result->{passed}->[2], '007', 'Check third passed field' );
is( $result->{failed}->[0], '006', 'Check first failed field' );
is( $result->{failed}->[1], '007', 'Check second failed field' );
$schema->storage->txn_rollback;
};