From 9897f68860c0414325612496f33b2f334e1a0cf7 Mon Sep 17 00:00:00 2001
From: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Date: Wed, 12 Jun 2024 14:15:34 +0100
Subject: [PATCH] Bug 35104: Catch the failure on merging records

We now catch the error and display it to the end user so they can fix
the issues before attempting to merge again.

Signed-off-by: Baptiste Bayche <baptiste.bayche@inlibro.com>
Signed-off-by: Baptiste Wojtkowski <baptiste.wojtkowski@biblibre.com>
---
 cataloguing/merge.pl                          | 91 +++++++++++--------
 .../prog/en/modules/cataloguing/merge.tt      |  5 +-
 2 files changed, 58 insertions(+), 38 deletions(-)

diff --git a/cataloguing/merge.pl b/cataloguing/merge.pl
index 9fe7bc4f8b0..8823c5ace4b 100755
--- a/cataloguing/merge.pl
+++ b/cataloguing/merge.pl
@@ -89,50 +89,67 @@ if ($op eq 'cud-merge') {
     my $frameworkcode = $input->param('frameworkcode');
 
     # Modifying the reference record
-    ModBiblio($record, $ref_biblionumber, $frameworkcode);
+    my $invalid_metadata;
+    my $modded = try {
+        ModBiblio($record, $ref_biblionumber, $frameworkcode);
+        return 1;
+    } catch {
+        my $exception = $_;
+        if ( ref($exception) eq 'Koha::Exceptions::Metadata::Invalid' ) {
+            $invalid_metadata = $exception;
+        } else {
+            $exception->rethrow;
+        }
+        return 0;
+    };
 
     my $report_header = {};
-    foreach my $biblionumber ($ref_biblionumber, @biblionumbers) {
-        # build report
-        my $biblio = Koha::Biblios->find($biblionumber);
-        my $marcrecord = $biblio->metadata->record;
-        my %report_record = (
-            biblionumber => $biblionumber,
-            fields => {},
-        );
-        foreach my $field (@report_fields) {
-            my @marcfields = $marcrecord->field($field->{tag});
-            foreach my $marcfield (@marcfields) {
-                my $tag = $marcfield->tag();
-                if (scalar @{$field->{subfields}}) {
-                    foreach my $subfield (@{$field->{subfields}}) {
-                        my @values = $marcfield->subfield($subfield);
-                        $report_header->{ $tag . $subfield } = 1;
-                        push @{ $report_record{fields}->{$tag . $subfield} }, @values;
-                    }
-                } elsif ($field->{tag} gt '009') {
-                    my @marcsubfields = $marcfield->subfields();
-                    foreach my $marcsubfield (@marcsubfields) {
-                        my ($code, $value) = @$marcsubfield;
-                        $report_header->{ $tag . $code } = 1;
-                        push @{ $report_record{fields}->{ $tag . $code } }, $value;
+    if ($modded) {
+        foreach my $biblionumber ( $ref_biblionumber, @biblionumbers ) {
+
+            # build report
+            my $biblio        = Koha::Biblios->find($biblionumber);
+            my $marcrecord    = $biblio->metadata->record;
+            my %report_record = (
+                biblionumber => $biblionumber,
+                fields       => {},
+            );
+            foreach my $field (@report_fields) {
+                my @marcfields = $marcrecord->field( $field->{tag} );
+                foreach my $marcfield (@marcfields) {
+                    my $tag = $marcfield->tag();
+                    if ( scalar @{ $field->{subfields} } ) {
+                        foreach my $subfield ( @{ $field->{subfields} } ) {
+                            my @values = $marcfield->subfield($subfield);
+                            $report_header->{ $tag . $subfield } = 1;
+                            push @{ $report_record{fields}->{ $tag . $subfield } }, @values;
+                        }
+                    } elsif ( $field->{tag} gt '009' ) {
+                        my @marcsubfields = $marcfield->subfields();
+                        foreach my $marcsubfield (@marcsubfields) {
+                            my ( $code, $value ) = @$marcsubfield;
+                            $report_header->{ $tag . $code } = 1;
+                            push @{ $report_record{fields}->{ $tag . $code } }, $value;
+                        }
+                    } else {
+                        $report_header->{ $tag . '@' } = 1;
+                        push @{ $report_record{fields}->{ $tag . '@' } }, $marcfield->data();
                     }
-                } else {
-                    $report_header->{ $tag . '@' } = 1;
-                    push @{ $report_record{fields}->{ $tag .'@' } }, $marcfield->data();
                 }
             }
+            push @report_records, \%report_record;
         }
-        push @report_records, \%report_record;
-    }
 
-    my $rmerge;
-    eval {
-        my $newbiblio = Koha::Biblios->find($ref_biblionumber);
-        $rmerge = $newbiblio->merge_with( \@biblionumbers );
-    };
-    if ($@) {
-        push @errors, $@;
+        my $rmerge;
+        eval {
+            my $newbiblio = Koha::Biblios->find($ref_biblionumber);
+            $rmerge = $newbiblio->merge_with( \@biblionumbers );
+        };
+        if ($@) {
+            push @errors, $@;
+        }
+    } else {
+        push @errors, { code => "INVALID_METADATA", value => $invalid_metadata };
     }
 
     # Parameters
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/merge.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/merge.tt
index 6da973da338..3abfaa40982 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/merge.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/merge.tt
@@ -46,7 +46,10 @@ div#result { margin-top: 1em; }
        [% FOREACH error IN errors %]
            <div class="alert alert-warning">
                 [% IF error.code == 'CANNOT_MOVE' %]
-                    The following items could not be moved from the old record to the new one: [% error.value | html %]
+                    <p>The following items could not be moved from the old record to the new one: [% error.value | html %]</p>
+                [% ELSIF error.code == 'INVALID_METADATA' %]
+                    <p>This record had encoding issues, non-xml characters have been stripped in order to allow editing. Please be cautious when saving that some data may have been removed from the record.</p>
+                    <pre class="problem">[% error.value | html %]</pre>
                 [% ELSE %]
                     [% error | html %]
                 [% END %]
-- 
2.48.1