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_request );
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;
36 use CGI qw/:standard -oldstyle_urls/;
38 use C4::XSLT qw( transformMARCXML4XSLT );
44 Koha::OAI::Server::Repository - Handles OAI-PMH requests for a Koha database.
48 use Koha::OAI::Server::Repository;
50 my $repository = Koha::OAI::Server::Repository->new();
54 This object extend HTTP::OAI::Repository object.
55 It accepts OAI-PMH HTTP requests and returns result.
57 This OAI-PMH server can operate in a simple mode and extended one.
59 In simple mode, repository configuration comes entirely from Koha system
60 preferences (OAI-PMH:archiveID and OAI-PMH:MaxCount) and the server returns
61 records in marcxml or dublin core format. Dublin core records are created from
62 koha marcxml records transformed with XSLT. Used XSL file is located in koha-
63 tmpl/intranet-tmpl/prog/en/xslt directory and chosen based on marcflavour,
64 respecively MARC21slim2OAIDC.xsl for MARC21 and MARC21slim2OAIDC.xsl for
67 In extended mode, it's possible to parameter other format than marcxml or
68 Dublin Core. A new syspref OAI-PMH:ConfFile specify a YAML configuration file
69 which list available metadata formats and XSL file used to create them from
70 marcxml records. If this syspref isn't set, Koha OAI server works in simple
71 mode. A configuration file koha-oai.conf can look like that:
77 metadataNamespace: http://veryspecial.tamil.fr/vs/format-pivot/1.1/vs
78 schema: http://veryspecial.tamil.fr/vs/format-pivot/1.1/vs.xsd
79 xsl_file: /usr/local/koha/xslt/vs.xsl
81 metadataPrefix: marc21
82 metadataNamespace: http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim
83 schema: http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd
86 metadataPrefix: marcxml
87 metadataNamespace: http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim
88 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->{ xslt_engine } = Koha::XSLT::Base->new;
111 # Load configuration file if defined in OAI-PMH:ConfFile syspref
112 if ( my $file = C4::Context->preference("OAI-PMH:ConfFile") ) {
113 $self->{ conf } = YAML::XS::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 my $sth = C4::Context->dbh->prepare('SELECT @@session.time_zone');
122 my ( $orig_tz ) = $sth->fetchrow();
123 $self->{ mysql_orig_tz } = $orig_tz;
124 C4::Context->dbh->prepare("SET time_zone='+00:00'")->execute();
126 # Check for grammatical errors in the request
127 my @errs = validate_request( CGI::Vars() );
129 # Is metadataPrefix supported by the repository?
130 my $mdp = param('metadataPrefix') || '';
131 if ( $mdp && !grep { $_ eq $mdp } @{$self->{ koha_metadata_format }} ) {
132 push @errs, HTTP::OAI::Error->new(
133 code => 'cannotDisseminateFormat',
134 message => "Dissemination as '$mdp' is not supported",
140 $response = HTTP::OAI::Response->new(
141 requestURL => self_url(),
146 my %attr = CGI::Vars();
147 my $verb = delete $attr{verb};
148 my $class = "Koha::OAI::Server::$verb";
149 $response = $class->new($self, %attr);
152 $response->set_handler( XML::SAX::Writer->new( Output => *STDOUT ) );
153 $response->xslt( "/opac-tmpl/xslt/OAI.xslt" );
164 # Reset time zone to the original value
165 C4::Context->dbh->prepare("SET time_zone='" . $self->{ mysql_orig_tz } . "'")->execute()
166 if $self->{ mysql_orig_tz };
170 sub get_biblio_marcxml {
171 my ( $self, $biblionumber, $format ) = @_;
173 my $expanded_avs = 0;
174 if ( my $conf = $self->{conf} ) {
175 $with_items = $conf->{format}->{$format}->{include_items };
176 $expanded_avs = $conf->{format}->{$format}->{expanded_avs};
179 my $biblio = Koha::Biblios->find($biblionumber);
180 my $record = $biblio->metadata->record({ embed_items => $with_items, opac => 1 });
181 $record = transformMARCXML4XSLT( $biblionumber, $record )
184 return $record ? $record->as_xml_record() : undef;
189 my ( $self, $format ) = @_;
190 my $xsl_file = $self->{ conf }
191 ? $self->{ conf }->{ format }->{ $format }->{ xsl_file }
192 : ( C4::Context->config('intrahtdocs') .
194 C4::Context->preference('marcflavour') .
202 my ( $self, $format ) = @_;
204 if ( my $conf = $self->{ conf } ) {
205 return $conf->{ format }->{ $format }->{ include_items };