2018-08-06 12:30:51 +00:00
|
|
|
<?php
|
|
|
|
namespace App\Http\Controllers\Oai;
|
|
|
|
|
2020-03-26 08:11:12 +00:00
|
|
|
use App\Exceptions\OaiModelException;
|
2018-08-06 12:30:51 +00:00
|
|
|
use App\Http\Controllers\Controller;
|
2018-09-10 13:09:10 +00:00
|
|
|
use App\Models\Dataset;
|
2020-05-18 17:36:31 +00:00
|
|
|
use App\Models\Project;
|
2020-05-07 17:29:18 +00:00
|
|
|
use App\Models\Oai\Configuration as OaiModelConfiguration;
|
2018-12-10 16:26:57 +00:00
|
|
|
use App\Models\Oai\OaiModelError;
|
2020-05-07 17:29:18 +00:00
|
|
|
use App\Models\Oai\ResumptionTokens;
|
2018-12-10 16:26:57 +00:00
|
|
|
use App\Models\Oai\ResumptionToken;
|
2020-03-26 08:11:12 +00:00
|
|
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
|
|
|
use Illuminate\Http\Request;
|
|
|
|
use Illuminate\Support\Facades\Log;
|
2020-03-05 08:47:01 +00:00
|
|
|
use \Exception;
|
2020-05-07 17:29:18 +00:00
|
|
|
use Carbon\Carbon;
|
2020-03-26 08:11:12 +00:00
|
|
|
|
2018-08-06 12:30:51 +00:00
|
|
|
class RequestController extends Controller
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Holds information about which dataset state aka server_state
|
|
|
|
* are delivered out
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
2020-03-26 08:11:12 +00:00
|
|
|
private $deliveringDocumentStates = array('published', 'deleted'); // maybe deleted documents too
|
2020-04-16 20:29:26 +00:00
|
|
|
//private $xMetaDissRestriction = array('doctoralthesis', 'habilitation');
|
2018-08-06 12:30:51 +00:00
|
|
|
const SET_SPEC_PATTERN = '[A-Za-z0-9\-_\.!~\*\'\(\)]+';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Holds xml representation of document information to be processed.
|
|
|
|
*
|
|
|
|
* @var \DomDocument Defaults to null.
|
|
|
|
*/
|
2020-03-26 08:11:12 +00:00
|
|
|
protected $xml = null;
|
2018-08-06 12:30:51 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Holds the stylesheet for the transformation.
|
|
|
|
*
|
|
|
|
* @var \DomDocument Defaults to null.
|
|
|
|
*/
|
2018-09-10 13:09:10 +00:00
|
|
|
protected $xslt = null;
|
2018-08-06 12:30:51 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Holds the xslt processor.
|
|
|
|
*
|
|
|
|
* @var \XSLTProcessor Defaults to null.
|
|
|
|
*/
|
2020-03-26 08:11:12 +00:00
|
|
|
protected $proc = null;
|
2018-08-06 12:30:51 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Load an xslt stylesheet.
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
private function loadStyleSheet($stylesheet)
|
|
|
|
{
|
2018-09-10 13:09:10 +00:00
|
|
|
$this->xslt = new \DomDocument;
|
|
|
|
$this->xslt->load($stylesheet);
|
2020-03-26 08:11:12 +00:00
|
|
|
$this->proc->importStyleSheet($this->xslt);
|
2018-08-06 12:30:51 +00:00
|
|
|
if (isset($_SERVER['HTTP_HOST'])) {
|
2020-03-26 08:11:12 +00:00
|
|
|
$this->proc->setParameter('', 'host', $_SERVER['HTTP_HOST']);
|
2018-08-06 12:30:51 +00:00
|
|
|
}
|
2020-03-26 08:11:12 +00:00
|
|
|
//$this->proc->setParameter('', 'server', $this->getRequest()->getBaseUrl());
|
2018-08-06 12:30:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function __construct()
|
|
|
|
{
|
|
|
|
//$this->middleware('auth');
|
|
|
|
// Initialize member variables.
|
2020-06-08 14:04:32 +00:00
|
|
|
$this->xml = new \DomDocument();
|
|
|
|
$this->proc = new \XSLTProcessor();
|
2020-05-07 17:29:18 +00:00
|
|
|
|
|
|
|
$this->configuration = new OaiModelConfiguration();
|
2018-08-06 12:30:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function index(Request $request)
|
|
|
|
{
|
2018-11-27 17:06:11 +00:00
|
|
|
// to handle POST and GET Request, take any given parameter
|
2018-08-06 12:30:51 +00:00
|
|
|
$oaiRequest = $request->all();
|
2020-04-06 20:28:28 +00:00
|
|
|
if ($oaiRequest == null) {
|
|
|
|
return view('oai.index');
|
|
|
|
}
|
2018-08-06 12:30:51 +00:00
|
|
|
$safeRemoveParameters = array('module', 'controller', 'action', 'role');
|
|
|
|
foreach ($safeRemoveParameters as $parameter) {
|
|
|
|
unset($oaiRequest[$parameter]);
|
|
|
|
}
|
2018-11-27 17:06:11 +00:00
|
|
|
try {
|
|
|
|
$this->__handleRequest($oaiRequest);
|
|
|
|
} catch (OaiModelException $e) {
|
|
|
|
$errorCode = OaiModelError::mapCode($e->getCode());
|
|
|
|
//$this->getLogger()->err($errorCode);
|
2020-03-26 08:11:12 +00:00
|
|
|
$this->proc->setParameter('', 'oai_error_code', $errorCode);
|
2018-11-27 17:06:11 +00:00
|
|
|
//$this->getLogger()->err($e->getMessage());
|
2020-03-26 08:11:12 +00:00
|
|
|
$this->proc->setParameter('', 'oai_error_message', htmlentities($e->getMessage()));
|
2018-11-27 17:06:11 +00:00
|
|
|
} catch (Exception $e) {
|
|
|
|
//$this->getLogger()->err($e);
|
2020-03-26 08:11:12 +00:00
|
|
|
$this->proc->setParameter('', 'oai_error_code', 'unknown');
|
|
|
|
$this->proc->setParameter('', 'oai_error_message', 'An internal error occured.');
|
2018-11-27 17:06:11 +00:00
|
|
|
//$this->getResponse()->setHttpResponseCode(500);
|
|
|
|
}
|
2020-03-26 08:11:12 +00:00
|
|
|
// $xml = $this->xml->saveXML();
|
|
|
|
$xml = $this->proc->transformToXML($this->xml);
|
2018-11-27 17:06:11 +00:00
|
|
|
|
2020-03-26 08:11:12 +00:00
|
|
|
//$xml = $this->doc->asXML();
|
|
|
|
return response($xml) //->view('rss', array('rss'=>$this->rss))
|
|
|
|
->header('Content-Type', 'application/xml')
|
|
|
|
->header('charset', 'utf-8');
|
2018-08-06 12:30:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private function __handleRequest(array $oaiRequest)
|
|
|
|
{
|
2020-03-26 08:11:12 +00:00
|
|
|
// Setup stylesheet
|
2018-12-10 16:26:57 +00:00
|
|
|
$this->loadStyleSheet('datasetxml2oai-pmh.xslt');
|
2018-08-06 12:30:51 +00:00
|
|
|
|
|
|
|
// Set response time
|
2020-03-26 08:11:12 +00:00
|
|
|
$this->proc->setParameter('', 'responseDate', date("Y-m-d\TH:i:s\Z"));
|
2020-06-08 14:04:32 +00:00
|
|
|
// set timestamp
|
|
|
|
$date = new \DateTime();
|
|
|
|
$unixTimestamp = $date->getTimestamp();
|
|
|
|
$this->proc->setParameter('', 'unixTimestamp', $unixTimestamp);
|
2018-08-06 12:30:51 +00:00
|
|
|
|
|
|
|
// set OAI base url
|
|
|
|
$uri = explode('?', $_SERVER['REQUEST_URI'], 2);
|
2020-03-26 08:11:12 +00:00
|
|
|
$this->proc->setParameter('', 'baseURL', url('/') . $uri[0]);
|
2020-05-18 17:36:31 +00:00
|
|
|
$this->proc->setParameter('', 'repURL', url('/'));
|
2020-10-13 15:19:26 +00:00
|
|
|
$this->proc->setParameter('', 'downloadLink', url('/') . '/file/download/');
|
2021-06-10 14:15:01 +00:00
|
|
|
$this->proc->setParameter('', 'doiLink', 'https://doi.org/');
|
2018-08-06 12:30:51 +00:00
|
|
|
|
2020-05-07 17:29:18 +00:00
|
|
|
// $resumptionPath = $this->configuration->getResumptionTokenPath();
|
|
|
|
|
2018-08-06 12:30:51 +00:00
|
|
|
if (isset($oaiRequest['verb'])) {
|
2020-03-26 08:11:12 +00:00
|
|
|
$this->proc->setParameter('', 'oai_verb', $oaiRequest['verb']);
|
2018-08-06 12:30:51 +00:00
|
|
|
if ($oaiRequest['verb'] == 'Identify') {
|
2018-09-10 13:09:10 +00:00
|
|
|
$this->handleIdentify();
|
2018-08-06 12:30:51 +00:00
|
|
|
} elseif ($oaiRequest['verb'] == 'ListMetadataFormats') {
|
2018-09-10 13:09:10 +00:00
|
|
|
$this->handleListMetadataFormats();
|
2018-08-06 12:30:51 +00:00
|
|
|
} elseif ($oaiRequest['verb'] == 'ListRecords') {
|
2018-09-10 13:09:10 +00:00
|
|
|
$this->handleListRecords($oaiRequest);
|
2018-11-27 17:06:11 +00:00
|
|
|
} elseif ($oaiRequest['verb'] == 'GetRecord') {
|
|
|
|
$this->handleGetRecord($oaiRequest);
|
2018-08-06 12:30:51 +00:00
|
|
|
} elseif ($oaiRequest['verb'] == 'ListIdentifiers') {
|
2018-09-10 13:09:10 +00:00
|
|
|
$this->handleListIdentifiers($oaiRequest);
|
2018-08-06 12:30:51 +00:00
|
|
|
} elseif ($oaiRequest['verb'] == 'ListSets') {
|
2018-09-10 13:09:10 +00:00
|
|
|
$this->handleListSets($oaiRequest);
|
2018-08-06 12:30:51 +00:00
|
|
|
} else {
|
2018-09-10 13:09:10 +00:00
|
|
|
$this->handleIllegalVerb();
|
2018-08-06 12:30:51 +00:00
|
|
|
}
|
|
|
|
} else {
|
2020-07-15 15:37:27 +00:00
|
|
|
// $oaiRequest['verb'] = 'Identify';
|
|
|
|
// $this->proc->setParameter('', 'oai_verb', $oaiRequest['verb']);
|
|
|
|
// $this->doc = $this->handleIdentify();
|
|
|
|
throw new OaiModelException('The verb provided in the request is illegal.', OaiModelError::BADVERB);
|
2018-08-06 12:30:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implements response for OAI-PMH verb 'Identify'.
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
2018-09-10 13:09:10 +00:00
|
|
|
private function handleIdentify()
|
2018-08-06 12:30:51 +00:00
|
|
|
{
|
|
|
|
$email = "repository@geologie.ac.at";
|
2020-03-05 08:47:01 +00:00
|
|
|
$repositoryName = "Tethys RDR";
|
2020-04-01 08:33:55 +00:00
|
|
|
$repIdentifier = "tethys.at";
|
2020-05-26 19:46:06 +00:00
|
|
|
$sampleIdentifier = "oai:" . $repIdentifier . ":1"; //$this->_configuration->getSampleIdentifier();
|
2020-03-26 08:11:12 +00:00
|
|
|
$earliestDateFromDb = Dataset::earliestPublicationDate() != null ?
|
2020-04-01 08:33:55 +00:00
|
|
|
Dataset::earliestPublicationDate()->server_date_published->format('Y-m-d\TH:i:s\Z') : null;
|
2018-08-06 12:30:51 +00:00
|
|
|
|
|
|
|
// set parameters for oai-pmh.xslt
|
2020-03-26 08:11:12 +00:00
|
|
|
$this->proc->setParameter('', 'email', $email);
|
|
|
|
$this->proc->setParameter('', 'repositoryName', $repositoryName);
|
|
|
|
$this->proc->setParameter('', 'repIdentifier', $repIdentifier);
|
|
|
|
$this->proc->setParameter('', 'sampleIdentifier', $sampleIdentifier);
|
|
|
|
$this->proc->setParameter('', 'earliestDatestamp', $earliestDateFromDb);
|
|
|
|
$this->xml->appendChild($this->xml->createElement('Datasets'));
|
2018-08-06 12:30:51 +00:00
|
|
|
}
|
|
|
|
|
2018-11-27 17:06:11 +00:00
|
|
|
/**
|
|
|
|
* Implements response for OAI-PMH verb 'GetRecord'.
|
|
|
|
*
|
|
|
|
* @param array &$oaiRequest Contains full request information
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
private function handleGetRecord(array &$oaiRequest)
|
|
|
|
{
|
2020-04-16 20:29:26 +00:00
|
|
|
$repIdentifier = "tethys.at";
|
|
|
|
$this->proc->setParameter('', 'repIdentifier', $repIdentifier);
|
2020-07-15 15:37:27 +00:00
|
|
|
|
2018-11-27 17:06:11 +00:00
|
|
|
// Identifier references metadata Urn, not plain Id!
|
|
|
|
// Currently implemented as 'oai:foo.bar.de:{docId}' or 'urn:nbn...-123'
|
2020-07-15 15:37:27 +00:00
|
|
|
if (!array_key_exists('identifier', $oaiRequest)) {
|
|
|
|
throw new OaiModelException(
|
|
|
|
'The prefix of the identifier argument is unknown.',
|
|
|
|
OaiModelError::BADARGUMENT
|
|
|
|
);
|
|
|
|
}
|
2018-11-27 17:06:11 +00:00
|
|
|
$dataId = $this->getDocumentIdByIdentifier($oaiRequest['identifier']);
|
|
|
|
|
|
|
|
$dataset = null;
|
|
|
|
try {
|
|
|
|
//$dataset = new Opus_Document($docId);
|
2020-05-25 14:56:20 +00:00
|
|
|
//$dataset = Dataset::findOrFail($publishId);
|
|
|
|
$dataset = Dataset::where('publish_id', '=', $dataId)->firstOrFail();
|
2020-03-26 08:11:12 +00:00
|
|
|
} catch (ModelNotFoundException $ex) {
|
2018-11-27 17:06:11 +00:00
|
|
|
throw new OaiModelException(
|
|
|
|
'The value of the identifier argument is unknown or illegal in this repository.',
|
|
|
|
OaiModelError::IDDOESNOTEXIST
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-09-12 15:40:21 +00:00
|
|
|
$metadataPrefix = null;
|
|
|
|
if (true === array_key_exists('metadataPrefix', $oaiRequest)) {
|
|
|
|
$metadataPrefix = $oaiRequest['metadataPrefix'];
|
2020-07-15 15:37:27 +00:00
|
|
|
} else {
|
|
|
|
throw new OaiModelException(
|
|
|
|
'The prefix of the metadata argument is unknown.',
|
|
|
|
OaiModelError::BADARGUMENT
|
|
|
|
);
|
2019-09-12 15:40:21 +00:00
|
|
|
}
|
2020-03-26 08:11:12 +00:00
|
|
|
$this->proc->setParameter('', 'oai_metadataPrefix', $metadataPrefix);
|
2018-11-27 17:06:11 +00:00
|
|
|
|
|
|
|
// do not deliver datasets which are restricted by document state
|
|
|
|
if (is_null($dataset)
|
|
|
|
//or (false === in_array($dataset->getServerState(), $this->_deliveringDocumentStates))
|
2020-03-26 08:11:12 +00:00
|
|
|
or (false === $dataset->whereIn('server_state', $this->deliveringDocumentStates))
|
2020-04-16 20:29:26 +00:00
|
|
|
//or (false === $dataset->hasEmbargoPassed())
|
2020-05-07 17:29:18 +00:00
|
|
|
) {
|
2018-11-27 17:06:11 +00:00
|
|
|
throw new OaiModelException('Document is not available for OAI export!', OaiModelError::NORECORDSMATCH);
|
|
|
|
}
|
|
|
|
|
2020-03-26 08:11:12 +00:00
|
|
|
$this->xml->appendChild($this->xml->createElement('Datasets'));
|
2018-11-27 17:06:11 +00:00
|
|
|
$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 '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)) {
|
2020-03-05 08:47:01 +00:00
|
|
|
throw new OaiModelException(
|
2018-11-27 17:06:11 +00:00
|
|
|
'The value of the identifier argument is unknown or illegal in this repository.',
|
2020-03-05 08:47:01 +00:00
|
|
|
OaiModelError::IDDOESNOTEXIST
|
2018-11-27 17:06:11 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $dataId;
|
|
|
|
}
|
|
|
|
|
2018-08-06 12:30:51 +00:00
|
|
|
/**
|
|
|
|
* Implements response for OAI-PMH verb 'ListMetadataFormats'.
|
|
|
|
*
|
|
|
|
* @param array &$oaiRequest Contains full request information
|
|
|
|
* @return void
|
|
|
|
*/
|
2018-09-10 13:09:10 +00:00
|
|
|
private function handleListMetadataFormats()
|
2018-08-06 12:30:51 +00:00
|
|
|
{
|
2020-03-26 08:11:12 +00:00
|
|
|
$this->xml->appendChild($this->xml->createElement('Datasets'));
|
2018-08-06 12:30:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implements response for OAI-PMH verb 'ListRecords'.
|
|
|
|
*
|
|
|
|
* @param array &$oaiRequest Contains full request information
|
|
|
|
* @return void
|
|
|
|
*/
|
2020-05-11 12:05:53 +00:00
|
|
|
private function handleListRecords(array &$oaiRequest)
|
2018-08-06 12:30:51 +00:00
|
|
|
{
|
2020-05-07 17:29:18 +00:00
|
|
|
//$maxRecords = 30; //$this->_configuration->getMaxListRecords();
|
|
|
|
$maxRecords = $this->configuration->getMaxListRecords();
|
2018-09-10 13:09:10 +00:00
|
|
|
$this->handlingOfLists($oaiRequest, $maxRecords);
|
2018-08-06 12:30:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implements response for OAI-PMH verb 'ListIdentifiers'.
|
|
|
|
*
|
|
|
|
* @param array &$oaiRequest Contains full request information
|
|
|
|
* @return void
|
|
|
|
*/
|
2018-09-10 13:09:10 +00:00
|
|
|
private function handleListIdentifiers(array &$oaiRequest)
|
2018-08-06 12:30:51 +00:00
|
|
|
{
|
2020-05-07 17:29:18 +00:00
|
|
|
//$maxIdentifier = 5; //$this->_configuration->getMaxListIdentifiers();
|
|
|
|
$maxIdentifier = $this->configuration->getMaxListIdentifiers();
|
2018-09-10 13:09:10 +00:00
|
|
|
$this->handlingOfLists($oaiRequest, $maxIdentifier);
|
2018-08-06 12:30:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implements response for OAI-PMH verb 'ListSets'.
|
|
|
|
*
|
|
|
|
* @param array &$oaiRequest Contains full request information
|
|
|
|
* @return void
|
|
|
|
*/
|
2018-09-10 13:09:10 +00:00
|
|
|
private function handleListSets()
|
2018-08-06 12:30:51 +00:00
|
|
|
{
|
2020-04-16 20:29:26 +00:00
|
|
|
$repIdentifier = "tethys.at";
|
2020-03-26 08:11:12 +00:00
|
|
|
$this->proc->setParameter('', 'repIdentifier', $repIdentifier);
|
|
|
|
$this->xml->appendChild($this->xml->createElement('Datasets'));
|
2018-08-06 12:30:51 +00:00
|
|
|
|
|
|
|
//$oaiSets = new Oai_Model_Sets();
|
|
|
|
$sets = array(
|
2020-05-18 17:36:31 +00:00
|
|
|
// 'bibliography:true' => 'Set for bibliographic entries',
|
|
|
|
// 'bibliography:false' => 'Set for non-bibliographic entries',
|
2018-08-06 12:30:51 +00:00
|
|
|
);
|
|
|
|
$sets = array_merge(
|
|
|
|
$sets,
|
2020-05-18 17:36:31 +00:00
|
|
|
$this->getSetsForDocumentTypes(),
|
|
|
|
$this->getSetsForProjects(),
|
2018-08-06 12:30:51 +00:00
|
|
|
);
|
|
|
|
//$sets = $this->getSetsForDocumentTypes();
|
|
|
|
|
|
|
|
foreach ($sets as $type => $name) {
|
2020-03-26 08:11:12 +00:00
|
|
|
$opusDoc = $this->xml->createElement('Rdr_Sets');
|
|
|
|
$typeAttr = $this->xml->createAttribute('Type');
|
|
|
|
$typeValue = $this->xml->createTextNode($type);
|
2018-08-06 12:30:51 +00:00
|
|
|
$typeAttr->appendChild($typeValue);
|
|
|
|
$opusDoc->appendChild($typeAttr);
|
2020-03-26 08:11:12 +00:00
|
|
|
$nameAttr = $this->xml->createAttribute('TypeName');
|
|
|
|
$nameValue = $this->xml->createTextNode($name);
|
2018-08-06 12:30:51 +00:00
|
|
|
$nameAttr->appendChild($nameValue);
|
|
|
|
$opusDoc->appendChild($nameAttr);
|
2020-03-26 08:11:12 +00:00
|
|
|
$this->xml->documentElement->appendChild($opusDoc);
|
2018-08-06 12:30:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-10 13:09:10 +00:00
|
|
|
private function handleIllegalVerb()
|
2018-08-06 12:30:51 +00:00
|
|
|
{
|
2020-03-26 08:11:12 +00:00
|
|
|
$this->proc->setParameter('', 'oai_error_code', 'badVerb');
|
|
|
|
$this->proc->setParameter('', 'oai_error_message', 'The verb provided in the request is illegal.');
|
2018-08-06 12:30:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper method for handling lists.
|
|
|
|
*
|
|
|
|
* @param array $oaiRequest query parameter
|
|
|
|
* @param mixed $maxRecords max count of records
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
2018-09-10 13:09:10 +00:00
|
|
|
private function handlingOfLists(array &$oaiRequest, $maxRecords)
|
2018-08-06 12:30:51 +00:00
|
|
|
{
|
|
|
|
if (true === empty($maxRecords)) {
|
|
|
|
$maxRecords = 100;
|
|
|
|
}
|
2018-12-10 16:26:57 +00:00
|
|
|
|
2020-04-16 20:29:26 +00:00
|
|
|
$repIdentifier = "tethys.at";
|
2020-05-11 12:05:53 +00:00
|
|
|
//$this->_configuration->getResumptionTokenPath();
|
|
|
|
$tokenTempPath = storage_path('app' . DIRECTORY_SEPARATOR . 'resumption');
|
2018-12-10 16:26:57 +00:00
|
|
|
|
2020-03-26 08:11:12 +00:00
|
|
|
$this->proc->setParameter('', 'repIdentifier', $repIdentifier);
|
|
|
|
$this->xml->appendChild($this->xml->createElement('Datasets'));
|
|
|
|
|
2018-08-06 12:30:51 +00:00
|
|
|
// do some initialisation
|
|
|
|
$cursor = 0;
|
|
|
|
//$totalIds = 0;
|
|
|
|
$start = $maxRecords + 1;
|
|
|
|
$reldocIds = array();
|
|
|
|
|
|
|
|
$metadataPrefix = null;
|
2020-07-28 07:22:28 +00:00
|
|
|
// if (true === array_key_exists('metadataPrefix', $oaiRequest)) {
|
|
|
|
// $metadataPrefix = $oaiRequest['metadataPrefix'];
|
|
|
|
// }
|
|
|
|
// $this->proc->setParameter('', 'oai_metadataPrefix', $metadataPrefix);
|
2020-05-07 17:29:18 +00:00
|
|
|
|
|
|
|
$tokenWorker = new ResumptionTokens();
|
|
|
|
$tokenWorker->setResumptionPath($tokenTempPath);
|
2018-08-06 12:30:51 +00:00
|
|
|
|
2018-12-10 16:26:57 +00:00
|
|
|
// parameter resumptionToken is given
|
|
|
|
if (false === empty($oaiRequest['resumptionToken'])) {
|
2020-05-07 17:29:18 +00:00
|
|
|
$resParam = $oaiRequest['resumptionToken']; //e.g. "158886496600000"
|
|
|
|
$token = $tokenWorker->getResumptionToken($resParam);
|
|
|
|
|
|
|
|
if (true === is_null($token)) {
|
|
|
|
throw new OaiModelException("cache is outdated.", OaiModelError::BADRESUMPTIONTOKEN);
|
|
|
|
}
|
|
|
|
$cursor = $token->getStartPosition() - 1;//startet dann bei Index 10
|
|
|
|
$start = $token->getStartPosition() + $maxRecords;
|
|
|
|
$totalIds = $token->getTotalIds();
|
|
|
|
$reldocIds = $token->getDocumentIds();
|
|
|
|
$metadataPrefix = $token->getMetadataPrefix();
|
|
|
|
|
|
|
|
$this->proc->setParameter('', 'oai_metadataPrefix', $metadataPrefix);
|
|
|
|
|
|
|
|
// else no resumptionToken is given
|
2018-12-10 16:26:57 +00:00
|
|
|
} else {
|
|
|
|
// no resumptionToken is given
|
2020-07-28 07:22:28 +00:00
|
|
|
if (true === array_key_exists('metadataPrefix', $oaiRequest)) {
|
|
|
|
$metadataPrefix = $oaiRequest['metadataPrefix'];
|
|
|
|
} else {
|
|
|
|
throw new OaiModelException(
|
|
|
|
'The prefix of the metadata argument is unknown.',
|
|
|
|
OaiModelError::BADARGUMENT
|
|
|
|
);
|
|
|
|
}
|
|
|
|
$this->proc->setParameter('', 'oai_metadataPrefix', $metadataPrefix);
|
|
|
|
|
2018-12-10 16:26:57 +00:00
|
|
|
$finder = Dataset::query();
|
|
|
|
// add server state restrictions
|
|
|
|
$finder->whereIn('server_state', $this->deliveringDocumentStates);
|
|
|
|
if (array_key_exists('set', $oaiRequest)) {
|
|
|
|
$setarray = explode(':', $oaiRequest['set']);
|
2020-05-18 17:36:31 +00:00
|
|
|
|
2018-12-10 16:26:57 +00:00
|
|
|
if ($setarray[0] == 'data-type') {
|
|
|
|
if (count($setarray) === 2 and !empty($setarray[1])) {
|
|
|
|
$finder->where('type', $setarray[1]);
|
|
|
|
}
|
2020-05-18 17:36:31 +00:00
|
|
|
} elseif ($setarray[0] == 'project') {
|
|
|
|
if (count($setarray) === 2 and !empty($setarray[1])) {
|
|
|
|
// $finder->where('type', $setarray[1]);
|
|
|
|
$finder->whereHas('project', function ($q) use ($setarray) {
|
|
|
|
$q->where('label', $setarray[1]);
|
|
|
|
});
|
|
|
|
}
|
2018-08-06 12:30:51 +00:00
|
|
|
}
|
|
|
|
}
|
2020-07-27 11:58:47 +00:00
|
|
|
|
2020-07-27 16:34:58 +00:00
|
|
|
if (array_key_exists('from', $oaiRequest) && array_key_exists('until', $oaiRequest)) {
|
|
|
|
$from = $oaiRequest['from'];
|
|
|
|
$until = $oaiRequest['until'];
|
|
|
|
|
|
|
|
if (strlen($from) != strlen($until)) {
|
|
|
|
throw new OaiModelException(
|
|
|
|
'The request has different granularities for the from and until parameters.',
|
|
|
|
OaiModelError::BADARGUMENT
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2020-07-27 11:58:47 +00:00
|
|
|
|
|
|
|
if (array_key_exists('until', $oaiRequest)) {
|
|
|
|
$until = $oaiRequest['until'];
|
2020-07-27 14:06:15 +00:00
|
|
|
try {
|
2020-07-27 16:34:58 +00:00
|
|
|
$untilDate = \Illuminate\Support\Carbon::parse($until);
|
|
|
|
// if (strtotime($untilDate) > 0) {
|
|
|
|
$earliestPublicationDate = Dataset::earliestPublicationDate()->server_date_published;
|
2020-07-27 11:58:47 +00:00
|
|
|
if ($earliestPublicationDate->gt($untilDate)) {
|
|
|
|
throw new OaiModelException(
|
2020-07-27 14:06:15 +00:00
|
|
|
"earliestDatestamp is greater than given until date. The given values results in an empty list.",
|
2020-07-27 11:58:47 +00:00
|
|
|
OaiModelError::NORECORDSMATCH
|
2020-07-27 16:34:58 +00:00
|
|
|
);
|
2020-07-27 11:58:47 +00:00
|
|
|
} else {
|
2020-07-27 14:06:15 +00:00
|
|
|
$finder->where('server_date_published', '<=', $untilDate);
|
|
|
|
$test = $finder->toSql();
|
2020-07-27 11:58:47 +00:00
|
|
|
}
|
2020-07-27 16:34:58 +00:00
|
|
|
} catch (OaiModelException $e) {
|
2020-07-27 14:06:15 +00:00
|
|
|
throw new OaiModelException(
|
|
|
|
"earliestDatestamp is greater than given until date. The given values results in an empty list.",
|
|
|
|
OaiModelError::NORECORDSMATCH
|
2020-07-27 16:34:58 +00:00
|
|
|
);
|
|
|
|
} catch (\Exception $e) {
|
2020-07-27 14:06:15 +00:00
|
|
|
throw new OaiModelException(
|
|
|
|
'The until date argument is not valid.',
|
|
|
|
OaiModelError::BADARGUMENT
|
|
|
|
);
|
|
|
|
}
|
2020-07-27 11:58:47 +00:00
|
|
|
}
|
2020-07-27 16:34:58 +00:00
|
|
|
|
2020-07-27 11:58:47 +00:00
|
|
|
if (array_key_exists('from', $oaiRequest)) {
|
|
|
|
$from = $oaiRequest['from'];
|
2020-07-27 14:06:15 +00:00
|
|
|
try {
|
2020-07-27 16:34:58 +00:00
|
|
|
$fromDate = \Illuminate\Support\Carbon::parse($from);
|
|
|
|
// if (strtotime($fromDate) > 0) {
|
|
|
|
$now = new Carbon();
|
2020-07-27 11:58:47 +00:00
|
|
|
if ($fromDate->gt($now)) {
|
|
|
|
throw new OaiModelException(
|
2020-07-27 14:06:15 +00:00
|
|
|
"Given from date is greater than now. The given values results in an empty list.",
|
2020-07-27 11:58:47 +00:00
|
|
|
OaiModelError::NORECORDSMATCH
|
|
|
|
);
|
|
|
|
} else {
|
2020-07-27 14:06:15 +00:00
|
|
|
$finder->where('server_date_published', '>=', $fromDate);
|
2020-07-27 11:58:47 +00:00
|
|
|
}
|
2020-07-27 16:34:58 +00:00
|
|
|
} catch (OaiModelException $e) {
|
2020-07-27 14:06:15 +00:00
|
|
|
throw new OaiModelException(
|
|
|
|
"Given from date is greater than now. The given values results in an empty list.",
|
|
|
|
OaiModelError::NORECORDSMATCH
|
2020-07-27 16:34:58 +00:00
|
|
|
);
|
|
|
|
} catch (\Exception $e) {
|
2020-07-27 14:06:15 +00:00
|
|
|
throw new OaiModelException(
|
|
|
|
'The from date argument is not valid.',
|
|
|
|
OaiModelError::BADARGUMENT
|
|
|
|
);
|
2020-07-27 11:58:47 +00:00
|
|
|
}
|
|
|
|
}
|
2020-05-18 17:36:31 +00:00
|
|
|
|
2018-12-10 16:26:57 +00:00
|
|
|
$totalIds = $finder->count();
|
2020-05-25 14:56:20 +00:00
|
|
|
$reldocIds = $finder->orderBy('publish_id')->pluck('publish_id')->toArray();
|
2018-08-06 12:30:51 +00:00
|
|
|
}
|
|
|
|
|
2020-03-26 08:11:12 +00:00
|
|
|
// handling of document ids
|
2018-08-06 12:30:51 +00:00
|
|
|
$restIds = $reldocIds;
|
|
|
|
$workIds = array_splice($restIds, 0, $maxRecords);
|
|
|
|
//foreach ($datasets as $dataset)
|
|
|
|
foreach ($workIds as $dataId) {
|
2020-05-25 14:56:20 +00:00
|
|
|
//$dataset = Dataset::findOrFail($dataId);
|
|
|
|
$dataset = Dataset::where('publish_id', '=', $dataId)->firstOrFail();
|
2018-08-06 12:30:51 +00:00
|
|
|
$this->createXmlRecord($dataset);
|
|
|
|
}
|
2020-05-07 17:29:18 +00:00
|
|
|
|
|
|
|
// no records returned
|
|
|
|
if (true === empty($workIds)) {
|
|
|
|
throw new OaiModelException(
|
|
|
|
"The combination of the given values results in an empty list.",
|
|
|
|
OaiModelError::NORECORDSMATCH
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// store the further Ids in a resumption-file
|
|
|
|
$countRestIds = count($restIds);
|
|
|
|
if ($countRestIds > 0) {
|
|
|
|
$token = new ResumptionToken();
|
|
|
|
$token->setStartPosition($start);
|
|
|
|
$token->setTotalIds($totalIds);
|
|
|
|
$token->setDocumentIds($restIds);
|
|
|
|
$token->setMetadataPrefix($metadataPrefix);
|
|
|
|
|
|
|
|
$tokenWorker->storeResumptionToken($token);
|
|
|
|
|
|
|
|
// set parameters for the resumptionToken-node
|
|
|
|
$res = $token->getResumptionId();
|
|
|
|
$this->setParamResumption($res, $cursor, $totalIds);
|
|
|
|
}
|
|
|
|
}
|
2020-07-27 16:34:58 +00:00
|
|
|
|
2020-05-07 17:29:18 +00:00
|
|
|
/**
|
|
|
|
* Set parameters for resumptionToken-line.
|
|
|
|
*
|
|
|
|
* @param string $res value of the resumptionToken
|
|
|
|
* @param int $cursor value of the cursor
|
|
|
|
* @param int $totalIds value of the total Ids
|
|
|
|
*/
|
|
|
|
private function setParamResumption($res, $cursor, $totalIds)
|
|
|
|
{
|
|
|
|
$tomorrow = str_replace('+00:00', 'Z', Carbon::now()->addHour(1)->setTimeZone('UTC'));
|
|
|
|
$this->proc->setParameter('', 'dateDelete', $tomorrow);
|
|
|
|
$this->proc->setParameter('', 'res', $res);
|
|
|
|
$this->proc->setParameter('', 'cursor', $cursor);
|
|
|
|
$this->proc->setParameter('', 'totalIds', $totalIds);
|
2018-08-06 12:30:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private function createXmlRecord(Dataset $dataset)
|
|
|
|
{
|
2020-03-26 08:11:12 +00:00
|
|
|
//$node = $this->xml->createElement('Rdr_Dataset');
|
2018-08-06 12:30:51 +00:00
|
|
|
$domNode = $this->getDatasetXmlDomNode($dataset);
|
2020-03-26 08:11:12 +00:00
|
|
|
// add frontdoor url
|
2020-05-25 14:56:20 +00:00
|
|
|
$this->addLandingPageAttribute($domNode, $dataset->publish_id);
|
2018-08-06 12:30:51 +00:00
|
|
|
|
|
|
|
// add access rights to element
|
|
|
|
//$this->_addAccessRights($domNode, $dataset);
|
|
|
|
|
2020-03-26 08:11:12 +00:00
|
|
|
$node = $this->xml->importNode($domNode, true);
|
2018-08-06 12:30:51 +00:00
|
|
|
|
|
|
|
//$node->setAttribute("Id", $dataset->id);
|
|
|
|
//$node->setAttribute("ServerState", $dataset->server_state);
|
|
|
|
|
|
|
|
////$child = new \DOMElement("ServerDateModified");
|
2020-03-26 08:11:12 +00:00
|
|
|
//$child = $this->xml->createElement('ServerDateModified');
|
2018-08-06 12:30:51 +00:00
|
|
|
//$child->setAttribute("Year", $dataset->server_date_modified->format('Y'));
|
|
|
|
//$child->setAttribute("Month", $dataset->server_date_modified->month);
|
|
|
|
//$child->setAttribute("Day", $dataset->server_date_modified->day);
|
|
|
|
//$node->appendChild($child);
|
|
|
|
|
|
|
|
//$type = $dataset->type;
|
2018-12-10 16:26:57 +00:00
|
|
|
$this->addSpecInformation($node, 'data-type:' . $dataset->type);
|
2018-09-10 13:09:10 +00:00
|
|
|
//$this->addSpecInformation($node, 'bibliography:' . 'false');
|
2018-08-06 12:30:51 +00:00
|
|
|
|
2020-03-26 08:11:12 +00:00
|
|
|
$this->xml->documentElement->appendChild($node);
|
2018-08-06 12:30:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add the landingpage attribute to Rdr_Dataset XML output.
|
|
|
|
*
|
|
|
|
* @param \DOMNode $document Rdr_Dataset XML serialisation
|
|
|
|
* @param string $docid Id of the dataset
|
|
|
|
* @return void
|
|
|
|
*/
|
2018-09-10 13:09:10 +00:00
|
|
|
private function addLandingPageAttribute(\DOMNode $document, $dataid)
|
2018-08-06 12:30:51 +00:00
|
|
|
{
|
2018-09-06 15:58:54 +00:00
|
|
|
$url = route('frontend.dataset.show', $dataid);
|
2018-08-06 12:30:51 +00:00
|
|
|
|
|
|
|
$owner = $document->ownerDocument;
|
|
|
|
$attr = $owner->createAttribute('landingpage');
|
|
|
|
$attr->appendChild($owner->createTextNode($url));
|
|
|
|
$document->appendChild($attr);
|
|
|
|
}
|
|
|
|
|
2018-09-10 13:09:10 +00:00
|
|
|
private function addSpecInformation(\DOMNode $document, $information)
|
2018-08-06 12:30:51 +00:00
|
|
|
{
|
2020-03-26 08:11:12 +00:00
|
|
|
$setSpecAttribute = $this->xml->createAttribute('Value');
|
|
|
|
$setSpecAttributeValue = $this->xml->createTextNode($information);
|
2018-08-06 12:30:51 +00:00
|
|
|
$setSpecAttribute->appendChild($setSpecAttributeValue);
|
|
|
|
|
2020-03-26 08:11:12 +00:00
|
|
|
$setSpecElement = $this->xml->createElement('SetSpec');
|
|
|
|
//$setSpecElement =new \DOMElement("SetSpec");
|
2018-08-06 12:30:51 +00:00
|
|
|
$setSpecElement->appendChild($setSpecAttribute);
|
|
|
|
$document->appendChild($setSpecElement);
|
|
|
|
}
|
|
|
|
|
|
|
|
private function getDatasetXmlDomNode($dataset)
|
|
|
|
{
|
2018-09-10 13:09:10 +00:00
|
|
|
if (!in_array($dataset->server_state, $this->deliveringDocumentStates)) {
|
2018-08-06 12:30:51 +00:00
|
|
|
$message = 'Trying to get a document in server state "' . $dataset->server_state . '"';
|
|
|
|
//Zend_Registry::get('Zend_Log')->err($message);
|
|
|
|
Log::error("server state: $message");
|
|
|
|
throw new \Exception($message);
|
|
|
|
}
|
|
|
|
|
|
|
|
$dataset->fetchValues();
|
|
|
|
$xmlModel = new \App\Library\Xml\XmlModel();
|
|
|
|
$xmlModel->setModel($dataset);
|
|
|
|
$xmlModel->excludeEmptyFields();
|
2020-03-26 08:11:12 +00:00
|
|
|
$cache = ($dataset->xmlCache) ? $dataset->xmlCache : new \App\Models\XmlCache();
|
2019-02-14 14:09:11 +00:00
|
|
|
$xmlModel->setXmlCache($cache);
|
2018-08-06 12:30:51 +00:00
|
|
|
return $xmlModel->getDomDocument()->getElementsByTagName('Rdr_Dataset')->item(0);
|
|
|
|
}
|
|
|
|
|
2020-05-18 17:36:31 +00:00
|
|
|
/**
|
|
|
|
* Returns oai sets for projects.
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
private function getSetsForProjects()
|
|
|
|
{
|
|
|
|
$setSpecPattern = self::SET_SPEC_PATTERN;
|
|
|
|
$sets = array();
|
|
|
|
|
|
|
|
$projects = Project::pluck('name', 'label')->toArray();
|
|
|
|
foreach ($projects as $doctype => $row) {
|
|
|
|
if (0 == preg_match("/^$setSpecPattern$/", $doctype)) {
|
|
|
|
$msg = "Invalid SetSpec (doctype='" . $doctype . "')."
|
|
|
|
. " Allowed characters are [$setSpecPattern].";
|
|
|
|
Log::error("OAI-PMH: $msg");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
$setSpec = 'project:' . $doctype;
|
|
|
|
// $count = $row['count'];
|
|
|
|
$sets[$setSpec] = "Set for project '$doctype'";
|
|
|
|
}
|
|
|
|
return $sets;
|
|
|
|
}
|
|
|
|
|
2018-08-06 12:30:51 +00:00
|
|
|
/**
|
|
|
|
* Returns oai sets for document types.
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
private function getSetsForDocumentTypes()
|
|
|
|
{
|
|
|
|
$setSpecPattern = self::SET_SPEC_PATTERN;
|
|
|
|
$sets = array();
|
|
|
|
|
2018-09-10 13:09:10 +00:00
|
|
|
$finder = new \App\Models\DatasetFinder();
|
2018-08-06 12:30:51 +00:00
|
|
|
$finder->setServerState('published');
|
|
|
|
foreach ($finder->groupedTypesPlusCount() as $doctype => $row) {
|
|
|
|
if (0 == preg_match("/^$setSpecPattern$/", $doctype)) {
|
|
|
|
$msg = "Invalid SetSpec (doctype='" . $doctype . "')."
|
|
|
|
. " Allowed characters are [$setSpecPattern].";
|
|
|
|
Log::error("OAI-PMH: $msg");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-12-10 16:26:57 +00:00
|
|
|
$setSpec = 'data-type:' . $doctype;
|
2018-08-06 12:30:51 +00:00
|
|
|
// $count = $row['count'];
|
|
|
|
$sets[$setSpec] = "Set for document type '$doctype'";
|
|
|
|
}
|
|
|
|
|
|
|
|
return $sets;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function handleIdentifyOld()
|
|
|
|
{
|
|
|
|
//$earliestDateFromDb = Opus_Document::getEarliestPublicationDate();
|
2018-09-10 13:09:10 +00:00
|
|
|
// $earliestDateFromDb = Dataset::select('server_date_created')
|
|
|
|
// ->orderBy('server_date_created', 'desc')
|
|
|
|
// ->first()->toDateTimeString();
|
2018-08-06 12:30:51 +00:00
|
|
|
$earliestDateFromDb = Dataset::earliestPublicationDate();
|
|
|
|
|
2018-09-10 13:09:10 +00:00
|
|
|
$sxe = new \SimpleXMLElement(
|
|
|
|
'<?xml version="1.0"?><?xml-stylesheet type="text/xsl" href="xsl/oai2.xslt"?><OAI-PMH/>'
|
|
|
|
);
|
|
|
|
|
2018-08-06 12:30:51 +00:00
|
|
|
$sxe->addAttribute('xmlns', 'http://www.openarchives.org/OAI/2.0/');
|
|
|
|
$sxe->addAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
|
|
|
|
$sxe->addAttribute('xmlns:mml', 'http://www.w3.org/1998/Math/MathML');
|
2018-09-10 13:09:10 +00:00
|
|
|
$sxe->addAttribute(
|
|
|
|
'xsi:schemaLocation',
|
|
|
|
'http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd'
|
|
|
|
);
|
2018-08-06 12:30:51 +00:00
|
|
|
$sxe->addChild('responseDate', date("Y-m-d\TH:i:s\Z"));
|
|
|
|
|
|
|
|
$uri = explode('?', $_SERVER['REQUEST_URI'], 2);
|
|
|
|
$requestChild = $sxe->addChild('request', url('/') . $uri[0]);
|
|
|
|
$requestChild->addAttribute('verb', 'Identify');
|
|
|
|
|
|
|
|
$identify = $sxe->addChild('Identify');
|
|
|
|
$identify->addChild('repositoryName', "Data Research Repository");
|
2020-05-18 17:36:31 +00:00
|
|
|
$identify->addChild('baseURL', "https://tethys.at/");
|
2018-08-06 12:30:51 +00:00
|
|
|
$identify->addChild('protocolVersion', '2.0');
|
|
|
|
$identify->addChild('adminEmail', 'repository@geologie.ac.at');
|
|
|
|
//$identify->addChild('earliestDatestamp', '2017-04-07');
|
|
|
|
$identify->addChild('earliestDatestamp', $earliestDateFromDb);
|
|
|
|
$identify->addChild('deletedRecord', 'persistent');
|
|
|
|
|
|
|
|
//$description = $identify->addChild('description');
|
|
|
|
//$oaiIdentifier = $description->addChild('oai-identifier');
|
|
|
|
//$oaiIdentifier->addAttribute('xmlns', 'http://www.openarchives.org/OAI/2.0/oai-identifier');
|
|
|
|
//$oaiIdentifier->addAttribute('xsi:schemaLocation', 'http://www.openarchives.org/OAI/2.0/oai-identifier');
|
|
|
|
//$oaiIdentifier->addChild('scheme', 'oai');
|
2018-09-10 13:09:10 +00:00
|
|
|
|
2018-08-06 12:30:51 +00:00
|
|
|
return $sxe;
|
|
|
|
}
|
|
|
|
}
|