diff --git a/C4/Biblio.pm b/C4/Biblio.pm index 5ddd7c7272..ac35b38777 100644 --- a/C4/Biblio.pm +++ b/C4/Biblio.pm @@ -824,8 +824,11 @@ sub LinkBibHeadingsToAuthorities { # thesaurus instead of relying on AddAuthority()'s LCSH-only default. # AddAuthority() only defaults 008/040 when they aren't already present # on the record, so pre-populating them here is sufficient - no change - # to AddAuthority() itself is needed. - if ( $heading->{thesaurus} ) { + # to AddAuthority() itself is needed. Skip this when the heading's + # thesaurus couldn't actually be identified (bug 31925 comment 30) - in + # that case the site's own MARCAuthorityControlField008 default should + # apply, the same as it always has, rather than being overridden. + if ( Koha::Authority->has_known_thesaurus( $heading->{thesaurus} ) ) { my $date = POSIX::strftime( '%y%m%d', localtime ); $marcrecordauth->insert_fields_ordered( MARC::Field->new( diff --git a/Koha/Authority.pm b/Koha/Authority.pm index d3f76ff106..b932ca250c 100644 --- a/Koha/Authority.pm +++ b/Koha/Authority.pm @@ -324,6 +324,41 @@ our $MARC21_THESAURUS_TO_CONTROL_FIELD_008_11 = { notspecified => '|', }; +# The subset of $MARC21_THESAURUS_TO_CONTROL_FIELD_008_11 keys that +# C4::Heading uses to mean "no specific thesaurus could be identified from +# the source heading's indicators" (a blank/unrecognised indicator 2, or +# indicator 2 = 4), rather than a genuine, named thesaurus. Kept private - +# callers should go through has_known_thesaurus() rather than consulting +# this directly. +my $UNDEFINED_THESAURUS_VALUES = { + notdefined => 1, + notspecified => 1, +}; + +=head3 has_known_thesaurus + + if ( Koha::Authority->has_known_thesaurus($thesaurus) ) { ... } + +Returns true if C<$thesaurus> (as derived by C4::Heading from MARC +indicator 2 / subfield $2, e.g. 'lcsh', 'mesh', or a raw $2 code such as +'fast') identifies an actual thesaurus. Returns false if C<$thesaurus> is +undefined, or is one of the placeholder values C4::Heading returns when +no thesaurus could be identified from the source heading's indicators +('notdefined', 'notspecified'). + +Callers that want to code a new authority's 008/11 (and 040$f) from a +heading's thesaurus should check this first, and leave the site's own +default (I) in place otherwise. + +=cut + +sub has_known_thesaurus { + my ( $class, $thesaurus ) = @_; + + return 0 unless defined $thesaurus; + return $UNDEFINED_THESAURUS_VALUES->{$thesaurus} ? 0 : 1; +} + =head3 default_marc21_008 my $default_008 = Koha::Authority->default_marc21_008; diff --git a/t/db_dependent/Biblio.t b/t/db_dependent/Biblio.t index 975517886a..5fda819a4e 100755 --- a/t/db_dependent/Biblio.t +++ b/t/db_dependent/Biblio.t @@ -17,7 +17,7 @@ use Modern::Perl; -use Test::More tests => 27; +use Test::More tests => 28; use Test::NoWarnings; use Test::MockModule; use Test::Warn; @@ -1115,7 +1115,7 @@ subtest "LinkBibHeadingsToAuthorities record generation tests" => sub { }; subtest "LinkBibHeadingsToAuthorities codes new authorities with the source thesaurus (bug 31925)" => sub { - plan tests => 7; + plan tests => 11; my $biblio_mod = Test::MockModule->new('C4::Linker::Default'); $biblio_mod->mock( @@ -1171,6 +1171,35 @@ subtest "LinkBibHeadingsToAuthorities codes new authorities with the source thes substr( $authority->field('008')->data(), 11, 1 ), 'a', 'Non-subject heading (700) keeps the default LCSH 008/11=a coding, unaffected by this fix' ); + + # Case 5: blank ind2 (thesaurus not identified at all) - must respect the + # MARCAuthorityControlField008 syspref default, not be forced to 'z' (bug 31925 comment 30) + $biblio = $builder->build_sample_biblio(); + $record = $biblio->metadata->record; + $field = MARC::Field->new( '650', '', ' ', 'a' => 'Unidentified thesaurus' ); + $record->append_fields($field); + LinkBibHeadingsToAuthorities( $linker, $record, "", undef, 650 ); + $authority = GetAuthority( $record->subfield( '650', '9' ) ); + is( + substr( $authority->field('008')->data(), 11, 1 ), 'a', + 'Blank ind2 (no thesaurus identified) keeps the syspref default 008/11=a, not forced to z' + ); + is( $authority->subfield( '040', 'f' ), undef, 'Blank ind2 (no thesaurus identified) gets no 040$f' ); + + # Case 6: ind2=4 (explicitly "source not specified") - must also respect a customised + # MARCAuthorityControlField008 syspref default rather than being forced to '|' + t::lib::Mocks::mock_preference( 'MARCAuthorityControlField008', '|| acn||aabn | a|a d' ); + $biblio = $builder->build_sample_biblio(); + $record = $biblio->metadata->record; + $field = MARC::Field->new( '650', '', '4', 'a' => 'Source not specified' ); + $record->append_fields($field); + LinkBibHeadingsToAuthorities( $linker, $record, "", undef, 650 ); + $authority = GetAuthority( $record->subfield( '650', '9' ) ); + is( + substr( $authority->field('008')->data(), 11, 1 ), 'n', + 'ind2=4 (source not specified) respects a customised syspref default 008/11=n, not forced to |' + ); + is( $authority->subfield( '040', 'f' ), undef, 'ind2=4 (source not specified) gets no 040$f' ); }; subtest 'autoControlNumber tests' => sub {