Merge branch 'opencultureconsulting:master' into master

This commit is contained in:
mkancija 2024-10-07 17:44:42 +02:00 committed by GitHub
commit 4b8f92e970
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 227 additions and 46 deletions

12
.editorconfig Normal file
View File

@ -0,0 +1,12 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true

121
.gitattributes vendored Normal file
View File

@ -0,0 +1,121 @@
###
# https://github.com/gitattributes/gitattributes/blob/master/Common.gitattributes
###
# Auto detect text files and perform LF normalization
* text=auto
#
# The above will handle all files NOT found below
#
# Documents
*.bibtex text diff=bibtex
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
*.md text diff=markdown
*.mdx text diff=markdown
*.tex text diff=tex
*.adoc text
*.textile text
*.mustache text
*.csv text eol=crlf
*.tab text
*.tsv text
*.txt text
*.sql text
*.epub diff=astextplain
# Graphics
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.tif binary
*.tiff binary
*.ico binary
# SVG treated as text by default.
*.svg text
# If you want to treat it as binary,
# use the following line instead.
# *.svg binary
*.eps binary
# Scripts
*.bash text eol=lf
*.fish text eol=lf
*.ksh text eol=lf
*.sh text eol=lf
*.zsh text eol=lf
# These are explicitly windows files and should use crlf
*.bat text eol=crlf
*.cmd text eol=crlf
*.ps1 text eol=crlf
# Serialisation
*.json text
*.toml text
*.xml text
*.yaml text
*.yml text
# Archives
*.7z binary
*.gz binary
*.tar binary
*.tgz binary
*.zip binary
# Text files where line endings should be preserved
*.patch -text
#
# Exclude files from exporting
#
.gitattributes export-ignore
.gitignore export-ignore
.gitkeep export-ignore
###
# https://github.com/gitattributes/gitattributes/blob/master/PHP.gitattributes
###
# PHP files
*.php text eol=lf diff=php
*.phpt text eol=lf diff=php
*.phtml text eol=lf diff=html
*.twig text eol=lf
*.phar binary
# Configuration
phpcs.xml text eol=lf
phpunit.xml text eol=lf
phpstan.neon text eol=lf
psalm.xml text eol=lf
###
# Open Culture Consulting custom additions
###
# Configuration
.editorconfig text eol=lf
*.dist.xml text eol=lf
*.xml.dist text eol=lf
*.neon text eol=lf
# Generated documentation
doc/* linguist-generated=true
# Exclude files from exporting
.github/* export-ignore
.phpdoc/* export-ignore
phpdoc.dist.xml export-ignore

9
.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
/.phpdoc/cache/
/.vscode/
/vendor/
.php-cs-fixer.php
phpcs.xml
phpdoc.xml
phpstan.neon
psalm.xml
TODO

View File

@ -24,33 +24,34 @@ namespace OCC\OAI2;
class Exception extends \Exception {
private array $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' => [
'text' => 'The value of the resumptionToken argument is invalid or expired.',
],
'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' => [
'text' => 'The metadata format identified by the value given for the metadataPrefix argument is not supported by the item or by the repository.',
],
'idDoesNotExist' => [
'text' => 'The value of the identifier argument is unknown or illegal in this repository.',
],
'noRecordsMatch' => [
'text' => 'The combination of the values of the from, until, set and metadataPrefix arguments results in an empty list.',
],
'noMetadataFormats' => [
'text' => 'There are no metadata formats available for the specified item.',
],
'noSetHierarchy' => [
'text' => 'The repository does not support sets.',
]
];
public function __construct($code) {
$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' => [
'text' => 'The value of the resumptionToken argument is invalid or expired.',
],
'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' => [
'text' => 'The metadata format identified by the value given for the metadataPrefix argument is not supported by the item or by the repository.',
],
'idDoesNotExist' => [
'text' => 'The value of the identifier argument is unknown or illegal in this repository.',
],
'noRecordsMatch' => [
'text' => 'The combination of the values of the from, until, set and metadataPrefix arguments results in an empty list.',
],
'noMetadataFormats' => [
'text' => 'There are no metadata formats available for the specified item.',
],
'noSetHierarchy' => [
'text' => 'The repository does not support sets.',
],
];
parent::__construct($this->errorTable[$code]['text']);
$this->code = $code;
}

View File

@ -24,7 +24,11 @@ namespace OCC\OAI2;
class Response {
public $doc; // DOMDocument. Handle of current XML Document object
public \DOMDocument $doc; // DOMDocument. Handle of current XML Document object
private string $verb = '';
private \DOMElement $verbNode;
public function __construct($uri, $verb, $request_args) {
if (substr($uri, -1, 1) == '/') {
@ -74,7 +78,7 @@ class Response {
* @param string $nodeName The name of appending node.
* @param string $value The content of appending node.
*/
public function addToVerbNode($nodeName, $value = null) {
public function addToVerbNode($nodeName, $value = '') {
if (!isset($this->verbNode) && !empty($this->verb)) {
$this->verbNode = $this->addChild($this->doc->documentElement, $this->verb);
}

View File

@ -34,6 +34,12 @@ class Server {
private $max_records = 100;
private $token_prefix = '/tmp/oai2-';
private $token_valid = 86400;
private $uri = '';
private $identifyResponse;
private $listMetadataFormatsCallback;
private $listRecordsCallback;
private $getRecordCallback;
private Response $response;
public function __construct($uri, $args, $identifyResponse, $callbacks, $config) {
$this->uri = $uri;
@ -242,7 +248,7 @@ class Server {
if ($records_count - $deliveredRecords > $maxItems) {
$deliveredRecords += $maxItems;
$restoken = $this->createResumptionToken($deliveredRecords, $metadataPrefix, $from, $until);
$expirationDatetime = gmstrftime('%Y-%m-%dT%TZ', time()+$this->token_valid);
$expirationDatetime = date('Y-m-d\TH:i:s\Z', time()+$this->token_valid);
} elseif (isset($this->args['resumptionToken'])) {
// Last delivery, return empty resumptionToken
$restoken = null;
@ -297,10 +303,14 @@ class Server {
}
private function formatTimestamp($datestamp) {
if (is_array($time = strptime($datestamp, '%Y-%m-%dT%H:%M:%SZ')) || is_array($time = strptime($datestamp, '%Y-%m-%d'))) {
return gmmktime($time['tm_hour'], $time['tm_min'], $time['tm_sec'], $time['tm_mon'] + 1, $time['tm_mday'], $time['tm_year']+1900);
} else {
$time = date_parse_from_format('Y-m-d\TH:i:s\Z', $datestamp);
if ($time['error_count'] > 0) {
$time = date_parse_from_format('Y-m-d', $datestamp);
}
if ($time['error_count'] > 0) {
return null;
} else {
return gmmktime($time['hour'], $time['minute'], $time['second'], $time['month'] + 1, $time['day'], $time['year']);
}
}
@ -309,7 +319,7 @@ class Server {
if ($datetime === false) {
$datetime = \DateTime::createFromFormat('Y-m-d', $date);
}
return ($datetime !== false) && !array_sum($datetime->getLastErrors());
return ($datetime !== false);
}
}

View File

@ -1,20 +1,20 @@
# Simple OAI-PMH 2.0 Data Provider
This is a stand-alone and easy to install data provider implementing the [Open Archives Initiative's Protocol for Metadata Harvesting (OAI-PMH)](https://openarchives.org/pmh/). It serves records in any metadata format from directories of XML files using the directory name as `metadataPrefix`, the filename as `identifier` and the filemtime as datestamp. 0-byte files are considered deleted records and handled accordingly. Resumption tokens are managed using files. Sets are currently not supported.
This is a stand-alone and easy to install data provider implementing the [Open Archives Initiative's Protocol for Metadata Harvesting (OAI-PMH)](https://openarchives.org/pmh/). It serves records in any metadata format from directories of XML files using the directory name as `metadataPrefix`, the filename as `identifier` and the filemtime as timestamp. 0-byte files are considered deleted records and handled accordingly. Resumption tokens are managed using files. Sets are currently not supported.
Just put the records as XML files in the data directory, adjust a few configuration settings and you are ready to go!
A demo installation can be found [here](https://demo.opencultureconsulting.com/oai_pmh/?verb=Identify).
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/7a12022611d047ad9ef9a0c3aadb986a)](https://www.codacy.com/gh/opencultureconsulting/oai_pmh)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/7a12022611d047ad9ef9a0c3aadb986a)](https://www.codacy.com/gh/opencultureconsulting/simple-oai-pmh)
## Installation
1. Run `composer create-project opencultureconsulting/oai_pmh <path>`.
1. Run `composer create-project opencultureconsulting/simple-oai-pmh <path>`.
2. Create a data directory in a not publicly accessible location outside of `<path>`. Create a subdirectory inside the specified data directory for every format (i. e. `metadataPrefix`) you want to provide.
2. Create a data directory in a location not publicly accessible (i. e. outside of `<path>`). Create a subdirectory inside the specified data directory for every format (i. e. `metadataPrefix`) you want to provide.
3. Copy `Configuration/Main.template.php` to `Configuration/Main.php` and adjust the settings according to your preferences. Don't forget pointing `$config['dataDirectory']` to your newly created data directory.
3. Copy `Configuration/Main.template.php` to `Configuration/Main.php` and edit the settings according to your preferences. Don't forget pointing `$config['dataDirectory']` to your newly created data directory.
4. Put the records into the respective directories according to their format. Each record has to be a separate XML file with its `identifier` as filename (e. g. the file *12345678.xml* can be adressed using the `identifier` *12345678*). Optionally you can maintain deletions by keeping 0-byte files for deleted records.
@ -24,7 +24,7 @@ A demo installation can be found [here](https://demo.opencultureconsulting.com/o
1. Backup `Configuration/Main.php`!
2. Delete `<path>` and re-install by running `composer create-project opencultureconsulting/oai_pmh <path>`.
2. Delete `<path>` and re-install by running `composer create-project opencultureconsulting/simple-oai-pmh <path>`.
3. Move your configuration back into `Configuration/Main.php`.

View File

@ -165,7 +165,7 @@
<xsl:apply-templates select="/oai:OAI-PMH"/>
<xsl:call-template name="quicklinks"/>
<p class="info">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 <em>view source</em> option or disable XSLT processing.</p>
<p class="info">This XSL script was originally written by Christopher Gutteridge at <a href="https://www.southampton.ac.uk/">University of Southampton</a> for the <a href="https://www.eprints.org/">EPrints</a> project and was later adapted by Sebastian Meyer at <a href="https://www.opencultureconsulting.com/">Open Culture Consulting</a> to be more generally applicable to other OAI-PMH interfaces. It is available on <a href="https://github.com/opencultureconsulting/oai_pmh">GitHub</a> for free!</p>
<p class="info">This XSL script was originally written by Christopher Gutteridge at <a href="https://www.southampton.ac.uk/">University of Southampton</a> for the <a href="https://www.eprints.org/">EPrints</a> project and was later adapted by Sebastian Meyer at <a href="https://www.opencultureconsulting.com/">Open Culture Consulting</a> to be more generally applicable to other OAI-PMH interfaces. It is available on <a href="https://github.com/opencultureconsulting/simple-oai-pmh">GitHub</a> for free!</p>
</body>
</html>
</xsl:template>

View File

@ -1,5 +1,5 @@
{
"name": "opencultureconsulting/oai_pmh",
"name": "opencultureconsulting/simple-oai-pmh",
"description": "This is a stand-alone and easy to install data provider implementing the Open Archives Initiative's Protocol for Metadata Harvesting (OAI-PMH).",
"type": "project",
"keywords": [
@ -9,7 +9,7 @@
"code4lib",
"repository"
],
"homepage": "https://github.com/opencultureconsulting/oai_pmh",
"homepage": "https://github.com/opencultureconsulting/simple-oai-pmh",
"readme": "README.md",
"license": ["GPL-3.0-or-later"],
"authors": [
@ -41,14 +41,17 @@
}
],
"support": {
"issues": "https://github.com/opencultureconsulting/oai_pmh/issues",
"source": "https://github.com/opencultureconsulting/oai_pmh",
"docs": "https://github.com/opencultureconsulting/oai_pmh/blob/master/README.md"
"issues": "https://github.com/opencultureconsulting/simple-oai-pmh/issues",
"source": "https://github.com/opencultureconsulting/simple-oai-pmh",
"docs": "https://github.com/opencultureconsulting/simple-oai-pmh/blob/master/README.md"
},
"require": {
"php": "^7.0",
"php": "7.4.*|8.0.*|8.1.*|8.2.*",
"ext-xml": "*"
},
"replace": {
"opencultureconsulting/oai_pmh": "self.version"
},
"autoload": {
"psr-4": {
"OCC\\OAI2\\": "Classes/"

21
composer.lock generated Normal file
View File

@ -0,0 +1,21 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "af0a24a6f06b7a8dc4ecd3084647403e",
"packages": [],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": "7.4.*|8.0.*|8.1.*|8.2.*",
"ext-xml": "*"
},
"platform-dev": [],
"plugin-api-version": "2.6.0"
}