1 # Copyright Tamil s.a.r.l. 2008-2015
2 # Copyright Biblibre 2008-2015
3 # Copyright The National Library of Finland, University of Helsinki 2016
5 # This file is part of Koha.
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
20 package Koha::OAI::Server::Repository;
24 use HTTP::OAI::Repository qw/:validate/;
26 use base ("HTTP::OAI::Repository");
28 use Koha::OAI::Server::Identify;
29 use Koha::OAI::Server::ListSets;
30 use Koha::OAI::Server::ListMetadataFormats;
31 use Koha::OAI::Server::GetRecord;
32 use Koha::OAI::Server::ListRecords;
33 use Koha::OAI::Server::ListIdentifiers;
37 use YAML::Syck qw( LoadFile );
38 use CGI qw/:standard -oldstyle_urls/;
45 Koha::OAI::Server::Repository - Handles OAI-PMH requests for a Koha database.
49 use Koha::OAI::Server::Repository;
51 my $repository = Koha::OAI::Server::Repository->new();
55 This object extend HTTP::OAI::Repository object.
56 It accepts OAI-PMH HTTP requests and returns result.
58 This OAI-PMH server can operate in a simple mode and extended one.
60 In simple mode, repository configuration comes entirely from Koha system
61 preferences (OAI-PMH:archiveID and OAI-PMH:MaxCount) and the server returns
62 records in marcxml or dublin core format. Dublin core records are created from
63 koha marcxml records transformed with XSLT. Used XSL file is located in koha-
64 tmpl/intranet-tmpl/prog/en/xslt directory and chosen based on marcflavour,
65 respecively MARC21slim2OAIDC.xsl for MARC21 and MARC21slim2OAIDC.xsl for
68 In extended mode, it's possible to parameter other format than marcxml or
69 Dublin Core. A new syspref OAI-PMH:ConfFile specify a YAML configuration file
70 which list available metadata formats and XSL file used to create them from
71 marcxml records. If this syspref isn't set, Koha OAI server works in simple
72 mode. A configuration file koha-oai.conf can look like that:
78 metadataNamespace: http://veryspecial.tamil.fr/vs/format-pivot/1.1/vs
79 schema: http://veryspecial.tamil.fr/vs/format-pivot/1.1/vs.xsd
80 xsl_file: /usr/local/koha/xslt/vs.xsl
82 metadataPrefix: marc21
83 metadataNamespace: http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim
84 schema: http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd
87 metadataPrefix: marxml
88 metadataNamespace: http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim
89 schema: http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd
92 metadataPrefix: oai_dc
93 metadataNamespace: http://www.openarchives.org/OAI/2.0/oai_dc/
94 schema: http://www.openarchives.org/OAI/2.0/oai_dc.xsd
95 xsl_file: /usr/local/koha/koha-tmpl/intranet-tmpl/xslt/UNIMARCslim2OAIDC.xsl
97 Note the 'include_items' parameter which is the only mean to return item-level info.
103 my ($class, %args) = @_;
104 my $self = $class->SUPER::new(%args);
106 $self->{ koha_identifier } = C4::Context->preference("OAI-PMH:archiveID");
107 $self->{ koha_max_count } = C4::Context->preference("OAI-PMH:MaxCount");
108 $self->{ koha_metadata_format } = ['oai_dc', 'marc21', 'marcxml'];
109 $self->{ koha_stylesheet } = { }; # Build when needed
111 # Load configuration file if defined in OAI-PMH:ConfFile syspref
112 if ( my $file = C4::Context->preference("OAI-PMH:ConfFile") ) {
113 $self->{ conf } = LoadFile( $file );
114 my @formats = keys %{ $self->{conf}->{format} };
115 $self->{ koha_metadata_format } = \@formats;
118 # OAI-PMH handles dates in UTC, so do that on the database level to avoid need for
120 C4::Context->dbh->prepare("SET time_zone='+00:00'")->execute();
122 # Check for grammatical errors in the request
123 my @errs = validate_request( CGI::Vars() );
125 # Is metadataPrefix supported by the repository?
126 my $mdp = param('metadataPrefix') || '';
127 if ( $mdp && !grep { $_ eq $mdp } @{$self->{ koha_metadata_format }} ) {
128 push @errs, new HTTP::OAI::Error(
129 code => 'cannotDisseminateFormat',
130 message => "Dissemination as '$mdp' is not supported",
136 $response = HTTP::OAI::Response->new(
137 requestURL => self_url(),
142 my %attr = CGI::Vars();
143 my $verb = delete $attr{verb};
144 my $class = "Koha::OAI::Server::$verb";
145 $response = $class->new($self, %attr);
148 $response->set_handler( XML::SAX::Writer->new( Output => *STDOUT ) );
149 $response->xslt( "/opac-tmpl/xslt/OAI.xslt" );
157 sub get_biblio_marcxml {
158 my ($self, $biblionumber, $format) = @_;
160 if ( my $conf = $self->{conf} ) {
161 $with_items = $conf->{format}->{$format}->{include_items};
163 my $record = GetMarcBiblio($biblionumber, $with_items, 1);
164 $record ? $record->as_xml_record() : undef;
169 my ( $self, $format ) = @_;
171 my $stylesheet = $self->{ koha_stylesheet }->{ $format };
172 unless ( $stylesheet ) {
173 my $xsl_file = $self->{ conf }
174 ? $self->{ conf }->{ format }->{ $format }->{ xsl_file }
175 : ( C4::Context->config('intrahtdocs') .
177 C4::Context->preference('marcflavour') .
179 $xsl_file || die( "No stylesheet found for $format" );
180 my $parser = XML::LibXML->new();
181 my $xslt = XML::LibXSLT->new();
182 my $style_doc = $parser->parse_file( $xsl_file );
183 $stylesheet = $xslt->parse_stylesheet( $style_doc );
184 $self->{ koha_stylesheet }->{ $format } = $stylesheet;
192 my ( $self, $format ) = @_;
194 if ( my $conf = $self->{ conf } ) {
195 return $conf->{ format }->{ $format }->{ include_items };