Bug 20486: Add --marc_conditions option to export_records.pl
[koha.git] / Koha / Exporter / Record.pm
index aa805e2..42ac002 100644 (file)
@@ -9,11 +9,13 @@ use C4::Biblio;
 use C4::Record;
 use Koha::CsvProfiles;
 use Koha::Logger;
+use List::Util qw(all any);
 
 sub _get_record_for_export {
     my ($params)           = @_;
     my $record_type        = $params->{record_type};
     my $record_id          = $params->{record_id};
+    my $conditions         = $params->{record_conditions};
     my $dont_export_fields = $params->{dont_export_fields};
     my $clean              = $params->{clean};
 
@@ -25,7 +27,60 @@ sub _get_record_for_export {
     } else {
         Koha::Logger->get->warn( "Record_type $record_type not supported." );
     }
-    return unless $record;
+    if ( !$record ) {
+        Koha::Logger->get->warn( "Record $record_id could not be exported." );
+        return;
+    }
+
+    # If multiple conditions all are required to match (and)
+    # For matching against multiple marc targets all are also required to match
+    my %operators = (
+        '=' => sub {
+            return $_[0] eq $_[1];
+        },
+        '!=' => sub {
+            return $_[0] ne $_[1];
+        },
+        '>' => sub {
+            return $_[0] gt $_[1];
+        },
+        '<' => sub {
+            return $_[0] lt $_[1];
+        },
+    );
+    if ($conditions) {
+        foreach my $condition (@{$conditions}) {
+            my ($field_tag, $subfield, $operator, $match_value) = @{$condition};
+            my @fields = $record->field($field_tag);
+            my $no_target = 0;
+
+            if (!@fields) {
+                $no_target = 1;
+            }
+            else {
+                if ($operator eq '?') {
+                    return unless any { $subfield ? $_->subfield($subfield) : $_->data() } @fields;
+                } elsif ($operator eq '!?') {
+                    return if any { $subfield ? $_->subfield($subfield) : $_->data() } @fields;
+                } else {
+                    my $op;
+                    if (exists $operators{$operator}) {
+                        $op = $operators{$operator};
+                    } else {
+                        die("Invalid operator: $op");
+                    }
+                    my @target_values = map { $subfield ? $_->subfield($subfield) : ($_->data()) } @fields;
+                    if (!@target_values) {
+                        $no_target = 1;
+                    }
+                    else {
+                        return unless all { $op->($_, $match_value) } @target_values;
+                    }
+                }
+            }
+            return if $no_target && $operator ne '!=';
+        }
+    }
 
     if ($dont_export_fields) {
         for my $f ( split / /, $dont_export_fields ) {
@@ -63,20 +118,24 @@ sub _get_biblio_for_export {
     my $biblionumber = $params->{biblionumber};
     my $itemnumbers  = $params->{itemnumbers};
     my $export_items = $params->{export_items} // 1;
-    my $only_export_items_for_branch = $params->{only_export_items_for_branch};
+    my $only_export_items_for_branches = $params->{only_export_items_for_branches};
 
-    my $record = eval { C4::Biblio::GetMarcBiblio($biblionumber); };
+    my $record = eval { C4::Biblio::GetMarcBiblio({ biblionumber => $biblionumber }); };
 
     return if $@ or not defined $record;
 
     if ($export_items) {
-        C4::Biblio::EmbedItemsInMarcBiblio( $record, $biblionumber, $itemnumbers );
-        if ($only_export_items_for_branch) {
+        C4::Biblio::EmbedItemsInMarcBiblio({
+            marc_record  => $record,
+            biblionumber => $biblionumber,
+            item_numbers => $itemnumbers });
+        if ($only_export_items_for_branches && @$only_export_items_for_branches) {
+            my %export_items_for_branches = map { $_ => 1 } @$only_export_items_for_branches;
             my ( $homebranchfield, $homebranchsubfield ) = GetMarcFromKohaField( 'items.homebranch', '' );    # Should be GetFrameworkCode( $biblionumber )?
 
             for my $itemfield ( $record->field($homebranchfield) ) {
                 my $homebranch = $itemfield->subfield($homebranchsubfield);
-                if ( $only_export_items_for_branch ne $homebranch ) {
+                unless ( $export_items_for_branches{$homebranch} ) {
                     $record->delete_field($itemfield);
                 }
             }
@@ -115,6 +174,7 @@ sub export {
     if ( $format eq 'iso2709' ) {
         for my $record_id (@$record_ids) {
             my $record = _get_record_for_export( { %$params, record_id => $record_id } );
+            next unless $record;
             my $errorcount_on_decode = eval { scalar( MARC::File::USMARC->decode( $record->as_usmarc )->warnings() ) };
             if ( $errorcount_on_decode or $@ ) {
                 my $msg = "Record $record_id could not be exported. " .
@@ -133,22 +193,15 @@ sub export {
         print "\n";
         for my $record_id (@$record_ids) {
             my $record = _get_record_for_export( { %$params, record_id => $record_id } );
-            if( !$record ) {
-                Koha::Logger->get->info( "Record $record_id could not be exported." );
-                next;
-            }
+            next unless $record;
             print MARC::File::XML::record($record);
             print "\n";
         }
         print MARC::File::XML::footer();
         print "\n";
     } elsif ( $format eq 'csv' ) {
-        unless ( $csv_profile_id ) {
-            # FIXME export_format.profile should be a unique key
-            my $csv_profiles = Koha::CsvProfiles->search({ profile => C4::Context->preference('ExportWithCsvProfile') });
-            die "The ExportWithCsvProfile system preference is not defined or does not match a valid csv profile" unless $csv_profiles->count;
-            $csv_profile_id = $csv_profiles->next->export_format_id;
-        }
+        die 'There is no valid csv profile defined for this export'
+            unless Koha::CsvProfiles->find( $csv_profile_id );
         print marc2csv( $record_ids, $csv_profile_id, $itemnumbers );
     }
 
@@ -208,7 +261,7 @@ It will displays on STDOUT the generated file.
 
 =item csv_profile_id
 
-  If the format is csv, a csv_profile_id can be provide to overwrite the default value (syspref ExportWithCsvProfile).
+  If the format is csv, you have to define a csv_profile_id.
 
 =cut