diff --git a/oai2exception.php b/Classes/OAI2Exception.php similarity index 82% rename from oai2exception.php rename to Classes/OAI2Exception.php index 0cbfaf9..1416181 100644 --- a/oai2exception.php +++ b/Classes/OAI2Exception.php @@ -23,32 +23,32 @@ class OAI2Exception extends Exception { public function __construct($code) { - $this->errorTable = array( - 'badArgument' => array( + $this->errorTable = [ + 'badArgument' => [ 'text' => 'The request includes illegal arguments, is missing required arguments, includes a repeated argument, or values for arguments have an illegal syntax.', - ), - 'badResumptionToken' => array( + ], + 'badResumptionToken' => [ 'text' => 'The value of the resumptionToken argument is invalid or expired.', - ), - 'badVerb' => array( + ], + 'badVerb' => [ 'text' => 'Value of the verb argument is not a legal OAI-PMH verb, the verb argument is missing, or the verb argument is repeated.', - ), - 'cannotDisseminateFormat' => array( + ], + 'cannotDisseminateFormat' => [ 'text' => 'The metadata format identified by the value given for the metadataPrefix argument is not supported by the item or by the repository.', - ), - 'idDoesNotExist' => array( + ], + 'idDoesNotExist' => [ 'text' => 'The value of the identifier argument is unknown or illegal in this repository.', - ), - 'noRecordsMatch' => array( + ], + 'noRecordsMatch' => [ 'text' => 'The combination of the values of the from, until, set and metadataPrefix arguments results in an empty list.', - ), - 'noMetadataFormats' => array( + ], + 'noMetadataFormats' => [ 'text' => 'There are no metadata formats available for the specified item.', - ), - 'noSetHierarchy' => array( + ], + 'noSetHierarchy' => [ 'text' => 'The repository does not support sets.', - ), - ); + ], + ]; parent::__construct($this->errorTable[$code]['text']); $this->code = $code; } diff --git a/Classes/OAI2Response.php b/Classes/OAI2Response.php new file mode 100644 index 0000000..475a8ee --- /dev/null +++ b/Classes/OAI2Response.php @@ -0,0 +1,137 @@ + + * Copyright (C) 2011 Jianfeng Li + * Copyright (C) 2013 Daniel Neis Araujo + * Copyright (C) 2017 Sebastian Meyer + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 this program. If not, see . + */ + +class OAI2Response { + + public $doc; // DOMDocument. Handle of current XML Document object + + public function __construct($uri, $verb, $request_args) { + if (substr($uri, -1, 1) == '/') { + $stylesheet = $uri.'Resources/Stylesheet.xsl'; + } else { + $stylesheet = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') ? 'https://' : 'http://'; + $stylesheet .= $_SERVER['HTTP_HOST'].pathinfo(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), PATHINFO_DIRNAME).'/Resources/Stylesheet.xsl'; + } + $this->verb = $verb; + $this->doc = new DOMDocument('1.0', 'UTF-8'); + $this->doc->appendChild($this->doc->createProcessingInstruction('xml-stylesheet', 'type="text/xsl" href="'.$stylesheet.'"')); + $oai_node = $this->doc->createElement('OAI-PMH'); + $oai_node->setAttribute('xmlns', 'http://www.openarchives.org/OAI/2.0/'); + $oai_node->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); + $oai_node->setAttribute('xsi:schemaLocation', 'http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd'); + $this->addChild($oai_node, 'responseDate', gmdate('Y-m-d\TH:i:s\Z')); + $this->doc->appendChild($oai_node); + $request = $this->addChild($this->doc->documentElement, 'request', $uri); + if (!empty($this->verb)) { + $request->setAttribute('verb', $this->verb); + } + foreach($request_args as $key => $value) { + $request->setAttribute($key, $value); + } + } + + /** + * Add a child node to a parent node on a XML Doc: a worker function. + * + * @param DOMNode $mom_node The target node. + * @param string $name The name of child node is being added. + * @param string $value Text for the adding node if it is a text node. + * + * @return DOMElement $added_node * The newly created node + */ + public function addChild($mom_node, $name, $value = '') { + $added_node = $this->doc->createElement($name, $value); + $added_node = $mom_node->appendChild($added_node); + return $added_node; + } + + /** + * Add direct child nodes to verb node (OAI-PMH), e.g. response to ListMetadataFormats. + * Different verbs can have different required child nodes. + * @see createHeader, importFragment + * + * @param string $nodeName The name of appending node. + * @param string $value The content of appending node. + */ + public function addToVerbNode($nodeName, $value = null) { + if (!isset($this->verbNode) && !empty($this->verb)) { + $this->verbNode = $this->addChild($this->doc->documentElement, $this->verb); + } + return $this->addChild($this->verbNode, $nodeName, $value); + } + + /** + * Headers are enclosed inside of to the query of ListRecords, ListIdentifiers and etc. + * + * @param string $identifier The identifier string for node . + * @param string $timestamp Timestamp in UTC format for node . + * @param boolean $deleted Deleted status for the record. + * @param DOMElement $add_to_node Default value is null. + * In normal cases, $add_to_node is the node created previously. + * When it is null, the newly created header node is attatched to $this->verbNode. + * Otherwise it will be attached to the desired node defined in $add_to_node. + */ + public function createHeader($identifier, $timestamp, $deleted = false, $add_to_node = null) { + if(is_null($add_to_node)) { + $header_node = $this->addToVerbNode('header'); + } else { + $header_node = $this->addChild($add_to_node, 'header'); + } + $this->addChild($header_node, 'identifier', $identifier); + $this->addChild($header_node, 'datestamp', $timestamp); + if($deleted) { + $header_node->setAttribute('status', 'deleted'); + } + return $header_node; + } + + /** + * If there are too many records request could not finished a resumpToken is generated to let harvester know + * + * @param string $token A random number created somewhere? + * @param string $expirationdatetime A string representing time. + * @param integer $num_rows Number of records retrieved. + * @param string $cursor Cursor can be used for database to retrieve next time. + */ + public function createResumptionToken($token, $expirationdatetime, $num_rows, $cursor = null) { + $resump_node = $this->addChild($this->verbNode, 'resumptionToken', $token); + if(isset($expirationdatetime)) { + $resump_node->setAttribute('expirationDate', $expirationdatetime); + } + $resump_node->setAttribute('completeListSize', $num_rows); + $resump_node->setAttribute('cursor', $cursor); + } + + /** + * Imports a XML fragment into a parent node on a XML Doc: a worker function. + * + * @param DOMNode $mom_node The target node. + * @param DOMDocument $fragment The XML fragment is being added. + * + * @return DOMElement $added_node * The newly created node + */ + public function importFragment($mom_node, $fragment) { + $added_node = $mom_node->appendChild($this->doc->importNode($fragment->documentElement, true)); + return $added_node; + } + +} diff --git a/oai2server.php b/Classes/OAI2Server.php similarity index 95% rename from oai2server.php rename to Classes/OAI2Server.php index 9381fba..23afe21 100644 --- a/oai2server.php +++ b/Classes/OAI2Server.php @@ -20,8 +20,8 @@ * along with this program. If not, see . */ -require_once('oai2exception.php'); -require_once('oai2xml.php'); +require_once './OAI2Exception.php'; +require_once './OAI2Response.php'; /** * This is an implementation of OAI Data Provider version 2.0. @@ -29,17 +29,16 @@ require_once('oai2xml.php'); */ class OAI2Server { - public $errors = array(); - private $args = array(); + public $errors = []; + private $args = []; private $verb = ''; - private $deleted_record = 'transient'; private $max_records = 100; private $token_prefix = '/tmp/oai2-'; private $token_valid = 86400; public function __construct($uri, $args, $identifyResponse, $callbacks, $config) { $this->uri = $uri; - $verbs = array('Identify', 'ListMetadataFormats', 'ListSets', 'ListIdentifiers', 'ListRecords', 'GetRecord'); + $verbs = ['Identify', 'ListMetadataFormats', 'ListSets', 'ListIdentifiers', 'ListRecords', 'GetRecord']; if (empty($args['verb']) || !in_array($args['verb'], $verbs)) { $this->errors[] = new OAI2Exception('badVerb'); return; @@ -51,19 +50,18 @@ class OAI2Server { $this->listMetadataFormatsCallback = $callbacks['ListMetadataFormats']; $this->listRecordsCallback = $callbacks['ListRecords']; $this->getRecordCallback = $callbacks['GetRecord']; - $this->deleted_record = $config['deletedRecord']; $this->max_records = $config['maxRecords']; $this->token_prefix = $config['tokenPrefix']; $this->token_valid = $config['tokenValid']; - $this->response = new OAI2XMLResponse($this->uri, $this->verb, $this->args); - call_user_func(array($this, $this->verb)); + $this->response = new OAI2Response($this->uri, $this->verb, $this->args); + call_user_func([$this, $this->verb]); } public function response() { if (empty($this->errors)) { return $this->response->doc; } - $errorResponse = new OAI2XMLResponse($this->uri, $this->verb, $this->args); + $errorResponse = new OAI2Response($this->uri, $this->verb, $this->args); $oai_node = $errorResponse->doc->documentElement; foreach($this->errors as $e) { $node = $errorResponse->addChild($oai_node, 'error', $e->getMessage()); @@ -222,7 +220,7 @@ class OAI2Server { $restoken = $this->createResumptionToken($deliveredRecords, $metadataPrefix, $from, $until); $expirationDatetime = gmstrftime('%Y-%m-%dT%TZ', time()+$this->token_valid); } elseif (isset($this->args['resumptionToken'])) { - // Last delivery, return empty ResumptionToken + // Last delivery, return empty resumptionToken $restoken = null; $expirationDatetime = null; } diff --git a/Configuration/Main.php b/Configuration/Main.php new file mode 100644 index 0000000..488671c --- /dev/null +++ b/Configuration/Main.php @@ -0,0 +1,76 @@ + + * Copyright (C) 2011 Jianfeng Li + * Copyright (C) 2013 Daniel Neis Araujo + * Copyright (C) 2017 Sebastian Meyer + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 this program. If not, see . + */ + +/** + * This file contains all configuration you need to change according to your preferences + * @see http://www.openarchives.org/OAI/2.0/openarchivesprotocol.htm for further explanation + */ + +$config = [ + + // A human readable name for the repository + 'repositoryName' => 'Simple OAI 2.0 Data Provider', + + // Email address for contacting the repository owner + 'adminEmail' => 'admin@example.org', + + // Do you provide 0-byte files for deleted records? + // + // Possible values: + // "no" -> the repository does not maintain information about deletions + // "transient" -> the repository maintains information about deletions, but + // does not guarantee them to be persistent (default) + // "persistent" -> the repository maintains information about deletions with + // no time limit + 'deletedRecord' => 'transient', + + // Metadata formats, schemas and namespaces of your records + // + // The default is 'oai_dc' which is also required by the OAI-PMH specification, + // but technically you can deliver any XML based data format you want. Just add + // another entry with the 'metadataPrefix' as key and schema/namespace URIs as + // array values or replace the default 'oai_dc' entry (not recommended). + 'metadataPrefix' => [ + 'oai_dc' => [ + 'schema' => 'http://www.openarchives.org/OAI/2.0/oai_dc.xsd', + 'namespace' => 'http://www.openarchives.org/OAI/2.0/oai_dc/', + ], + ], + + // Directory containing the records + // + // Make sure the given path is readable and there is a subdirectory for every + // 'metadataPrefix' you specified above. + 'dataDirectory' => './Data/', + + // Maximum number of records to return before giving a resumption token + 'maxRecords' => 100, + + // Absolute path and filename prefix for saving resumption tokens + // + // Make sure the given path is writable. + 'tokenPrefix' => '/tmp/oai2-', + + // Number of seconds a resumption token should be valid + 'tokenValid' => 86400, // 24 hours + +]; diff --git a/README.md b/README.md index 9798920..084f4d1 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ A demo installation can be found [here](https://demo.opencultureconsulting.com/o 1. Deploy all the files to a webserver. -2. Edit `config.php` and adjust the settings according to your preferences. +2. Edit `Configuration/Main.php` and adjust the settings according to your preferences. 3. Create a subdirectory inside the specified data directory for every format (i. e. `metadataPrefix`) you want to provide. diff --git a/oai2transform.xsl b/Resources/Stylesheet.xsl similarity index 98% rename from oai2transform.xsl rename to Resources/Stylesheet.xsl index a3efa9d..116375d 100644 --- a/oai2transform.xsl +++ b/Resources/Stylesheet.xsl @@ -164,7 +164,7 @@

You are viewing an HTML version of the XML OAI-PMH response. To see the underlying XML as it appears to any OAI-PMH harvester use your web browser's view source option or disable XSLT processing.

-

This XSL script was originally written by Christopher Gutteridge at University of Southampton for the EPrints project and was later adapted by Sebastian Meyer at Open Culture Consulting to be more generally applicable to other OAI-PMH interfaces. It is available on GitHub for free!

+

This XSL script was originally written by Christopher Gutteridge at University of Southampton for the EPrints project and was later adapted by Sebastian Meyer at Open Culture Consulting to be more generally applicable to other OAI-PMH interfaces. It is available on GitHub for free!

diff --git a/config.php b/config.php deleted file mode 100644 index d0be1e7..0000000 --- a/config.php +++ /dev/null @@ -1,74 +0,0 @@ - - * Copyright (C) 2011 Jianfeng Li - * Copyright (C) 2013 Daniel Neis Araujo - * Copyright (C) 2017 Sebastian Meyer - * - * This program 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 3 of the License, or - * (at your option) any later version. - * - * This program 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 this program. If not, see . - */ - -/** - * This file contains all configuration you need to change according to your preferences - * @see http://www.openarchives.org/OAI/2.0/openarchivesprotocol.htm for further explanation - */ - -$config = array(); - -// A human readable name for the repository -$config['repositoryName'] = 'Simple OAI 2.0 Data Provider'; - -// Email address for contacting the repository owner -$config['adminEmail'] = 'admin@example.org'; - -// Do you provide 0-byte files for deleted records? -// -// Possible values: -// "no" -> the repository does not maintain information about deletions -// "transient" -> the repository maintains information about deletions, but -// does not guarantee them to be persistent (default) -// "persistent" -> the repository maintains information about deletions with -// no time limit -$config['deletedRecord'] = 'transient'; - -// Metadata formats, schemas and namespaces of your records -// -// The default is 'oai_dc' which is also required by the OAI-PMH specification, -// but technically you can deliver any XML based data format you want. Just add -// another entry with the 'metadataPrefix' as key and schema/namespace URIs as -// array values or replace the default 'oai_dc' entry (not recommended). -$config['metadataPrefix'] = array( - 'oai_dc' => array( - 'schema' => 'http://www.openarchives.org/OAI/2.0/oai_dc.xsd', - 'namespace' => 'http://www.openarchives.org/OAI/2.0/oai_dc/', - ), -); - -// Directory containing the records -// -// Make sure the given path is readable and there is a subdirectory for every -// 'metadataPrefix' you specified above. -$config['dataDirectory'] = 'data/'; - -// Maximum number of records to return before giving a resumption token -$config['maxRecords'] = 100; - -// Path and prefix for saving resumption tokens -// -// Make sure the given path is writable. -$config['tokenPrefix'] = '/tmp/oai2-'; - -// Number of seconds a resumption token should be valid -$config['tokenValid'] = 86400; // 24 hours diff --git a/index.php b/index.php index 3df4976..1fcd74c 100644 --- a/index.php +++ b/index.php @@ -20,121 +20,118 @@ * along with this program. If not, see . */ -require_once('config.php'); -require_once('oai2server.php'); +require_once './Configuration/Main.php'; +require_once './Classes/OAI2Server.php'; // Get all available records and their respective status and timestamps -$records = array(); -$deleted = array(); -$timestamps = array(); +$records = []; +$deleted = []; +$timestamps = []; $earliest = time(); -foreach($config['metadataPrefix'] as $prefix => $uris) { - $files = glob(rtrim($config['dataDirectory'], '/').'/'.$prefix.'/*.xml'); - foreach($files as $file) { - $records[$prefix][pathinfo($file, PATHINFO_FILENAME)] = $file; - $deleted[$prefix][pathinfo($file, PATHINFO_FILENAME)] = !filesize($file); - $timestamps[$prefix][filemtime($file)][] = pathinfo($file, PATHINFO_FILENAME); - if (filemtime($file) < $earliest) { - $earliest = filemtime($file); +foreach ($config['metadataPrefix'] as $prefix => $uris) { + $files = glob(rtrim($config['dataDirectory'], '/').'/'.$prefix.'/*.xml'); + foreach ($files as $file) { + $records[$prefix][pathinfo($file, PATHINFO_FILENAME)] = $file; + $deleted[$prefix][pathinfo($file, PATHINFO_FILENAME)] = !filesize($file); + $timestamps[$prefix][filemtime($file)][] = pathinfo($file, PATHINFO_FILENAME); + if (filemtime($file) < $earliest) { + $earliest = filemtime($file); + } } - } - ksort($records[$prefix]); - reset($records[$prefix]); - ksort($timestamps[$prefix]); - reset($timestamps[$prefix]); + ksort($records[$prefix]); + reset($records[$prefix]); + ksort($timestamps[$prefix]); + reset($timestamps[$prefix]); } // Get current base URL $baseURL = $_SERVER['HTTP_HOST'].parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') { - $baseURL = 'https://'.$baseURL; + $baseURL = 'https://'.$baseURL; } else { - $baseURL = 'http://'.$baseURL; + $baseURL = 'http://'.$baseURL; } // Build the Identify response -$identifyResponse = array( - 'repositoryName' => $config['repositoryName'], - 'baseURL' => $baseURL, - 'protocolVersion' => '2.0', - 'adminEmail' => $config['adminEmail'], - 'earliestDatestamp' => gmdate('Y-m-d\TH:i:s\Z', $earliest), - 'deletedRecord' => $config['deletedRecord'], - 'granularity' => 'YYYY-MM-DDThh:mm:ssZ' -); +$identifyResponse = [ + 'repositoryName' => $config['repositoryName'], + 'baseURL' => $baseURL, + 'protocolVersion' => '2.0', + 'adminEmail' => $config['adminEmail'], + 'earliestDatestamp' => gmdate('Y-m-d\TH:i:s\Z', $earliest), + 'deletedRecord' => $config['deletedRecord'], + 'granularity' => 'YYYY-MM-DDThh:mm:ssZ' +]; $oai2 = new OAI2Server( - $baseURL, - $_GET, - $identifyResponse, - array( - 'GetRecord' => - function($identifier, $metadataPrefix) { - global $records, $deleted; - if (empty($records[$metadataPrefix][$identifier])) { - return array(); - } else { - return array( - 'identifier' => $identifier, - 'timestamp' => filemtime($records[$metadataPrefix][$identifier]), - 'deleted' => $deleted[$metadataPrefix][$identifier], - 'metadata' => $records[$metadataPrefix][$identifier] - ); - } - }, - 'ListRecords' => - function($metadataPrefix, $from = null, $until = null, $count = false, $deliveredRecords = 0, $maxItems = 100) { - global $records, $deleted, $timestamps; - $resultSet = array(); - foreach($timestamps[$metadataPrefix] as $timestamp => $identifiers) { - if ((is_null($from) || $timestamp >= $from) && (is_null($until) || $timestamp <= $until)) { - foreach($identifiers as $identifier) { - $resultSet[] = array( - 'identifier' => $identifier, - 'timestamp' => filemtime($records[$metadataPrefix][$identifier]), - 'deleted' => $deleted[$metadataPrefix][$identifier], - 'metadata' => $records[$metadataPrefix][$identifier] - ); - } + $baseURL, + $_GET, + $identifyResponse, + [ + 'GetRecord' => function ($identifier, $metadataPrefix) { + global $records, $deleted; + if (empty($records[$metadataPrefix][$identifier])) { + return []; + } else { + return [ + 'identifier' => $identifier, + 'timestamp' => filemtime($records[$metadataPrefix][$identifier]), + 'deleted' => $deleted[$metadataPrefix][$identifier], + 'metadata' => $records[$metadataPrefix][$identifier] + ]; + } + }, + 'ListRecords' => function ($metadataPrefix, $from = null, $until = null, $count = false, $deliveredRecords = 0, $maxItems = 100) { + global $records, $deleted, $timestamps; + $resultSet = []; + foreach ($timestamps[$metadataPrefix] as $timestamp => $identifiers) { + if ((is_null($from) || $timestamp >= $from) && (is_null($until) || $timestamp <= $until)) { + foreach ($identifiers as $identifier) { + $resultSet[] = [ + 'identifier' => $identifier, + 'timestamp' => filemtime($records[$metadataPrefix][$identifier]), + 'deleted' => $deleted[$metadataPrefix][$identifier], + 'metadata' => $records[$metadataPrefix][$identifier] + ]; + } + } + } + if ($count) { + return count($resultSet); + } else { + return array_slice($resultSet, $deliveredRecords, $maxItems); + } + }, + 'ListMetadataFormats' => function ($identifier = '') { + global $config, $records; + if (!empty($identifier)) { + $formats = []; + foreach ($records as $format => $record) { + if (!empty($record[$identifier])) { + $formats[$format] = $config['metadataPrefix'][$format]; + } + } + if (!empty($formats)) { + return $formats; + } else { + throw new OAI2Exception('idDoesNotExist'); + } + } else { + return $config['metadataPrefix']; + } } - } - if ($count) { - return count($resultSet); - } else { - return array_slice($resultSet, $deliveredRecords, $maxItems); - } - }, - 'ListMetadataFormats' => - function($identifier = '') { - global $config, $records; - if (!empty($identifier)) { - $formats = array(); - foreach($records as $format => $record) { - if (!empty($record[$identifier])) { - $formats[$format] = $config['metadataPrefix'][$format]; - } - } - if (!empty($formats)) { - return $formats; - } else { - throw new OAI2Exception('idDoesNotExist'); - } - } else { - return $config['metadataPrefix']; - } - } - ), - $config + ], + $config ); $response = $oai2->response(); if (isset($return)) { - return $response; + return $response; } else { - $response->formatOutput = true; - $response->preserveWhiteSpace = false; - header('Content-Type: text/xml'); - echo $response->saveXML(); + $response->formatOutput = true; + $response->preserveWhiteSpace = false; + header('Content-Type: text/xml'); + echo $response->saveXML(); } diff --git a/oai2xml.php b/oai2xml.php deleted file mode 100644 index e12e282..0000000 --- a/oai2xml.php +++ /dev/null @@ -1,137 +0,0 @@ - - * Copyright (C) 2011 Jianfeng Li - * Copyright (C) 2013 Daniel Neis Araujo - * Copyright (C) 2017 Sebastian Meyer - * - * This program 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 3 of the License, or - * (at your option) any later version. - * - * This program 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 this program. If not, see . - */ - -class OAI2XMLResponse { - - public $doc; // DOMDocument. Handle of current XML Document object - - public function __construct($uri, $verb, $request_args) { - if (substr($uri, -1, 1) == '/') { - $stylesheet = $uri.'oai2transform.xsl'; - } else { - $stylesheet = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') ? 'https://' : 'http://'; - $stylesheet .= $_SERVER['HTTP_HOST'].pathinfo(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), PATHINFO_DIRNAME).'/oai2transform.xsl'; - } - $this->verb = $verb; - $this->doc = new DOMDocument('1.0', 'UTF-8'); - $this->doc->appendChild($this->doc->createProcessingInstruction('xml-stylesheet', 'type="text/xsl" href="'.$stylesheet.'"')); - $oai_node = $this->doc->createElement('OAI-PMH'); - $oai_node->setAttribute('xmlns', 'http://www.openarchives.org/OAI/2.0/'); - $oai_node->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); - $oai_node->setAttribute('xsi:schemaLocation', 'http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd'); - $this->addChild($oai_node, 'responseDate', gmdate('Y-m-d\TH:i:s\Z')); - $this->doc->appendChild($oai_node); - $request = $this->addChild($this->doc->documentElement, 'request', $uri); - if (!empty($this->verb)) { - $request->setAttribute('verb', $this->verb); - } - foreach($request_args as $key => $value) { - $request->setAttribute($key, $value); - } - } - - /** - * Add a child node to a parent node on a XML Doc: a worker function. - * - * @param $mom_node Type: DOMNode. The target node. - * @param $name Type: string. The name of child node is being added - * @param $value Type: string. Text for the adding node if it is a text node. - * - * @return DOMElement $added_node * The newly created node - */ - function addChild($mom_node, $name, $value = '') { - $added_node = $this->doc->createElement($name, $value); - $added_node = $mom_node->appendChild($added_node); - return $added_node; - } - - /** - * Add direct child nodes to verb node (OAI-PMH), e.g. response to ListMetadataFormats. - * Different verbs can have different required child nodes. - * @see createHeader, importFragment - * - * @param $nodeName Type: string. The name of appending node. - * @param $value Type: string. The content of appending node. - */ - function addToVerbNode($nodeName, $value = null) { - if (!isset($this->verbNode) && !empty($this->verb)) { - $this->verbNode = $this->addChild($this->doc->documentElement, $this->verb); - } - return $this->addChild($this->verbNode, $nodeName, $value); - } - - /** - * Headers are enclosed inside of to the query of ListRecords, ListIdentifiers and etc. - * - * @param $identifier Type: string. The identifier string for node . - * @param $timestamp Type: timestamp. Timestamp in UTC format for node . - * @param $deleted Type: boolean. Deleted status for the record. - * @param $add_to_node Type: DOMElement. Default value is null. - * In normal cases, $add_to_node is the node created previously. - * When it is null, the newly created header node is attatched to $this->verbNode. - * Otherwise it will be attached to the desired node defined in $add_to_node. - */ - function createHeader($identifier, $timestamp, $deleted = false, $add_to_node = null) { - if(is_null($add_to_node)) { - $header_node = $this->addToVerbNode('header'); - } else { - $header_node = $this->addChild($add_to_node, 'header'); - } - $this->addChild($header_node, 'identifier', $identifier); - $this->addChild($header_node, 'datestamp', $timestamp); - if($deleted) { - $header_node->setAttribute('status', 'deleted'); - } - return $header_node; - } - - /** - * If there are too many records request could not finished a resumpToken is generated to let harvester know - * - * @param $token Type: string. A random number created somewhere? - * @param $expirationdatetime Type: string. A string representing time. - * @param $num_rows Type: integer. Number of records retrieved. - * @param $cursor Type: string. Cursor can be used for database to retrieve next time. - */ - function createResumptionToken($token, $expirationdatetime, $num_rows, $cursor = null) { - $resump_node = $this->addChild($this->verbNode, 'resumptionToken', $token); - if(isset($expirationdatetime)) { - $resump_node->setAttribute('expirationDate', $expirationdatetime); - } - $resump_node->setAttribute('completeListSize', $num_rows); - $resump_node->setAttribute('cursor', $cursor); - } - - /** - * Imports a XML fragment into a parent node on a XML Doc: a worker function. - * - * @param $mom_node Type: DOMNode. The target node. - * @param $fragment Type: DOMDocument. The XML fragment is being added - * - * @return DOMElement $added_node * The newly created node - */ - function importFragment($mom_node, $fragment) { - $added_node = $mom_node->appendChild($this->doc->importNode($fragment->documentElement, true)); - return $added_node; - } - -} diff --git a/update.php b/update.php index 0277389..7a6d555 100644 --- a/update.php +++ b/update.php @@ -20,7 +20,7 @@ // Make this script only executable via commandline interface! if (php_sapi_name() !== 'cli') exit; -require_once('config.php'); +require_once './Configuration/Main.php'; /** * Format output string