Bug 24567: (QA follow-up) Remove warning in regex
[koha.git] / Koha / Exporter / Record.pm
blobeaebe5763930f770883566979c87d2712fa68f13
1 package Koha::Exporter::Record;
3 use Modern::Perl;
4 use MARC::File::XML;
5 use MARC::File::USMARC;
7 use C4::AuthoritiesMarc;
8 use C4::Biblio;
9 use C4::Record;
10 use Koha::CsvProfiles;
11 use Koha::Logger;
12 use List::Util qw(all any);
14 sub _get_record_for_export {
15 my ($params) = @_;
16 my $record_type = $params->{record_type};
17 my $record_id = $params->{record_id};
18 my $conditions = $params->{record_conditions};
19 my $dont_export_fields = $params->{dont_export_fields};
20 my $clean = $params->{clean};
22 my $record;
23 if ( $record_type eq 'auths' ) {
24 $record = _get_authority_for_export( { %$params, authid => $record_id } );
25 } elsif ( $record_type eq 'bibs' ) {
26 $record = _get_biblio_for_export( { %$params, biblionumber => $record_id } );
27 } else {
28 Koha::Logger->get->warn( "Record_type $record_type not supported." );
30 if ( !$record ) {
31 Koha::Logger->get->warn( "Record $record_id could not be exported." );
32 return;
35 # If multiple conditions all are required to match (and)
36 # For matching against multiple marc targets all are also required to match
37 my %operators = (
38 '=' => sub {
39 return $_[0] eq $_[1];
41 '!=' => sub {
42 return $_[0] ne $_[1];
44 '>' => sub {
45 return $_[0] gt $_[1];
47 '<' => sub {
48 return $_[0] lt $_[1];
51 if ($conditions) {
52 foreach my $condition (@{$conditions}) {
53 my ($field_tag, $subfield, $operator, $match_value) = @{$condition};
54 my @fields = $record->field($field_tag);
55 my $no_target = 0;
57 if (!@fields) {
58 $no_target = 1;
60 else {
61 if ($operator eq '?') {
62 return unless any { $subfield ? $_->subfield($subfield) : $_->data() } @fields;
63 } elsif ($operator eq '!?') {
64 return if any { $subfield ? $_->subfield($subfield) : $_->data() } @fields;
65 } else {
66 my $op;
67 if (exists $operators{$operator}) {
68 $op = $operators{$operator};
69 } else {
70 die("Invalid operator: $op");
72 my @target_values = map { $subfield ? $_->subfield($subfield) : ($_->data()) } @fields;
73 if (!@target_values) {
74 $no_target = 1;
76 else {
77 return unless all { $op->($_, $match_value) } @target_values;
81 return if $no_target && $operator ne '!=';
85 if ($dont_export_fields) {
86 for my $f ( split / /, $dont_export_fields ) {
87 if ( $f =~ m/^(\d{3})(.)?$/ ) {
88 my ( $field, $subfield ) = ( $1, $2 );
90 # skip if this record doesn't have this field
91 if ( defined $record->field($field) ) {
92 if ( defined $subfield ) {
93 my @tags = $record->field($field);
94 foreach my $t (@tags) {
95 $t->delete_subfields($subfield);
97 } else {
98 $record->delete_fields( $record->field($field) );
104 C4::Biblio::RemoveAllNsb($record) if $clean;
105 return $record;
108 sub _get_authority_for_export {
109 my ($params) = @_;
110 my $authid = $params->{authid} || return;
111 my $authority = Koha::MetadataRecord::Authority->get_from_authid($authid);
112 return unless $authority;
113 return $authority->record;
116 sub _get_biblio_for_export {
117 my ($params) = @_;
118 my $biblionumber = $params->{biblionumber};
119 my $itemnumbers = $params->{itemnumbers};
120 my $export_items = $params->{export_items} // 1;
121 my $only_export_items_for_branches = $params->{only_export_items_for_branches};
123 my $record = eval { C4::Biblio::GetMarcBiblio({ biblionumber => $biblionumber }); };
125 return if $@ or not defined $record;
127 if ($export_items) {
128 C4::Biblio::EmbedItemsInMarcBiblio({
129 marc_record => $record,
130 biblionumber => $biblionumber,
131 item_numbers => $itemnumbers });
132 if ($only_export_items_for_branches && @$only_export_items_for_branches) {
133 my %export_items_for_branches = map { $_ => 1 } @$only_export_items_for_branches;
134 my ( $homebranchfield, $homebranchsubfield ) = GetMarcFromKohaField( 'items.homebranch' );
136 for my $itemfield ( $record->field($homebranchfield) ) {
137 my $homebranch = $itemfield->subfield($homebranchsubfield);
138 unless ( $export_items_for_branches{$homebranch} ) {
139 $record->delete_field($itemfield);
144 return $record;
147 sub export {
148 my ($params) = @_;
150 my $record_type = $params->{record_type};
151 my $record_ids = $params->{record_ids} || [];
152 my $format = $params->{format};
153 my $itemnumbers = $params->{itemnumbers} || []; # Does not make sense with record_type eq auths
154 my $export_items = $params->{export_items};
155 my $dont_export_fields = $params->{dont_export_fields};
156 my $csv_profile_id = $params->{csv_profile_id};
157 my $output_filepath = $params->{output_filepath};
159 if( !$record_type ) {
160 Koha::Logger->get->warn( "No record_type given." );
161 return;
163 return unless @$record_ids;
165 my $fh;
166 if ( $output_filepath ) {
167 open $fh, '>', $output_filepath or die "Cannot open file $output_filepath ($!)";
168 select $fh;
169 binmode $fh, ':encoding(UTF-8)' unless $format eq 'csv';
170 } else {
171 binmode STDOUT, ':encoding(UTF-8)' unless $format eq 'csv';
174 if ( $format eq 'iso2709' ) {
175 for my $record_id (@$record_ids) {
176 my $record = _get_record_for_export( { %$params, record_id => $record_id } );
177 next unless $record;
178 my $errorcount_on_decode = eval { scalar( MARC::File::USMARC->decode( $record->as_usmarc )->warnings() ) };
179 if ( $errorcount_on_decode or $@ ) {
180 my $msg = "Record $record_id could not be exported. " .
181 ( $@ // '' );
182 chomp $msg;
183 Koha::Logger->get->info( $msg );
184 next;
186 print $record->as_usmarc();
188 } elsif ( $format eq 'xml' ) {
189 my $marcflavour = C4::Context->preference("marcflavour");
190 MARC::File::XML->default_record_format( ( $marcflavour eq 'UNIMARC' && $record_type eq 'auths' ) ? 'UNIMARCAUTH' : $marcflavour );
192 print MARC::File::XML::header();
193 print "\n";
194 for my $record_id (@$record_ids) {
195 my $record = _get_record_for_export( { %$params, record_id => $record_id } );
196 next unless $record;
197 print MARC::File::XML::record($record);
198 print "\n";
200 print MARC::File::XML::footer();
201 print "\n";
202 } elsif ( $format eq 'csv' ) {
203 die 'There is no valid csv profile defined for this export'
204 unless Koha::CsvProfiles->find( $csv_profile_id );
205 print marc2csv( $record_ids, $csv_profile_id, $itemnumbers );
208 close $fh if $output_filepath;
213 __END__
215 =head1 NAME
217 Koha::Exporter::Records - module to export records (biblios and authorities)
219 =head1 SYNOPSIS
221 This module provides a public subroutine to export records as xml, csv or iso2709.
223 =head2 FUNCTIONS
225 =head3 export
227 Koha::Exporter::Record::export($params);
229 $params is a hashref with some keys:
231 It will displays on STDOUT the generated file.
233 =over 4
235 =item record_type
237 Must be set to 'bibs' or 'auths'
239 =item record_ids
241 The list of the records to export (a list of biblionumber or authid)
243 =item format
245 The format must be 'csv', 'xml' or 'iso2709'.
247 =item itemnumbers
249 Generate the item infos only for these itemnumbers.
251 Must only be used with biblios.
253 =item export_items
255 If this flag is set, the items will be exported.
256 Default is ON.
258 =item dont_export_fields
260 List of fields not to export.
262 =item csv_profile_id
264 If the format is csv, you have to define a csv_profile_id.
266 =cut
268 =back
270 =head1 LICENSE
272 This file is part of Koha.
274 Copyright Koha Development Team
276 Koha is free software; you can redistribute it and/or modify it
277 under the terms of the GNU General Public License as published by
278 the Free Software Foundation; either version 3 of the License, or
279 (at your option) any later version.
281 Koha is distributed in the hope that it will be useful, but
282 WITHOUT ANY WARRANTY; without even the implied warranty of
283 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
284 GNU General Public License for more details.
286 You should have received a copy of the GNU General Public License
287 along with Koha; if not, see <http://www.gnu.org/licenses>.