From 4fa963e9264b7536bfb79f5dd7ce79a2efb02d84 Mon Sep 17 00:00:00 2001
From: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Date: Fri, 18 Mar 2022 11:30:31 +0100
Subject: [PATCH] Bug 29697: Deal with the degraded view in detail.pl

In detail.pl we must provide a degraded view with an error message about
invalid MARC::Record.
We are then forced to reproduce the GetMarcBiblio behaviour and call
StripNonXmlChars on the MARC::XML
---
 C4/Biblio.pm        |  1 -
 catalogue/detail.pl | 41 +++++++++++++++++++++++------------------
 2 files changed, 23 insertions(+), 19 deletions(-)

diff --git a/C4/Biblio.pm b/C4/Biblio.pm
index 271d4b4fcae..6ce71248b7e 100644
--- a/C4/Biblio.pm
+++ b/C4/Biblio.pm
@@ -95,7 +95,6 @@ use C4::Charset qw(
     nsb_clean
     SetMarcUnicodeFlag
     SetUTF8Flag
-    StripNonXmlChars
 );
 use C4::Linker;
 use C4::OAI::Sets;
diff --git a/catalogue/detail.pl b/catalogue/detail.pl
index bbe7a1d0c2a..24eb352ebb0 100755
--- a/catalogue/detail.pl
+++ b/catalogue/detail.pl
@@ -86,10 +86,9 @@ my $biblionumber = $query->param('biblionumber');
 $biblionumber = HTML::Entities::encode($biblionumber);
 # FIXME Special case here
 my $biblio = Koha::Biblios->find( $biblionumber );
-my $record = $biblio->metadata->record;
 $template->param( 'biblio', $biblio );
 
-if ( not defined $record ) {
+unless ( $biblio ) {
     # biblionumber invalid -> report and exit
     $template->param( unknownbiblionumber => 1,
                       biblionumber => $biblionumber );
@@ -98,7 +97,16 @@ if ( not defined $record ) {
 }
 
 my $marc_record = eval { $biblio->metadata->record };
-$template->param( decoding_error => $@ );
+my $invalid_marc_record = $@ || !$marc_record;
+if ($invalid_marc_record) {
+    $template->param( decoding_error => $@ );
+    my $marc_xml = C4::Charset::StripNonXmlChars( $biblio->metadata->metadata );
+
+    $marc_record = eval {
+        MARC::Record::new_from_xml( $marc_xml, 'UTF-8',
+            C4::Context->preference('marcflavour') );
+    };
+}
 
 if($query->cookie("holdfor")){
     my $holdfor_patron = Koha::Patrons->find( $query->cookie("holdfor") );
@@ -127,18 +135,15 @@ my $marcflavour  = C4::Context->preference("marcflavour");
 
 $template->param( 'SpineLabelShowPrintOnBibDetails' => C4::Context->preference("SpineLabelShowPrintOnBibDetails") );
 
-# Catch the exception as Koha::Biblio::Metadata->record can explode if the MARCXML is invalid
-# Do not propagate it as we already deal with it previously in this script
-my $coins = eval { $biblio->get_coins };
-$template->param( ocoins => $coins );
+$template->param( ocoins => !$invalid_marc_record ? $biblio->get_coins : undef );
 
 # some useful variables for enhanced content;
 # in each case, we're grabbing the first value we find in
 # the record and normalizing it
-my $upc = GetNormalizedUPC($record,$marcflavour);
-my $ean = GetNormalizedEAN($record,$marcflavour);
-my $oclc = GetNormalizedOCLCNumber($record,$marcflavour);
-my $isbn = GetNormalizedISBN(undef,$record,$marcflavour);
+my $upc = GetNormalizedUPC($marc_record,$marcflavour);
+my $ean = GetNormalizedEAN($marc_record,$marcflavour);
+my $oclc = GetNormalizedOCLCNumber($marc_record,$marcflavour);
+my $isbn = GetNormalizedISBN(undef,$marc_record,$marcflavour);
 my $content_identifier_exists;
 if ( $isbn or $ean or $oclc or $upc ) {
     $content_identifier_exists = 1;
@@ -166,7 +171,7 @@ for my $itm (@all_items) {
 # flag indicating existence of at least one item linked via a host record
 my $hostrecords;
 # adding items linked via host biblios
-my @hostitems = GetHostItemsInfo($record);
+my @hostitems = GetHostItemsInfo($marc_record);
 if (@hostitems){
     $hostrecords =1;
     push (@items,@hostitems);
@@ -204,7 +209,7 @@ foreach my $subscription (@subscriptions) {
 my $showcomp = C4::Context->preference('ShowComponentRecords');
 my $show_analytics;
 if ( $showcomp eq 'both' || $showcomp eq 'staff' ) {
-    if ( my $components = $marc_record ? $biblio->get_marc_components(C4::Context->preference('MaxComponentRecords')) : undef ) {
+    if ( my $components = !$invalid_marc_record ? $biblio->get_marc_components(C4::Context->preference('MaxComponentRecords')) : undef ) {
         $show_analytics = 1 if @{$components}; # just show link when having results
         $template->param( analytics_error => 1 ) if grep { $_->message eq 'component_search' } @{$biblio->object_messages};
         my $parts;
@@ -226,7 +231,7 @@ if ( $showcomp eq 'both' || $showcomp eq 'staff' ) {
         $template->param( ComponentPartsQuery => $biblio->get_components_query );
     }
 } else { # check if we should show analytics anyway
-    $show_analytics = 1 if $marc_record && @{$biblio->get_marc_components(1)}; # count matters here, results does not
+    $show_analytics = 1 if !$invalid_marc_record && @{$biblio->get_marc_components(1)}; # count matters here, results does not
     $template->param( analytics_error => 1 ) if grep { $_->message eq 'component_search' } @{$biblio->object_messages};
 }
 
@@ -236,7 +241,7 @@ $template->param(
     XSLTDetailsDisplay => '1',
     XSLTBloc => XSLTParse4Display({
         biblionumber   => $biblionumber,
-        record         => $record,
+        record         => $marc_record,
         xsl_syspref    => "XSLTDetailsDisplay",
         fix_amps       => 1,
         xslt_variables => $xslt_variables,
@@ -465,7 +470,7 @@ $template->param(
 );
 
 $template->param(
-    MARCNOTES   => $marc_record ? $biblio->get_marc_notes({ marcflavour => $marcflavour }) : (),
+    MARCNOTES   => !$invalid_marc_record ? $biblio->get_marc_notes({ marcflavour => $marcflavour }) : (),
     itemdata_ccode      => $itemfields{ccode},
     itemdata_enumchron  => $itemfields{enumchron},
     itemdata_uri        => $itemfields{uri},
@@ -487,7 +492,7 @@ if (C4::Context->preference("AlternateHoldingsField") && scalar @items == 0) {
     my $subfields = substr $fieldspec, 3;
     my $holdingsep = C4::Context->preference("AlternateHoldingsSeparator") || ' ';
     my @alternateholdingsinfo = ();
-    my @holdingsfields = $record->field(substr $fieldspec, 0, 3);
+    my @holdingsfields = $marc_record->field(substr $fieldspec, 0, 3);
 
     for my $field (@holdingsfields) {
         my %holding = ( holding => '' );
@@ -560,7 +565,7 @@ if ( C4::Context->preference("LocalCoverImages") == 1 ) {
 
 # HTML5 Media
 if ( (C4::Context->preference("HTML5MediaEnabled") eq 'both') or (C4::Context->preference("HTML5MediaEnabled") eq 'staff') ) {
-    $template->param( C4::HTML5Media->gethtml5media($record));
+    $template->param( C4::HTML5Media->gethtml5media($marc_record));
 }
 
 # Displaying tags
-- 
2.25.1