1 package OpenILS::WWW::Exporter;
7 use Apache2::Const -compile => qw(OK REDIRECT DECLINED NOT_FOUND :log);
8 use APR::Const -compile => qw(:error SUCCESS);
11 use Apache2::RequestRec ();
12 use Apache2::RequestIO ();
13 use Apache2::RequestUtil;
18 use OpenSRF::EX qw(:try);
19 use OpenSRF::Utils qw/:datetime/;
20 use OpenSRF::Utils::Cache;
22 use OpenSRF::AppSession;
27 use Unicode::Normalize;
28 use OpenILS::Utils::Fieldmapper;
29 use OpenSRF::Utils::Logger qw/$logger/;
34 use UNIVERSAL::require;
36 our @formats = qw/USMARC UNIMARC XML BRE/;
38 # set the bootstrap config and template include directory when
39 # this module is loaded
49 OpenSRF::System->bootstrap_client( config_file => $bootstrap );
59 @records = $cgi->param('id');
61 if (!@records) { # try for a file
62 my $file = $cgi->param('idfile');
64 my $col = $cgi->param('idcolumn') || 0;
65 my $csv = new Text::CSV;
71 my @data = $csv->fields;
81 if (!@records) { # try pathinfo
82 my $path_rec = $cgi->path_info();
84 @records = map { $_ ? ($_) : () } split '/', $path_rec;
88 return show_template($r) unless (@records);
90 my $type = $cgi->param('rectype') || 'biblio';
91 if ($type ne 'biblio' && $type ne 'authority') {
92 die "Bad record type: $type";
95 my $tcn_v = 'tcn_value';
96 my $tcn_s = 'tcn_source';
98 if ($type eq 'authority') {
100 $tcn_s = 'arn_source';
103 my $holdings = $cgi->param('holdings') if ($type eq 'biblio');
104 my $location = $cgi->param('location') || 'gaaagpl'; # just because...
106 my $format = $cgi->param('format') || 'USMARC';
107 $format = uc($format);
109 my $encoding = $cgi->param('encoding') || 'UTF-8';
110 $encoding = uc($encoding);
112 my $filename = $cgi->param('filename') || "export.$type.$encoding.$format";
114 binmode(STDOUT, ':raw') if ($encoding ne 'UTF-8');
115 binmode(STDOUT, ':utf8') if ($encoding eq 'UTF-8');
117 if (!grep { uc($format) eq $_ } @formats) {
118 die "Please select a supported format. ".
119 "Right now that means one of [".
120 join('|',@formats). "]\n";
123 if ($format ne 'XML') {
124 my $ftype = 'MARC::File::' . $format;
128 my $ses = OpenSRF::AppSession->create('open-ils.cstore');
130 $r->headers_out->set("Content-Disposition" => "inline; filename=$filename");
132 if (uc($format) eq 'XML') {
133 $r->content_type('application/xml');
135 $r->content_type('application/octet-stream');
138 $r->print( <<" HEADER" ) if (uc($format) eq 'XML');
139 <?xml version="1.0" encoding="$encoding"?>
140 <collection xmlns='http://www.loc.gov/MARC21/slim'>
149 my $req = $ses->request( 'open-ils.cstore.direct.actor.org_unit.search', { id => { '!=' => undef } } );
151 while (my $o = $req->recv) {
152 die $req->failed->stringify if ($req->failed);
159 $req = $ses->request( 'open-ils.cstore.direct.asset.copy_location.search', { id => { '!=' => undef } } );
161 while (my $s = $req->recv) {
162 die $req->failed->stringify if ($req->failed);
165 $shelves{$s->id} = $s;
169 $flesh = { flesh => 2, flesh_fields => { bre => [ 'call_numbers' ], acn => [ 'copies' ] } };
172 for my $i ( @records ) {
175 local $SIG{ALRM} = sub { die "TIMEOUT\n" };
177 $bib = $ses->request( "open-ils.cstore.direct.$type.record_entry.retrieve", $i, $flesh )->gather(1);
180 warn "\n!!!!!! Timed out trying to read record $i\n";
186 if (uc($format) eq 'BRE') {
187 $r->print( OpenSRF::Utils::JSON->perl2JSON($bib) );
193 my $req = MARC::Record->new_from_xml( $bib->marc, $encoding, $format );
194 $req->delete_field( $_ ) for ($req->field(901));
207 my $cn_list = $bib->call_numbers;
208 if ($cn_list && @$cn_list) {
210 my $cp_list = [ map { @{ $_->copies } } @$cn_list ];
211 if ($cp_list && @$cp_list) {
214 push @{$cn_map{$_->call_number}}, $_ for (@$cp_list);
216 for my $cn ( @$cn_list ) {
217 my $cn_map_list = $cn_map{$cn->id};
219 for my $cp ( @$cn_map_list ) {
225 b => $orgs{$cn->owning_lib}->shortname,
226 b => $orgs{$cp->circ_lib}->shortname,
227 c => $shelves{$cp->location}->name,
229 ($cp->circ_modifier ? ( g => $cp->circ_modifier ) : ()),
231 ($cp->price ? ( y => $cp->price ) : ()),
232 ($cp->copy_number ? ( t => $cp->copy_number ) : ()),
233 ($cp->ref eq 't' ? ( x => 'reference' ) : ()),
234 ($cp->holdable eq 'f' ? ( x => 'unholdable' ) : ()),
235 ($cp->circulate eq 'f' ? ( x => 'noncirculating' ) : ()),
236 ($cp->opac_visible eq 'f' ? ( x => 'hidden' ) : ()),
246 if (uc($format) eq 'XML') {
247 my $x = $req->as_xml_record;
248 $x =~ s/^<\?xml version="1.0" encoding="UTF-8"\?>//o;
250 } elsif (uc($format) eq 'UNIMARC') {
251 $r->print($req->as_unimarc);
252 } elsif (uc($format) eq 'USMARC') {
253 $r->print($req->as_usmarc);
263 $r->print("</collection>\n") if ($format eq 'XML');
265 return Apache2::Const::OK;
272 $r->content_type('text/html');
277 <title>Record Export</title>
280 <form method="POST" enctype="multipart/form-data">
281 Use field number <input type="text" size="2" maxlength="2" name="idcolumn" value="0"/> (starting from 0)
282 from CSV file <input type="file" name="idfile"/>
283 <br/><br/> <b>or</b> <br/><br/>
284 Record ID <input type="text" size="12" maxlength="12" name="id"/>
285 <br/><br/> Record Type:
287 <option value="biblio">Bibliographic Records</option>
288 <option value="authority">Authority Records</option>
290 <br/><br/> Record Fromat:
291 <select name="format">
292 <option value="USMARC">MARC21</option>
293 <option value="UNIMARC">UNIMARC</option>
294 <option value="XML">MARC XML</option>
295 <option value="BRE">Evergreen BRE</option>
297 <br/><br/> Record Encoding:
298 <select name="encoding">
299 <option value="UTF-8">UTF-8</option>
300 <option value="MARC8">MARC8</option>
302 <br/><br/> Include holdings in Bibliographic Records:
303 <input type="checkbox" name="holdings" value="1">
304 <br/><input type="submit" value="Retrieve Records"/>
311 return Apache2::Const::OK;