From b0c502407df8332222c83c50791d01f7280baa5b Mon Sep 17 00:00:00 2001 From: Martin Renvoize Date: Thu, 10 Sep 2026 09:14:07 +0100 Subject: [PATCH] Bug 31925: Only code auto-created authorities with the source thesaurus when LinkerConsiderThesaurus is on Comments 43-51 identified a further problem with unconditionally coding a newly auto-created authority's 008/11 (and 040$f) from the source bib heading's thesaurus: when LinkerConsiderThesaurus is off (the default), the linker matches new headings to existing authorities by text alone, regardless of thesaurus. So a bib heading from one thesaurus (e.g. FAST) can auto-create an authority coded for that thesaurus, and a later bib heading with the *same* text but no thesaurus of its own (or a different one) can then link to that same authority purely on the text match. Saving that authority afterwards propagates its 008/11 and 040$f coding back onto every bib heading linked to it - silently adding indicators and subfields the cataloguer never set, on installs that never opted into thesaurus-aware behaviour. Before this bug, AutoCreateAuthorities always created LCSH-coded records, so that propagation was always onto the coding most sites already expect. This bug's earlier patches changed that default for every site regardless of whether they use LinkerConsiderThesaurus, which is what comments 43/45 (reproduced by Pedro Amorim) demonstrated as disruptive. Sites that haven't turned on LinkerConsiderThesaurus don't benefit from thesaurus-aware authority creation anyway, since their linker never searches by thesaurus - C4::Heading::_search and C4::Linker::Default already gate thesaurus-consideration on this same preference for matching. This change gates authority-creation coding on it too, so the behaviour introduced by this bug only applies to installs that already opted into thesaurus-aware linking. Test plan: 1. prove t/db_dependent/Biblio.t Note the new case 7 in the "codes new authorities with the source thesaurus" subtest: with LinkerConsiderThesaurus off, a FAST heading no longer codes the new authority as FAST, it keeps the MARCAuthorityControlField008 syspref default instead. 2. Librarian-facing regression check: with LinkerConsiderThesaurus off (the default), AutoLinkBiblios and AutoCreateAuthorities on, catalogue a 650 with ind2=7 $2=fast and save. The new authority's 008/11 should be whatever MARCAuthorityControlField008 says (LCSH 'a' by default), not 'z'. 3. Confirm the LinkerConsiderThesaurus=on cases from the earlier patches are unaffected: with it on, a FAST heading still codes 008/11='z' with 040$f=fast, and a MeSH heading still codes 008/11='c'. Sponsored-by: Heythrop Library Signed-off-by: Phil Ringnalda Signed-off-by: David Cook Signed-off-by: Pedro Amorim --- C4/Biblio.pm | 13 +++++++++++-- t/db_dependent/Biblio.t | 30 +++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/C4/Biblio.pm b/C4/Biblio.pm index ac35b38777..5c9dad5c6d 100644 --- a/C4/Biblio.pm +++ b/C4/Biblio.pm @@ -827,8 +827,17 @@ sub LinkBibHeadingsToAuthorities { # 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} ) ) { + # apply, the same as it always has, rather than being overridden. Also + # skip it entirely when LinkerConsiderThesaurus is off (bug 31925 comment + # 45): with thesaurus-aware matching disabled, headings from any thesaurus + # can link to the same auto-created authority by text alone, so coding + # that authority for whichever heading happened to create it would let its + # thesaurus silently propagate onto unrelated bibs the next time the + # authority is saved - only sites that opted into thesaurus-aware linking + # (and so already search by thesaurus) should get thesaurus-aware creation. + if ( C4::Context->preference('LinkerConsiderThesaurus') + && 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/t/db_dependent/Biblio.t b/t/db_dependent/Biblio.t index 5fda819a4e..50c5ee3981 100755 --- a/t/db_dependent/Biblio.t +++ b/t/db_dependent/Biblio.t @@ -1115,7 +1115,7 @@ subtest "LinkBibHeadingsToAuthorities record generation tests" => sub { }; subtest "LinkBibHeadingsToAuthorities codes new authorities with the source thesaurus (bug 31925)" => sub { - plan tests => 11; + plan tests => 13; my $biblio_mod = Test::MockModule->new('C4::Linker::Default'); $biblio_mod->mock( @@ -1125,8 +1125,9 @@ subtest "LinkBibHeadingsToAuthorities codes new authorities with the source thes } ); - t::lib::Mocks::mock_preference( 'marcflavour', 'MARC21' ); - t::lib::Mocks::mock_preference( 'AutoCreateAuthorities', '1' ); + t::lib::Mocks::mock_preference( 'marcflavour', 'MARC21' ); + t::lib::Mocks::mock_preference( 'AutoCreateAuthorities', '1' ); + t::lib::Mocks::mock_preference( 'LinkerConsiderThesaurus', '1' ); my $linker = C4::Linker::Default->new(); @@ -1200,6 +1201,29 @@ subtest "LinkBibHeadingsToAuthorities codes new authorities with the source thes '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' ); + + # Case 7: LinkerConsiderThesaurus off (the default) - a FAST heading must NOT get + # thesaurus-aware coding on the new authority (bug 31925 comment 45). With thesaurus + # matching disabled, any other heading spelled the same can link to this same + # auto-created authority regardless of its own thesaurus, so coding it FAST here would + # let that thesaurus silently propagate onto unrelated bibs the next time the authority + # is saved. Only sites that opted into LinkerConsiderThesaurus should get this coding. + t::lib::Mocks::mock_preference( 'MARCAuthorityControlField008', '' ); + t::lib::Mocks::mock_preference( 'LinkerConsiderThesaurus', '0' ); + $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 ), 'a', + 'FAST heading (ind2=7, $2=fast) is coded with the syspref default, not z, when LinkerConsiderThesaurus is off' + ); + is( + $authority->subfield( '040', 'f' ), undef, + 'FAST heading gets no 040$f when LinkerConsiderThesaurus is off' + ); }; subtest 'autoControlNumber tests' => sub {