Bug 17569: Koha::Patrons - Move GetUpcomingMembershipExpires to search_upcoming_membe...
[koha.git] / Koha / Exporter / Record.pm
1 package Koha::Exporter::Record;
2
3 use Modern::Perl;
4 use MARC::File::XML;
5 use MARC::File::USMARC;
6
7 use C4::AuthoritiesMarc;
8 use C4::Biblio;
9 use C4::Record;
10 use Koha::CsvProfiles;
11 use Koha::Logger;
12
13 sub _get_record_for_export {
14     my ($params)           = @_;
15     my $record_type        = $params->{record_type};
16     my $record_id          = $params->{record_id};
17     my $dont_export_fields = $params->{dont_export_fields};
18     my $clean              = $params->{clean};
19
20     my $record;
21     if ( $record_type eq 'auths' ) {
22         $record = _get_authority_for_export( { %$params, authid => $record_id } );
23     } elsif ( $record_type eq 'bibs' ) {
24         $record = _get_biblio_for_export( { %$params, biblionumber => $record_id } );
25     } else {
26         Koha::Logger->get->warn( "Record_type $record_type not supported." );
27     }
28     return unless $record;
29
30     if ($dont_export_fields) {
31         for my $f ( split / /, $dont_export_fields ) {
32             if ( $f =~ m/^(\d{3})(.)?$/ ) {
33                 my ( $field, $subfield ) = ( $1, $2 );
34
35                 # skip if this record doesn't have this field
36                 if ( defined $record->field($field) ) {
37                     if ( defined $subfield ) {
38                         my @tags = $record->field($field);
39                         foreach my $t (@tags) {
40                             $t->delete_subfields($subfield);
41                         }
42                     } else {
43                         $record->delete_fields( $record->field($field) );
44                     }
45                 }
46             }
47         }
48     }
49     C4::Biblio::RemoveAllNsb($record) if $clean;
50     return $record;
51 }
52
53 sub _get_authority_for_export {
54     my ($params) = @_;
55     my $authid = $params->{authid} || return;
56     my $authority = Koha::MetadataRecord::Authority->get_from_authid($authid);
57     return unless $authority;
58     return $authority->record;
59 }
60
61 sub _get_biblio_for_export {
62     my ($params)     = @_;
63     my $biblionumber = $params->{biblionumber};
64     my $itemnumbers  = $params->{itemnumbers};
65     my $export_items = $params->{export_items} // 1;
66     my $only_export_items_for_branch = $params->{only_export_items_for_branch};
67
68     my $record = eval { C4::Biblio::GetMarcBiblio($biblionumber); };
69
70     return if $@ or not defined $record;
71
72     if ($export_items) {
73         C4::Biblio::EmbedItemsInMarcBiblio( $record, $biblionumber, $itemnumbers );
74         if ($only_export_items_for_branch) {
75             my ( $homebranchfield, $homebranchsubfield ) = GetMarcFromKohaField( 'items.homebranch', '' );    # Should be GetFrameworkCode( $biblionumber )?
76
77             for my $itemfield ( $record->field($homebranchfield) ) {
78                 my $homebranch = $itemfield->subfield($homebranchsubfield);
79                 if ( $only_export_items_for_branch ne $homebranch ) {
80                     $record->delete_field($itemfield);
81                 }
82             }
83         }
84     }
85     return $record;
86 }
87
88 sub export {
89     my ($params) = @_;
90
91     my $record_type        = $params->{record_type};
92     my $record_ids         = $params->{record_ids} || [];
93     my $format             = $params->{format};
94     my $itemnumbers        = $params->{itemnumbers} || [];    # Does not make sense with record_type eq auths
95     my $export_items       = $params->{export_items};
96     my $dont_export_fields = $params->{dont_export_fields};
97     my $csv_profile_id     = $params->{csv_profile_id};
98     my $output_filepath    = $params->{output_filepath};
99
100     if( !$record_type ) {
101         Koha::Logger->get->warn( "No record_type given." );
102         return;
103     }
104     return unless @$record_ids;
105
106     my $fh;
107     if ( $output_filepath ) {
108         open $fh, '>', $output_filepath or die "Cannot open file $output_filepath ($!)";
109         select $fh;
110         binmode $fh, ':encoding(UTF-8)' unless $format eq 'csv';
111     } else {
112         binmode STDOUT, ':encoding(UTF-8)' unless $format eq 'csv';
113     }
114
115     if ( $format eq 'iso2709' ) {
116         for my $record_id (@$record_ids) {
117             my $record = _get_record_for_export( { %$params, record_id => $record_id } );
118             my $errorcount_on_decode = eval { scalar( MARC::File::USMARC->decode( $record->as_usmarc )->warnings() ) };
119             if ( $errorcount_on_decode or $@ ) {
120                 my $msg = "Record $record_id could not be exported. " .
121                     ( $@ // '' );
122                 chomp $msg;
123                 Koha::Logger->get->info( $msg );
124                 next;
125             }
126             print $record->as_usmarc();
127         }
128     } elsif ( $format eq 'xml' ) {
129         my $marcflavour = C4::Context->preference("marcflavour");
130         MARC::File::XML->default_record_format( ( $marcflavour eq 'UNIMARC' && $record_type eq 'auths' ) ? 'UNIMARCAUTH' : $marcflavour );
131
132         print MARC::File::XML::header();
133         print "\n";
134         for my $record_id (@$record_ids) {
135             my $record = _get_record_for_export( { %$params, record_id => $record_id } );
136             if( !$record ) {
137                 Koha::Logger->get->info( "Record $record_id could not be exported." );
138                 next;
139             }
140             print MARC::File::XML::record($record);
141             print "\n";
142         }
143         print MARC::File::XML::footer();
144         print "\n";
145     } elsif ( $format eq 'csv' ) {
146         unless ( $csv_profile_id ) {
147             # FIXME export_format.profile should be a unique key
148             my $csv_profiles = Koha::CsvProfiles->search({ profile => C4::Context->preference('ExportWithCsvProfile') });
149             die "The ExportWithCsvProfile system preference is not defined or does not match a valid csv profile" unless $csv_profiles->count;
150             $csv_profile_id = $csv_profiles->next->export_format_id;
151         }
152         print marc2csv( $record_ids, $csv_profile_id, $itemnumbers );
153     }
154
155     close $fh if $output_filepath;
156 }
157
158 1;
159
160 __END__
161
162 =head1 NAME
163
164 Koha::Exporter::Records - module to export records (biblios and authorities)
165
166 =head1 SYNOPSIS
167
168 This module provides a public subroutine to export records as xml, csv or iso2709.
169
170 =head2 FUNCTIONS
171
172 =head3 export
173
174     Koha::Exporter::Record::export($params);
175
176 $params is a hashref with some keys:
177
178 It will displays on STDOUT the generated file.
179
180 =over 4
181
182 =item record_type
183
184   Must be set to 'bibs' or 'auths'
185
186 =item record_ids
187
188   The list of the records to export (a list of biblionumber or authid)
189
190 =item format
191
192   The format must be 'csv', 'xml' or 'iso2709'.
193
194 =item itemnumbers
195
196   Generate the item infos only for these itemnumbers.
197
198   Must only be used with biblios.
199
200 =item export_items
201
202   If this flag is set, the items will be exported.
203   Default is ON.
204
205 =item dont_export_fields
206
207   List of fields not to export.
208
209 =item csv_profile_id
210
211   If the format is csv, a csv_profile_id can be provide to overwrite the default value (syspref ExportWithCsvProfile).
212
213 =cut
214
215 =back
216
217 =head1 LICENSE
218
219 This file is part of Koha.
220
221 Copyright Koha Development Team
222
223 Koha is free software; you can redistribute it and/or modify it
224 under the terms of the GNU General Public License as published by
225 the Free Software Foundation; either version 3 of the License, or
226 (at your option) any later version.
227
228 Koha is distributed in the hope that it will be useful, but
229 WITHOUT ANY WARRANTY; without even the implied warranty of
230 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
231 GNU General Public License for more details.
232
233 You should have received a copy of the GNU General Public License
234 along with Koha; if not, see <http://www.gnu.org/licenses>.