From f0896480e4406569d0480b0490e7c7d480ff400a Mon Sep 17 00:00:00 2001 From: Marcel de Rooy Date: Thu, 26 Jun 2025 16:23:43 +0200 Subject: [PATCH] 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 Signed-off-by: Owen Leonard --- Koha/Biblio/Metadata/Extractor/MARC/MARC21.pm | 54 +++++++++++++++++++ cataloguing/addbiblio.pl | 11 +++- .../prog/en/modules/cataloguing/addbiblio.tt | 4 ++ .../Biblio/Metadata/Extractor/MARC/MARC21.t | 40 +++++++++++++- 4 files changed, 106 insertions(+), 3 deletions(-) diff --git a/Koha/Biblio/Metadata/Extractor/MARC/MARC21.pm b/Koha/Biblio/Metadata/Extractor/MARC/MARC21.pm index 4fe7df8afe5..fc3d9fcbfc7 100644 --- a/Koha/Biblio/Metadata/Extractor/MARC/MARC21.pm +++ b/Koha/Biblio/Metadata/Extractor/MARC/MARC21.pm @@ -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, Etomascohen@theke.ioE diff --git a/cataloguing/addbiblio.pl b/cataloguing/addbiblio.pl index 58f555d6de0..627c5dcc75c 100755 --- a/cataloguing/addbiblio.pl +++ b/cataloguing/addbiblio.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/perl # Copyright 2000-2002 Katipo Communications # Copyright 2004-2010 BibLibre @@ -53,7 +53,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; @@ -833,6 +833,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, diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbiblio.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbiblio.tt index 003358530c5..fb1dff79406 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbiblio.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/addbiblio.tt @@ -805,6 +805,10 @@ [% END %] + [% IF marc21_fixlen %] +

WARNING

The following fixed-length control field(s) have an invalid length: [% marc21_fixlen.failed.join(',') | html %]. Please fix.

+ [% END %] + [% IF ( Koha.Preference('EnableAdvancedCatalogingEditor') && CAN_user_editcatalogue_advanced_editor ) %]
diff --git a/t/db_dependent/Koha/Biblio/Metadata/Extractor/MARC/MARC21.t b/t/db_dependent/Koha/Biblio/Metadata/Extractor/MARC/MARC21.t index de5c62d7f9b..32d7261a28d 100755 --- a/t/db_dependent/Koha/Biblio/Metadata/Extractor/MARC/MARC21.t +++ b/t/db_dependent/Koha/Biblio/Metadata/Extractor/MARC/MARC21.t @@ -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; +}; -- 2.39.5