add GetRecord to OAI request

This commit is contained in:
Arno Kaimbacher 2018-11-27 18:06:11 +01:00
parent f0e84a2991
commit 559dd4ee10
6 changed files with 200 additions and 10 deletions

View File

@ -0,0 +1,12 @@
<?php
namespace App\Exceptions;
use Exception;
/**
* Class GeneralException.
*/
class OaiModelException extends Exception
{
}

View File

@ -5,6 +5,9 @@ use Illuminate\Http\Request;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\Dataset; use App\Models\Dataset;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use App\Exceptions\OaiModelException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use App\Models\OaiModelError;
class RequestController extends Controller class RequestController extends Controller
{ {
@ -65,12 +68,33 @@ class RequestController extends Controller
public function index(Request $request) public function index(Request $request)
{ {
// to handle POST and GET Request, take any given parameter
$oaiRequest = $request->all(); $oaiRequest = $request->all();
$safeRemoveParameters = array('module', 'controller', 'action', 'role'); $safeRemoveParameters = array('module', 'controller', 'action', 'role');
foreach ($safeRemoveParameters as $parameter) { foreach ($safeRemoveParameters as $parameter) {
unset($oaiRequest[$parameter]); unset($oaiRequest[$parameter]);
} }
return $this->__handleRequest($oaiRequest); try {
$this->__handleRequest($oaiRequest);
} catch (OaiModelException $e) {
$errorCode = OaiModelError::mapCode($e->getCode());
//$this->getLogger()->err($errorCode);
$this->_proc->setParameter('', 'oai_error_code', $errorCode);
//$this->getLogger()->err($e->getMessage());
$this->_proc->setParameter('', 'oai_error_message', htmlentities($e->getMessage()));
} catch (Exception $e) {
//$this->getLogger()->err($e);
$this->_proc->setParameter('', 'oai_error_code', 'unknown');
$this->_proc->setParameter('', 'oai_error_message', 'An internal error occured.');
//$this->getResponse()->setHttpResponseCode(500);
}
// $xml = $this->_xml->saveXML();
$xml = $this->_proc->transformToXML($this->_xml);
//$xml = $this->doc->asXML();
return response($xml)//->view('rss', array('rss'=>$this->rss))
->header('Content-Type', 'application/xml')
->header('charset', 'utf-8');
} }
@ -95,6 +119,8 @@ class RequestController extends Controller
$this->handleListMetadataFormats(); $this->handleListMetadataFormats();
} elseif ($oaiRequest['verb'] == 'ListRecords') { } elseif ($oaiRequest['verb'] == 'ListRecords') {
$this->handleListRecords($oaiRequest); $this->handleListRecords($oaiRequest);
} elseif ($oaiRequest['verb'] == 'GetRecord') {
$this->handleGetRecord($oaiRequest);
} elseif ($oaiRequest['verb'] == 'ListIdentifiers') { } elseif ($oaiRequest['verb'] == 'ListIdentifiers') {
$this->handleListIdentifiers($oaiRequest); $this->handleListIdentifiers($oaiRequest);
} elseif ($oaiRequest['verb'] == 'ListSets') { } elseif ($oaiRequest['verb'] == 'ListSets') {
@ -107,14 +133,6 @@ class RequestController extends Controller
$this->_proc->setParameter('', 'oai_verb', $oaiRequest['verb']); $this->_proc->setParameter('', 'oai_verb', $oaiRequest['verb']);
$this->doc = $this->handleIdentify(); $this->doc = $this->handleIdentify();
} }
//$xml = $this->_xml->saveXML();
$xml = $this->_proc->transformToXML($this->_xml);
//$xml = $this->doc->asXML();
return response($xml)//->view('rss', array('rss'=>$this->rss))
->header('Content-Type', 'application/xml')
->header('charset', 'utf-8');
} }
/** /**
@ -139,6 +157,89 @@ class RequestController extends Controller
$this->_xml->appendChild($this->_xml->createElement('Documents')); $this->_xml->appendChild($this->_xml->createElement('Documents'));
} }
/**
* Implements response for OAI-PMH verb 'GetRecord'.
*
* @param array &$oaiRequest Contains full request information
* @return void
*/
private function handleGetRecord(array &$oaiRequest)
{
// Identifier references metadata Urn, not plain Id!
// Currently implemented as 'oai:foo.bar.de:{docId}' or 'urn:nbn...-123'
$dataId = $this->getDocumentIdByIdentifier($oaiRequest['identifier']);
$dataset = null;
try {
//$dataset = new Opus_Document($docId);
$dataset = Dataset::findOrFail($dataId);
} catch (ModelNotFoundException $ex) {
throw new OaiModelException(
'The value of the identifier argument is unknown or illegal in this repository.',
OaiModelError::IDDOESNOTEXIST
);
}
$metadataPrefix = $oaiRequest['metadataPrefix'];
// do not deliver datasets which are restricted by document state
if (is_null($dataset)
//or (false === in_array($dataset->getServerState(), $this->_deliveringDocumentStates))
or (false === $dataset->whereIn('server_state', $this->deliveringDocumentStates))
or (false === $dataset->hasEmbargoPassed())) {
throw new OaiModelException('Document is not available for OAI export!', OaiModelError::NORECORDSMATCH);
}
$this->_xml->appendChild($this->_xml->createElement('Documents'));
$this->createXmlRecord($dataset);
}
/**
* Retrieve a document id by an oai identifier.
*
* @param string $oaiIdentifier
* @result int
*/
private function getDocumentIdByIdentifier($oaiIdentifier)
{
$identifierParts = explode(":", $oaiIdentifier);
$dataId = null;
switch ($identifierParts[0]) {
// case 'urn':
// //$finder = new Opus_DocumentFinder();
// $finder = Dataset::query();
// // $finder->setIdentifierTypeValue('urn', $oaiIdentifier);
// // $finder->setServerStateInList($this->_deliveringDocumentStates);
// $finder->whereIn('server_state', $this->deliveringDocumentStates);
// $docIds = $finder->ids();
// $docId = $docIds[0];
// break;
case 'oai':
if (isset($identifierParts[2])) {
$dataId = $identifierParts[2];
}
break;
default:
throw new OaiModelException(
'The prefix of the identifier argument is unknown.',
OaiModelError::BADARGUMENT
);
break;
}
if (empty($dataId) or !preg_match('/^\d+$/', $dataId)) {
throw new Oai_Model_Exception(
'The value of the identifier argument is unknown or illegal in this repository.',
Oai_Model_Error::IDDOESNOTEXIST
);
}
return $dataId;
}

View File

@ -11,6 +11,7 @@ use App\Models\Person;
use App\Models\XmlCache; use App\Models\XmlCache;
use App\Models\File; use App\Models\File;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;
class Dataset extends Model class Dataset extends Model
{ {
@ -40,6 +41,7 @@ class Dataset extends Model
'server_date_created', 'server_date_created',
'server_date_modified', 'server_date_modified',
'server_date_published', 'server_date_published',
'embargo_date',
]; ];
//protected $dateFormat = 'Y-m-d'; //protected $dateFormat = 'Y-m-d';
@ -209,4 +211,31 @@ class Dataset extends Model
{ {
return $this->project()->exists(); return $this->project()->exists();
} }
public function hasEmbargoPassed($now = null)
{
$embargoDate = $this->embargo_date;
if (is_null($embargoDate)) {
return true;
}
if (is_null($now)) {
$now = $dt = Carbon::now();
}
// Embargo has passed on the day after the specified date
// $embargoDate->setHour(23);
// $embargoDate->setMinute(59);
// $embargoDate->setSecond(59);
// $embargoDate->setTimezone('Z');
// $dt->year = 2015;
// $dt->month = 04;
// $dt->day = 21;
$embargoDate->hour = 23;
$embargoDate->minute = 59;
$embargoDate->second = 59;
return ($embargoDate->gt($now) == true);
}
} }

View File

@ -0,0 +1,42 @@
<?php
namespace App\Models;
class OaiModelError
{
/**
* Define all valid error codes.
*/
const BADVERB = 1010;
const BADARGUMENT = 1011;
const CANNOTDISSEMINATEFORMAT = 1012;
const BADRESUMPTIONTOKEN = 1013;
const NORECORDSMATCH = 1014;
const IDDOESNOTEXIST = 1015;
/**
* Holds OAI error codes for internal error numbers.
*
* @var array Valid OAI parameters.
*/
protected static $oaiErrorCodes = array(
self::BADVERB => 'badVerb',
self::BADARGUMENT => 'badArgument',
self::NORECORDSMATCH => 'noRecordsMatch',
self::CANNOTDISSEMINATEFORMAT => 'cannotDisseminateFormat',
self::BADRESUMPTIONTOKEN => 'badResumptionToken',
self::IDDOESNOTEXIST => 'idDoesNotExist',
);
/**
* Map internal error codes to OAI error codes.
*
* @param int $code Internal error code.
* @return string OAI error code.
*/
public static function mapCode($code)
{
if (false === array_key_exists($code, self::$oaiErrorCodes)) {
throw new Oai_Model_Exception("Unknown oai error code $code");
}
return self::$oaiErrorCodes[$code];
}
}

View File

@ -323,6 +323,6 @@ return [
// URLs which should not be processed, e.g. '/nova', '/nova/*', '/nova-api/*' or specific application URLs // URLs which should not be processed, e.g. '/nova', '/nova/*', '/nova-api/*' or specific application URLs
// Defaults to [] // Defaults to []
'urlsIgnored' => ['/skipped', '/settings', '/settings/*'], 'urlsIgnored' => ['/skipped', '/settings', '/settings/*', '/oai'],
]; ];

View File

@ -214,6 +214,12 @@
</xsl:if> </xsl:if>
</xsl:template> </xsl:template>
<xsl:template match="Documents" mode="GetRecord">
<GetRecord>
<xsl:apply-templates select="Rdr_Dataset" />
</GetRecord>
</xsl:template>
<xsl:template match="Rdr_Dataset"> <xsl:template match="Rdr_Dataset">
<xsl:choose> <xsl:choose>
<xsl:when test="$oai_verb='ListIdentifiers'"> <xsl:when test="$oai_verb='ListIdentifiers'">