diff --git a/C4/Biblio.pm b/C4/Biblio.pm index f694a19f46..5ddd7c7272 100644 --- a/C4/Biblio.pm +++ b/C4/Biblio.pm @@ -99,6 +99,7 @@ use Koha::Logger; use Koha::Cache::Memory::Lite; use Koha::Caches; use Koha::ClassSources; +use Koha::Authority; use Koha::Authority::Types; use Koha::Acquisition::Currencies; use Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue; @@ -811,10 +812,35 @@ sub LinkBibHeadingsToAuthorities { if ( C4::Context->preference('marcflavour') eq 'MARC21' ) { my $userenv = C4::Context->userenv; - my $library; - if ( $userenv && $userenv->{'branch'} ) { - $library = Koha::Libraries->find( $userenv->{'branch'} ); + + # userenv's library could not exist because of a trick in misc/commit_file.pl + # (see FIXME and set_userenv statement there) + my $library = + $userenv && $userenv->{branch} ? Koha::Libraries->find( $userenv->{branch} ) : undef; + my $marcorgcode = + $library ? $library->get_effective_marcorgcode : C4::Context->preference('MARCOrgCode'); + + # Bug 31925: code the new authority with the source heading's actual + # 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} ) { + my $date = POSIX::strftime( '%y%m%d', localtime ); + $marcrecordauth->insert_fields_ordered( + MARC::Field->new( + '008', $date . Koha::Authority->default_marc21_008( $heading->{thesaurus} ) + ) + ); + + my @f040_subfields = ( 'a' => $marcorgcode, 'c' => $marcorgcode ); + push @f040_subfields, ( 'f' => $heading->{thesaurus} ) + unless exists + $Koha::Authority::MARC21_THESAURUS_TO_CONTROL_FIELD_008_11->{ $heading->{thesaurus} }; + $marcrecordauth->insert_fields_ordered( + MARC::Field->new( '040', '', '', @f040_subfields ) ); } + $marcrecordauth->insert_fields_ordered( MARC::Field->new( '667', '', '', @@ -825,10 +851,8 @@ sub LinkBibHeadingsToAuthorities { $cite =~ s/^[\s\,]*//; $cite =~ s/[\s\,]*$//; $cite = - C4::Context->preference('GenerateAuthorityField670') . ": (" - . ( - $library ? $library->get_effective_marcorgcode : C4::Context->preference('MARCOrgCode') ) - . ")" + C4::Context->preference('GenerateAuthorityField670') . ": (" + . "$marcorgcode)" . $bib->subfield( '999', 'c' ) . ": " . $cite; $marcrecordauth->insert_fields_ordered( MARC::Field->new( '670', '', '', 'a' => $cite ) ); diff --git a/t/db_dependent/Biblio.t b/t/db_dependent/Biblio.t index 1b2e81a7c2..975517886a 100755 --- a/t/db_dependent/Biblio.t +++ b/t/db_dependent/Biblio.t @@ -1114,6 +1114,65 @@ subtest "LinkBibHeadingsToAuthorities record generation tests" => sub { ); }; +subtest "LinkBibHeadingsToAuthorities codes new authorities with the source thesaurus (bug 31925)" => sub { + plan tests => 7; + + my $biblio_mod = Test::MockModule->new('C4::Linker::Default'); + $biblio_mod->mock( + 'get_link', + sub { + return ( undef, undef, 0 ); + } + ); + + t::lib::Mocks::mock_preference( 'marcflavour', 'MARC21' ); + t::lib::Mocks::mock_preference( 'AutoCreateAuthorities', '1' ); + + my $linker = C4::Linker::Default->new(); + + # Case 1: plain LCSH (ind2=0, no $2) - regression guard, must stay coded 'a' + my $biblio = $builder->build_sample_biblio(); + my $record = $biblio->metadata->record; + my $field = MARC::Field->new( '650', '', '0', 'a' => 'Feminism' ); + $record->append_fields($field); + LinkBibHeadingsToAuthorities( $linker, $record, "", undef, 650 ); + my $authority = GetAuthority( $record->subfield( '650', '9' ) ); + is( substr( $authority->field('008')->data(), 11, 1 ), 'a', 'Plain LCSH heading (ind2=0) is coded 008/11=a' ); + is( $authority->subfield( '040', 'f' ), undef, 'Plain LCSH heading (ind2=0) gets no 040$f' ); + + # Case 2: FAST heading (ind2=7, $2=fast) - the actual bug: must NOT be coded as LCSH + $biblio = $builder->build_sample_biblio(); + $record = $biblio->metadata->record; + $field = MARC::Field->new( '650', '', '7', 'a' => 'Miracles', '2' => 'fast' ); + $record->append_fields($field); + LinkBibHeadingsToAuthorities( $linker, $record, "", undef, 650 ); + $authority = GetAuthority( $record->subfield( '650', '9' ) ); + is( substr( $authority->field('008')->data(), 11, 1 ), 'z', 'FAST heading (ind2=7, $2=fast) is coded 008/11=z' ); + is( $authority->subfield( '040', 'f' ), 'fast', 'FAST heading (ind2=7, $2=fast) gets 040$f=fast' ); + + # Case 3: MeSH heading (ind2=2, no $2) + $biblio = $builder->build_sample_biblio(); + $record = $biblio->metadata->record; + $field = MARC::Field->new( '650', '', '2', 'a' => 'Something' ); + $record->append_fields($field); + LinkBibHeadingsToAuthorities( $linker, $record, "", undef, 650 ); + $authority = GetAuthority( $record->subfield( '650', '9' ) ); + is( substr( $authority->field('008')->data(), 11, 1 ), 'c', 'MeSH heading (ind2=2) is coded 008/11=c' ); + is( $authority->subfield( '040', 'f' ), undef, 'MeSH heading (ind2=2) gets no 040$f' ); + + # Case 4: non-subject heading (personal name added entry) is unaffected - no thesaurus semantics + $biblio = $builder->build_sample_biblio(); + $record = $biblio->metadata->record; + $field = MARC::Field->new( '700', '', '', 'a' => 'Doe, Jane' ); + $record->append_fields($field); + LinkBibHeadingsToAuthorities( $linker, $record, "", undef, 700 ); + $authority = GetAuthority( $record->subfield( '700', '9' ) ); + is( + substr( $authority->field('008')->data(), 11, 1 ), 'a', + 'Non-subject heading (700) keeps the default LCSH 008/11=a coding, unaffected by this fix' + ); +}; + subtest 'autoControlNumber tests' => sub { plan tests => 3;