X-Git-Url: http://koha-dev.rot13.org:8081/gitweb/?a=blobdiff_plain;f=opac%2Funapi;h=0f97eced35a304946d03a2fcaf08462641d7a67c;hb=8ded191629fc2c113bcd7e995f87e409990e763d;hp=b6d03b3369d37dbe08b126a7a013fda1c7ccdb99;hpb=4d3519dffdb54dd6e9d9d701cb0edb0cc724f8dd;p=koha_fer diff --git a/opac/unapi b/opac/unapi index b6d03b3369..0f97eced35 100755 --- a/opac/unapi +++ b/opac/unapi @@ -1,75 +1,207 @@ #!/usr/bin/perl -use CGI; + +# Copyright 2008-2009 LibLime +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + use strict; use warnings; + +=head1 NAME + +unapi - implement unAPI for the OPAC + +=head1 SYNOPSIS + +Retrieve http://library.example.org/cgi-bin/koha/unapi?id=koha:biblionumber:123&format=oai_dc + +=head1 DESCRIPTION + +Implements unAPI , a small HTTP API for retrieving structured +content from a web application. The primary application of unAPI in Koha is to +allow tools such as Zotero to identify and grab bibliographic record metadata in +an XML format such as OAI DC, RSS2, MARCXML, or MODS. + +=cut + +use CGI; use C4::Context; -use XML::Simple; -use LWP::Simple; +use C4::Biblio; +use XML::LibXML; +use XML::LibXSLT; + +my $cgi = CGI->new(); +binmode(STDOUT, ":encoding(UTF-8)"); #output as utf8 + +=head1 VARIABLES + +=head2 $format_to_stylesheet_map + +This hashref of hashrefs maps from a MARC flavour and unAPI format +to the stylesheet that should be used to transform the bib MARCXML +to the desired output format. As new MARC XSLT stylesheets are added, +(particularly for UNIMARC), this map should be updated. Of course, +if/when we add support for emitting a format that is not genreated +by a stylesheet, the structure of this variable will have to be changed. +At present, this doubles as the list of output formats supported by +this unAPI implementation. -use LWP::UserAgent; -use HTTP::Request::Common; +=cut -my $cgi = new CGI; -binmode(STDOUT, "utf8"); #output as utf8 -my $baseurl = C4::Context->preference('OPACBaseURL'); -warn "Warning: OPACBaseURL not set in system preferences" unless $baseurl; +my $format_to_stylesheet_map = { + 'MARC21' => { + 'marcxml' => 'identity.xsl', + 'marcxml-full' => 'identity.xsl', + 'mods' => 'MARC21slim2MODS.xsl', + 'mods-full' => 'MARC21slim2MODS.xsl', + 'mods3' => 'MARC21slim2MODS3-1.xsl', + 'mods3-full' => 'MARC21slim2MODS3-1.xsl', + 'oai_dc' => 'MARC21slim2OAIDC.xsl', + 'rdfdc', => 'MARC21slim2RDFDC.xsl', + 'rss2' => 'MARC21slim2RSS2.xsl', + 'rss2-full' => 'MARC21slim2RSS2.xsl', + 'srw_dc' => 'MARC21slim2SRWDC.xsl', + }, + 'UNIMARC' => { + 'marcxml' => 'identity.xsl', + 'marcxml-full' => 'identity.xsl', + 'oai_dc' => 'UNIMARCslim2OAIDC.xsl', + }, +}; -my $id = $cgi->param('id'); +=head2 $format_info + +This hashref maps from unAPI output formats to the elements +used to describe them in an unAPI format request. + +=cut + +my $format_info = { + 'marcxml' => q(), + 'marcxml-full' => q(), + 'mods' => q(), + 'mods-full' => q(), + 'mods3' => q(), + 'mods3-full' => q(), + 'oai_dc' => q(), + 'rdfdc' => q(), + 'rss2' => q(), + 'rss2-full' => q(), + 'srw_dc' => q(), +}; + +my $id = $cgi->param('id'); my $format = $cgi->param('format'); -if ($id && $format) { - # koha:isbn:0152018484 - if ($id =~ /isbn/) { - $id =~ s/koha:isbn://; +if (not defined $format) { + emit_formats($id); +} elsif ($id) { - # two ways to do this, one via the SRU Zebra server (fast) - my $url = "http://$baseurl:9998/biblios?version=1.1&operation=searchRetrieve&query=$id&startRecord=1&maximumRecords=20&recordSchema=$format"; - my $content= get($url); + # koha:biblionumber:0152018484 + if ($id =~ /koha:biblionumber:(\d+)/) { + my $biblionumber = $1; - # the other via XSL parsing (not as fast) - unless ($content) { - + my $content; eval { - my $conn = C4::Context->Zconn('biblioserver'); - $conn->option(preferredRecordSyntax => $format); - my $rs = $conn->search_pqf('@attr 1=7 '.$id); - my $n = $rs->size(); - $content = $rs->record(0)->raw(); + my $marcxml = GetXmlBiblio($biblionumber); + unless (defined $marcxml) { + # no bib, so 404 + print $cgi->header( -status => '404 record not found'); + exit 0; + } + + my $transformer = get_transformer($format); + unless (defined $transformer) { + print $cgi->header( -status => '406 invalid format requested' ); + exit 0; + } + my $parser = XML::LibXML->new(); + my $record_dom = $parser->parse_string( $marcxml ); + $record_dom = $transformer->transform( $record_dom ); + $content = $record_dom->toString(); }; if ($@) { - print "Error ", $@->code(), ": ", $@->message(), "\n"; + print $cgi->header( -status => '500 internal error ' . $@->code() . ": " . $@->message() ); + exit 0; } - } print $cgi->header( -type =>'application/xml' ); print $content; + } else { + # ID is obviously wrong, so 404 + print $cgi->header( -status => '404 record not found'); + exit 0; } +} else { + # supplied a format but no id - caller is doing it wrong + print $cgi->header( -status => '400 bad request - if you specify format, must specify id'); + exit 0; } -else { - -print $cgi->header( -type =>'application/xml' ); - -print " - - - - - - - - - - - - - - - - - - - - -"; +exit 0; + +sub emit_formats { + my $id = shift; + + if (defined $id) { + print $cgi->header( -type =>'application/xml', -status => '300 multiple choices' ); + } else { + print $cgi->header( -type =>'application/xml' ); + } + + print "\n"; + if (defined $id) { + print qq(\n); + } else { + print "\n"; + } + + my $marcflavour = uc(C4::Context->preference('marcflavour')); + foreach my $format (sort keys %{ $format_to_stylesheet_map->{$marcflavour} }) { + print $format_info->{$format}, "\n"; + } + print "\n"; + return; } + + +sub get_transformer { + my $format = lc shift; + + my $marcflavour = uc(C4::Context->preference('marcflavour')); + return unless $format_to_stylesheet_map->{$marcflavour}->{$format}; + + my $xslt_file = C4::Context->config('intranetdir') . + "/koha-tmpl/intranet-tmpl/prog/en/xslt/" . + $format_to_stylesheet_map->{$marcflavour}->{$format}; + + my $parser = XML::LibXML->new(); + my $xslt = XML::LibXSLT->new(); + my $style_doc = $parser->parse_file( $xslt_file ); + my $stylesheet = $xslt->parse_stylesheet( $style_doc ); + + return $stylesheet; +} + +=head1 AUTHOR + +Koha Development Team + +Originally written by Joshua Ferraro + +Improved by Galen Charlton + +=cut