From 3522dc2bca202eabde571f4e17b2fe17bd092652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Cohen=20Arazi?= Date: Fri, 8 May 2026 15:57:36 -0300 Subject: [PATCH] Bug 42567: Remove C4::Koha::GetNormalizedEAN in favor of MetadataExtractor Adds get_normalized_ean to the flavor-specific extractors: - MARC21: 024$a with indicator 1 = 3 - UNIMARC: 073$a Exposes it as $biblio->normalized_ean and migrates all callers. Assisted-by: Sonnet 4.6 (Anthropic) Test plan: 1. Apply patch 2. Run: $ ktd --shell k$ prove t/db_dependent/Koha.t \ t/db_dependent/Koha/Biblio.t \ t/db_dependent/Koha/Biblio/Metadata/Extractor/MARC/MARC21.t \ t/db_dependent/Koha/Biblio/Metadata/Extractor/MARC/UNIMARC.t => SUCCESS: Tests pass 3. Verify EAN numbers still display in OPAC and staff detail pages 4. Sign off :-D Signed-off-by: David Nind Signed-off-by: Jonathan Druart Signed-off-by: Pedro Amorim --- C4/Koha.pm | 32 ------------------- C4/Search.pm | 4 +-- C4/ShelfBrowser.pm | 4 +-- Koha/Biblio.pm | 13 ++++++++ Koha/Biblio/Metadata/Extractor/MARC/MARC21.pm | 23 +++++++++++++ .../Biblio/Metadata/Extractor/MARC/UNIMARC.pm | 22 +++++++++++++ catalogue/detail.pl | 3 +- opac/opac-ISBDdetail.pl | 3 +- opac/opac-detail.pl | 3 +- opac/opac-shelves.pl | 12 +++---- opac/opac-showreviews.pl | 5 ++- t/db_dependent/Koha.t | 6 +--- t/db_dependent/Koha/Biblio.t | 24 +++++++++++++- .../Biblio/Metadata/Extractor/MARC/MARC21.t | 30 ++++++++++++++++- .../Biblio/Metadata/Extractor/MARC/UNIMARC.t | 24 +++++++++++++- virtualshelves/shelves.pl | 3 +- 16 files changed, 149 insertions(+), 62 deletions(-) diff --git a/C4/Koha.pm b/C4/Koha.pm index 52c8b8f7c9..fbce23192e 100644 --- a/C4/Koha.pm +++ b/C4/Koha.pm @@ -34,7 +34,6 @@ BEGIN { getitemtypeimagelocation GetAuthorisedValues GetNormalizedISBN - GetNormalizedEAN xml_escape GetVariationsOfISBN @@ -639,37 +638,6 @@ sub GetNormalizedISBN { } } -=head2 GetNormalizedEAN - -Missing POD for GetNormalizedEAN. - -=cut - -sub GetNormalizedEAN { - my ( $marcrecord, $marcflavour ) = @_; - - return unless $marcrecord; - - if ( $marcflavour eq 'UNIMARC' ) { - my @fields = $marcrecord->field('073'); - foreach my $field (@fields) { - my $ean = _normalize_match_point( $field->subfield('a') ); - if ($ean) { - return $ean; - } - } - } else { # assume marc21 if not unimarc - my @fields = $marcrecord->field('024'); - foreach my $field (@fields) { - my $indicator = $field->indicator(1); - my $ean = _normalize_match_point( $field->subfield('a') ); - if ( $ean && $indicator eq '3' ) { - return $ean; - } - } - } -} - sub _normalize_match_point { my $match_point = shift; ( my $normalized_match_point ) = $match_point =~ /([\d-]*[X]*)/; diff --git a/C4/Search.pm b/C4/Search.pm index 3dc16f86f2..0ff6798617 100644 --- a/C4/Search.pm +++ b/C4/Search.pm @@ -35,7 +35,7 @@ BEGIN { use C4::Context; use C4::Biblio qw( TransformMarcToKoha GetMarcFromKohaField GetFrameworkCode GetAuthorisedValueDesc GetBiblioData ); -use C4::Koha qw( getFacets GetVariationsOfISBN GetNormalizedEAN GetNormalizedISBN getitemtypeimagelocation ); +use C4::Koha qw( getFacets GetVariationsOfISBN GetNormalizedISBN getitemtypeimagelocation ); use Koha::Biblio::Metadata::Extractor; use Koha::DateUtils; use Koha::Libraries; @@ -1770,7 +1770,7 @@ sub searchResults { my $extractor = Koha::Biblio::Metadata::Extractor->new( { metadata => $marcrecord } ); $oldbiblio->{normalized_upc} = $extractor->get_normalized_upc; - $oldbiblio->{normalized_ean} = GetNormalizedEAN( $marcrecord, $marcflavour ); + $oldbiblio->{normalized_ean} = $extractor->get_normalized_ean; $oldbiblio->{normalized_oclc} = $extractor->get_normalized_oclc; $oldbiblio->{normalized_isbn} = GetNormalizedISBN( $oldbiblio->{isbn}, $marcrecord, $marcflavour ) ; # Use existing ISBN from record if we got one diff --git a/C4/ShelfBrowser.pm b/C4/ShelfBrowser.pm index 7a6787fad9..1b7a39daa4 100644 --- a/C4/ShelfBrowser.pm +++ b/C4/ShelfBrowser.pm @@ -28,7 +28,7 @@ BEGIN { use C4::Biblio qw( GetAuthorisedValueDesc ); use C4::Context; -use C4::Koha qw( GetNormalizedISBN GetNormalizedEAN ); +use C4::Koha qw( GetNormalizedISBN ); use Koha::Biblios; use Koha::Libraries; @@ -238,7 +238,7 @@ sub GetShelfInfo { $item->{'browser_normalized_upc'} = $biblio->normalized_upc; $item->{'browser_normalized_oclc'} = $biblio->normalized_oclc; $item->{'browser_normalized_isbn'} = GetNormalizedISBN( undef, $this_record, $marcflavour ); - $item->{'browser_normalized_ean'} = GetNormalizedEAN( $this_record, $marcflavour ); + $item->{'browser_normalized_ean'} = $biblio->normalized_ean; push @valid_items, $item; } return @valid_items; diff --git a/Koha/Biblio.pm b/Koha/Biblio.pm index e08c27e231..5eef7ced80 100644 --- a/Koha/Biblio.pm +++ b/Koha/Biblio.pm @@ -1703,6 +1703,19 @@ sub normalized_upc { return $self->metadata_extractor->get_normalized_upc; } +=head3 normalized_ean + + my $normalized_ean = $biblio->normalized_ean + +Normalizes and returns the EAN found in the MARC record. + +=cut + +sub normalized_ean { + my ($self) = @_; + return $self->metadata_extractor->get_normalized_ean; +} + =head3 normalized_oclc my $normalized_oclc = $biblio->normalized_oclc diff --git a/Koha/Biblio/Metadata/Extractor/MARC/MARC21.pm b/Koha/Biblio/Metadata/Extractor/MARC/MARC21.pm index 6bcef6d28a..a87cf50b85 100644 --- a/Koha/Biblio/Metadata/Extractor/MARC/MARC21.pm +++ b/Koha/Biblio/Metadata/Extractor/MARC/MARC21.pm @@ -74,6 +74,29 @@ sub get_normalized_upc { } } +=head2 get_normalized_ean + + my $normalized_ean = $extractor->get_normalized_ean(); + +Returns a normalized EAN from 024$a with indicator 1 = 3. + +=cut + +sub get_normalized_ean { + my ($self) = @_; + + my $record = $self->metadata; + my @fields = $record->field('024'); + foreach my $field (@fields) { + my $indicator = $field->indicator(1); + my $ean = $self->_normalize_string( $field->subfield('a') ); + if ( $ean && $indicator eq '3' ) { + return $ean; + } + } + return; +} + =head2 check_fixed_length my $info = $extractor->check_fixed_length; diff --git a/Koha/Biblio/Metadata/Extractor/MARC/UNIMARC.pm b/Koha/Biblio/Metadata/Extractor/MARC/UNIMARC.pm index f4c68ec963..6ffcf8a784 100644 --- a/Koha/Biblio/Metadata/Extractor/MARC/UNIMARC.pm +++ b/Koha/Biblio/Metadata/Extractor/MARC/UNIMARC.pm @@ -72,6 +72,28 @@ sub get_normalized_upc { } } +=head2 get_normalized_ean + + my $normalized_ean = $extractor->get_normalized_ean(); + +Returns a normalized EAN from 073$a. + +=cut + +sub get_normalized_ean { + my ($self) = @_; + + my $record = $self->metadata; + my @fields = $record->field('073'); + foreach my $field (@fields) { + my $ean = $self->_normalize_string( $field->subfield('a') ); + if ($ean) { + return $ean; + } + } + return; +} + =head1 AUTHOR Tomas Cohen Arazi, Etomascohen@theke.ioE diff --git a/catalogue/detail.pl b/catalogue/detail.pl index 9fc6f3e259..93953e6dad 100755 --- a/catalogue/detail.pl +++ b/catalogue/detail.pl @@ -23,7 +23,6 @@ use C4::Context; use C4::Koha qw( GetAuthorisedValues getitemtypeimagelocation - GetNormalizedEAN GetNormalizedISBN ); use C4::Serials qw( CountSubscriptionFromBiblionumber SearchSubscriptions GetLatestSerials ); @@ -168,7 +167,7 @@ $template->param( ocoins => !$invalid_marc_record ? $biblio->get_coins : undef ) # in each case, we're grabbing the first value we find in # the record and normalizing it my $upc = $biblio->normalized_upc; -my $ean = GetNormalizedEAN( $marc_record, $marcflavour ); +my $ean = $biblio->normalized_ean; my $oclc = $biblio->normalized_oclc; my $isbn = GetNormalizedISBN( undef, $marc_record, $marcflavour ); my $content_identifier_exists; diff --git a/opac/opac-ISBDdetail.pl b/opac/opac-ISBDdetail.pl index b0a8937d3e..34e32ec1d6 100755 --- a/opac/opac-ISBDdetail.pl +++ b/opac/opac-ISBDdetail.pl @@ -54,7 +54,6 @@ use C4::Record qw( marc2cites ); use C4::Reserves qw( IsAvailableForItemLevelRequest ); use C4::Serials qw( CountSubscriptionFromBiblionumber SearchSubscriptions GetLatestSerials ); use C4::Koha qw( - GetNormalizedEAN GetNormalizedISBN ); use Koha::CirculationRules; @@ -131,7 +130,7 @@ my $marcflavour = C4::Context->preference("marcflavour"); # in each case, we're grabbing the first value we find in # the record and normalizing it my $upc = $biblio->normalized_upc; -my $ean = GetNormalizedEAN( $record, $marcflavour ); +my $ean = $extractor->get_normalized_ean; my $oclc = $extractor->get_normalized_oclc; my $isbn = GetNormalizedISBN( undef, $record, $marcflavour ); my $content_identifier_exists; diff --git a/opac/opac-detail.pl b/opac/opac-detail.pl index c298ba692c..ec9f2b7818 100755 --- a/opac/opac-detail.pl +++ b/opac/opac-detail.pl @@ -26,7 +26,6 @@ use C4::Acquisition qw( SearchOrders ); use C4::Auth qw( get_template_and_user get_session ); use C4::Koha qw( getitemtypeimagelocation - GetNormalizedEAN GetNormalizedISBN ); use C4::Search qw( new_record_from_zebra searchResults getRecords ); @@ -159,7 +158,7 @@ if ( $query->cookie("bib_list") ) { SetUTF8Flag($record); my $marcflavour = C4::Context->preference("marcflavour"); -my $ean = GetNormalizedEAN( $record, $marcflavour ); +my $ean = $biblio->normalized_ean; my $OpacBrowseResults = C4::Context->preference("OpacBrowseResults"); diff --git a/opac/opac-shelves.pl b/opac/opac-shelves.pl index 64eecc9140..436f485d62 100755 --- a/opac/opac-shelves.pl +++ b/opac/opac-shelves.pl @@ -23,7 +23,6 @@ use CGI qw ( -utf8 ); use C4::Auth qw( get_template_and_user ); use C4::Biblio qw( GetBiblioData GetFrameworkCode ); use C4::Koha qw( - GetNormalizedEAN GetNormalizedISBN ); use C4::Members; @@ -388,12 +387,11 @@ if ( $op eq 'view' ) { $this_item->{description} = $itemtype->description; #FIXME Should not it be translated_description? $this_item->{notforloan} = $itemtype->notforloan; } - $this_item->{'coins'} = $biblio->get_coins; - $this_item->{'normalized_upc'} = - Koha::Biblio::Metadata::Extractor->new( { metadata => $record } )->get_normalized_upc; - $this_item->{'normalized_ean'} = GetNormalizedEAN( $record, $marcflavour ); - $this_item->{'normalized_oclc'} = - Koha::Biblio::Metadata::Extractor->new( { metadata => $record } )->get_normalized_oclc; + my $extractor = Koha::Biblio::Metadata::Extractor->new( { metadata => $record } ); + $this_item->{'coins'} = $biblio->get_coins; + $this_item->{'normalized_upc'} = $extractor->get_normalized_upc; + $this_item->{'normalized_ean'} = $extractor->get_normalized_ean; + $this_item->{'normalized_oclc'} = $extractor->get_normalized_oclc; $this_item->{'normalized_isbn'} = GetNormalizedISBN( undef, $record, $marcflavour ); # BZ17530: 'Intelligent' guess if result can be article requested diff --git a/opac/opac-showreviews.pl b/opac/opac-showreviews.pl index ac525337ee..b318515032 100755 --- a/opac/opac-showreviews.pl +++ b/opac/opac-showreviews.pl @@ -23,7 +23,6 @@ use Modern::Perl; use CGI qw ( -utf8 ); use C4::Auth qw( get_template_and_user ); use C4::Koha qw( - GetNormalizedEAN GetNormalizedISBN ); use C4::Output qw( output_html_with_http_headers ); @@ -93,8 +92,8 @@ for my $result (@$reviews) { my $biblioitem = $biblio->biblioitem; my $record = $biblio->metadata->record; $result->{normalized_upc} = $biblio->normalized_upc; - $result->{normalized_ean} = GetNormalizedEAN( $record, $marcflavour ); - $result->{normalized_oclc} = Koha::Biblio::Metadata::Extractor->new( { metadata => $record } )->get_normalized_oclc; + $result->{normalized_ean} = $biblio->normalized_ean; + $result->{normalized_oclc} = $biblio->normalized_oclc; $result->{normalized_isbn} = GetNormalizedISBN( undef, $record, $marcflavour ); $result->{title} = $biblio->title; $result->{subtitle} = $biblio->subtitle; diff --git a/t/db_dependent/Koha.t b/t/db_dependent/Koha.t index a7311b8fd9..4d916837c5 100755 --- a/t/db_dependent/Koha.t +++ b/t/db_dependent/Koha.t @@ -173,7 +173,7 @@ subtest 'Authorized Values Tests' => sub { }; subtest 'isbn tests' => sub { - plan tests => 31; + plan tests => 30; my $isbn13 = "9780330356473"; my $isbn13D = "978-0-330-35647-3"; @@ -283,10 +283,6 @@ subtest 'isbn tests' => sub { C4::Koha::GetNormalizedISBN(), undef, 'GetNormalizedISBN should return undef if no record and no isbn are passed' ); - is( - C4::Koha::GetNormalizedEAN(), undef, - 'GetNormalizedEAN should return undef if no record and no isbn are passed' - ); is( C4::Koha::GetNormalizedISBN('979-8-88650-962-5'), '9798886509625', 'Test GetNormalizedISBN' ); diff --git a/t/db_dependent/Koha/Biblio.t b/t/db_dependent/Koha/Biblio.t index 43eba5d103..aa6e632636 100755 --- a/t/db_dependent/Koha/Biblio.t +++ b/t/db_dependent/Koha/Biblio.t @@ -18,7 +18,7 @@ use Modern::Perl; use Test::NoWarnings; -use Test::More tests => 43; +use Test::More tests => 44; use Test::Exception; use Test::Warn; @@ -2037,6 +2037,28 @@ subtest 'normalized_upc() tests' => sub { }; +subtest 'normalized_ean() tests' => sub { + plan tests => 2; + + $schema->storage->txn_begin; + + t::lib::Mocks::mock_preference( 'marcflavour', 'MARC21' ); + + my $biblio = $builder->build_sample_biblio(); + my $record = $biblio->metadata->record; + $record->append_fields( MARC::Field->new( '024', '3', ' ', a => '978-3-16-148410-0' ) ); + C4::Biblio::ModBiblio( $record, $biblio->biblionumber ); + $biblio = $biblio->get_from_storage; + + is( $biblio->normalized_ean, '9783161484100', 'normalized_ean returns EAN from 024 ind1=3' ); + + my $biblio_no_ean = $builder->build_sample_biblio(); + is( $biblio_no_ean->normalized_ean, undef, 'normalized_ean returns undef when no EAN' ); + + $schema->storage->txn_rollback; + +}; + subtest 'normalized_oclc() tests' => sub { plan tests => 2; 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 15a67931e1..9cfcf9597d 100755 --- a/t/db_dependent/Koha/Biblio/Metadata/Extractor/MARC/MARC21.t +++ b/t/db_dependent/Koha/Biblio/Metadata/Extractor/MARC/MARC21.t @@ -20,7 +20,7 @@ use Modern::Perl; use Test::NoWarnings; -use Test::More tests => 5; +use Test::More tests => 6; use Test::Exception; use t::lib::TestBuilder; @@ -140,3 +140,31 @@ subtest 'check_fixed_length' => sub { $schema->storage->txn_rollback; }; + +subtest 'get_normalized_ean() tests' => sub { + plan tests => 3; + + $schema->storage->txn_begin; + + my $record = MARC::Record->new(); + $record->append_fields( + MARC::Field->new( '024', '1', ' ', a => '123456789' ), # UPC (ind1=1), not EAN + MARC::Field->new( '024', '3', ' ', a => '978-3-16-148410-0' ), # EAN (ind1=3) + ); + + my $extractor = Koha::Biblio::Metadata::Extractor->new( { metadata => $record } ); + is( $extractor->get_normalized_ean, '9783161484100', 'EAN extracted and normalized (dashes removed)' ); + + $record = MARC::Record->new(); + $record->append_fields( + MARC::Field->new( '024', '1', ' ', a => '123456789' ), # UPC only + ); + $extractor = Koha::Biblio::Metadata::Extractor->new( { metadata => $record } ); + is( $extractor->get_normalized_ean, undef, 'Returns undef when no EAN (ind1=3) present' ); + + $record = MARC::Record->new(); + $extractor = Koha::Biblio::Metadata::Extractor->new( { metadata => $record } ); + is( $extractor->get_normalized_ean, undef, 'Returns undef for empty record' ); + + $schema->storage->txn_rollback; +}; diff --git a/t/db_dependent/Koha/Biblio/Metadata/Extractor/MARC/UNIMARC.t b/t/db_dependent/Koha/Biblio/Metadata/Extractor/MARC/UNIMARC.t index 86f2c09e57..ed7553d493 100755 --- a/t/db_dependent/Koha/Biblio/Metadata/Extractor/MARC/UNIMARC.t +++ b/t/db_dependent/Koha/Biblio/Metadata/Extractor/MARC/UNIMARC.t @@ -20,7 +20,7 @@ use Modern::Perl; use Test::NoWarnings; -use Test::More tests => 3; +use Test::More tests => 4; use Test::Exception; use t::lib::TestBuilder; @@ -76,3 +76,25 @@ subtest 'get_normalized_upc() tests' => sub { $schema->storage->txn_rollback; }; + +subtest 'get_normalized_ean() tests' => sub { + plan tests => 2; + + $schema->storage->txn_begin; + + t::lib::Mocks::mock_preference( 'marcflavour', 'UNIMARC' ); + + my $record = MARC::Record->new(); + $record->append_fields( + MARC::Field->new( '073', ' ', ' ', a => '978-2-07-036822-8' ), + ); + + my $extractor = Koha::Biblio::Metadata::Extractor::MARC->new( { metadata => $record } ); + is( $extractor->get_normalized_ean, '9782070368228', 'EAN extracted from 073$a and normalized' ); + + $record = MARC::Record->new(); + $extractor = Koha::Biblio::Metadata::Extractor::MARC->new( { metadata => $record } ); + is( $extractor->get_normalized_ean, undef, 'Returns undef for empty record' ); + + $schema->storage->txn_rollback; +}; diff --git a/virtualshelves/shelves.pl b/virtualshelves/shelves.pl index b419245612..0c680d650d 100755 --- a/virtualshelves/shelves.pl +++ b/virtualshelves/shelves.pl @@ -23,7 +23,6 @@ use C4::Auth qw( get_template_and_user haspermission ); use C4::Circulation qw( barcodedecode ); use C4::Context; use C4::Koha qw( - GetNormalizedEAN GetNormalizedISBN ); use C4::Members; @@ -352,7 +351,7 @@ if ( $op eq 'view' ) { $this_item->{notforloan} = $itemtype->notforloan if $itemtype; $this_item->{'coins'} = $biblio->get_coins; $this_item->{'normalized_upc'} = $biblio->normalized_upc; - $this_item->{'normalized_ean'} = GetNormalizedEAN( $record, $marcflavour ); + $this_item->{'normalized_ean'} = $biblio->normalized_ean; $this_item->{'normalized_oclc'} = $biblio->normalized_oclc; $this_item->{'normalized_isbn'} = GetNormalizedISBN( undef, $record, $marcflavour );