Refactoring XML creation
This commit is contained in:
parent
6d339db918
commit
aac69993a3
56
oai2.php
56
oai2.php
|
@ -13,10 +13,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
define('MY_URI', 'dev2.moodle.ufsc.br');
|
|
||||||
|
|
||||||
require_once('oaidp-util.php');
|
require_once('oaidp-util.php');
|
||||||
require_once('xml_creater.php');
|
|
||||||
require_once('oai2server.php');
|
require_once('oai2server.php');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,11 +44,31 @@ $identifyResponse["deletedRecord"] = 'no'; // How your repository handles deleti
|
||||||
// maintained. It MAY reveal a deleted status for records.
|
// maintained. It MAY reveal a deleted status for records.
|
||||||
$identifyResponse["granularity"] = 'YYYY-MM-DDThh:mm:ssZ';
|
$identifyResponse["granularity"] = 'YYYY-MM-DDThh:mm:ssZ';
|
||||||
|
|
||||||
$oai2 = new OAI2Server($_REQUEST, $identifyResponse,
|
$example_record = array('identifier' => 'dev.testing.pmh',
|
||||||
|
'datestamp' => date('Y-m-d-H:s'),
|
||||||
|
'set' => 'class:activity',
|
||||||
|
'metadata' => array(
|
||||||
|
'container_name' => 'oai_dc:dc',
|
||||||
|
'container_attributes' => array(
|
||||||
|
'xmlns:oai_dc' => "http://www.openarchives.org/OAI/2.0/oai_dc/",
|
||||||
|
'xmlns:dc' => "http://purl.org/dc/elements/1.1/",
|
||||||
|
'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
|
||||||
|
'xsi:schemaLocation' =>
|
||||||
|
'http://www.openarchives.org/OAI/2.0/oai_dc/ http://www.openarchives.org/OAI/2.0/oai_dc.xsd'
|
||||||
|
),
|
||||||
|
'fields' => array(
|
||||||
|
'dc:title' => 'Testing records',
|
||||||
|
'dc:author' => 'Neis'
|
||||||
|
)
|
||||||
|
));
|
||||||
|
|
||||||
|
$oai2 = new OAI2Server('neis.moodle.ufsc.br', $_GET, $identifyResponse,
|
||||||
array(
|
array(
|
||||||
'ListMetadataFormats' =>
|
'ListMetadataFormats' =>
|
||||||
function($identifier = '') {
|
function($identifier = '') {
|
||||||
// throws new OAI2Exception('idDoesNotExist', '', $identifier)
|
if ($identifier == 'a.b.c') {
|
||||||
|
throw new OAI2Exception('idDoesNotExist', '', $identifier);
|
||||||
|
}
|
||||||
return
|
return
|
||||||
array('rif' => array('metadataPrefix'=>'rif',
|
array('rif' => array('metadataPrefix'=>'rif',
|
||||||
'schema'=>'http://services.ands.org.au/sandbox/orca/schemata/registryObjects.xsd',
|
'schema'=>'http://services.ands.org.au/sandbox/orca/schemata/registryObjects.xsd',
|
||||||
|
@ -85,35 +102,22 @@ $oai2 = new OAI2Server($_REQUEST, $identifyResponse,
|
||||||
|
|
||||||
'ListRecords' =>
|
'ListRecords' =>
|
||||||
function($metadataPrefix, $from = '', $until = '', $set = '', $count = false, $deliveredRecords = 0, $maxItems = 0) {
|
function($metadataPrefix, $from = '', $until = '', $set = '', $count = false, $deliveredRecords = 0, $maxItems = 0) {
|
||||||
|
global $example_record;
|
||||||
// throws new OAI2Exception('noRecordsMatch')
|
// throws new OAI2Exception('noRecordsMatch')
|
||||||
// throws new OAI2Exception('noSetHierarchy')
|
// throws new OAI2Exception('noSetHierarchy')
|
||||||
if ($count) {
|
if ($count) {
|
||||||
return 10;
|
return 1;
|
||||||
}
|
}
|
||||||
return array();
|
return array($example_record);
|
||||||
},
|
},
|
||||||
|
|
||||||
'GetRecord' =>
|
'GetRecord' =>
|
||||||
function($identifier, $metadataPrefix) {
|
function($identifier, $metadataPrefix) {
|
||||||
// throws new OAI2Exception('idDoesNotExist', '', $identifier) if record not found
|
global $example_record;
|
||||||
|
if ($identifier == 'a.b.c') {
|
||||||
return array('identifier' => 'dev.testing.pmh',
|
throw new OAI2Exception('idDoesNotExist', '', $identifier);
|
||||||
'datestamp' => date('Y-m-d-H:s'),
|
}
|
||||||
'set' => 'class:activity',
|
return $example_record;
|
||||||
'metadata' => array(
|
|
||||||
'container_name' => 'oai_dc:dc',
|
|
||||||
'container_attributes' => array(
|
|
||||||
'xmlns:oai_dc' => "http://www.openarchives.org/OAI/2.0/oai_dc/",
|
|
||||||
'xmlns:dc' => "http://purl.org/dc/elements/1.1/",
|
|
||||||
'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
|
|
||||||
'xsi:schemaLocation' =>
|
|
||||||
'http://www.openarchives.org/OAI/2.0/oai_dc/ http://www.openarchives.org/OAI/2.0/oai_dc.xsd'
|
|
||||||
),
|
|
||||||
'fields' => array(
|
|
||||||
'dc:title' => 'Testing records',
|
|
||||||
'dc:author' => 'Neis'
|
|
||||||
)
|
|
||||||
));
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
@ -73,6 +73,11 @@ class OAI2Exception extends Exception {
|
||||||
'code' => 'badArgument',
|
'code' => 'badArgument',
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
parent::__construct($this->errorTable[$code]['text'], $code);
|
parent::__construct($this->errorTable[$code]['text']);
|
||||||
|
$this->code = $code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOAI2Code() {
|
||||||
|
return $this->code;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
244
oai2server.php
244
oai2server.php
|
@ -18,23 +18,37 @@ define('TOKEN_PREFIX','/tmp/oai_pmh-');
|
||||||
class OAI2Server {
|
class OAI2Server {
|
||||||
|
|
||||||
public $errors = array();
|
public $errors = array();
|
||||||
|
private $args = array();
|
||||||
|
private $verb = '';
|
||||||
|
|
||||||
function __construct($args, $identifyResponse, $callbacks) {
|
function __construct($uri, $args, $identifyResponse, $callbacks) {
|
||||||
|
|
||||||
|
if (!isset($args['verb']) || empty($args['verb'])) {
|
||||||
|
$this->errors[] = new OAI2Exception('noVerb');
|
||||||
|
$this->errorResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->verb = $args['verb'];
|
||||||
|
unset($args['verb']);
|
||||||
$this->args = $args;
|
$this->args = $args;
|
||||||
|
|
||||||
|
$this->uri = $uri;
|
||||||
|
|
||||||
$this->identifyResponse = $identifyResponse;
|
$this->identifyResponse = $identifyResponse;
|
||||||
|
|
||||||
$this->listMetadataFormatsCallback = $callbacks['ListMetadataFormats'];
|
$this->listMetadataFormatsCallback = $callbacks['ListMetadataFormats'];
|
||||||
$this->listSetsCallback = $callbacks['ListSets'];
|
$this->listSetsCallback = $callbacks['ListSets'];
|
||||||
$this->listRecordsCallback = $callbacks['ListRecords'];
|
$this->listRecordsCallback = $callbacks['ListRecords'];
|
||||||
$this->getRecordCallback = $callbacks['GetRecord'];
|
$this->getRecordCallback = $callbacks['GetRecord'];
|
||||||
|
|
||||||
|
$this->response = new OAI2XMLResponse($this->uri, $this->verb, $this->args);
|
||||||
|
|
||||||
$this->respond();
|
$this->respond();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function respond() {
|
private function respond() {
|
||||||
if (!isset($this->args['verb']) || empty($this->args['verb'])) {
|
|
||||||
$this->errors[] = new OAI2Exception('noVerb');
|
switch ($this->verb) {
|
||||||
} else {
|
|
||||||
switch ($this->args['verb']) {
|
|
||||||
|
|
||||||
case 'Identify': $this->identify(); break;
|
case 'Identify': $this->identify(); break;
|
||||||
|
|
||||||
|
@ -49,24 +63,24 @@ class OAI2Server {
|
||||||
|
|
||||||
default: $this->errors[] = new OAI2Exception('badVerb', $this->args['verb']);
|
default: $this->errors[] = new OAI2Exception('badVerb', $this->args['verb']);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (empty($this->errors)) {
|
|
||||||
|
|
||||||
if (isset($this->outputObj)) {
|
if (empty($this->errors)) {
|
||||||
header(CONTENT_TYPE);
|
header(CONTENT_TYPE);
|
||||||
$this->outputObj->display();
|
$this->response->display();
|
||||||
} else {
|
|
||||||
exit("Nothing to output. May be a bug.");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
$this->errorResponse();
|
$this->errorResponse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function errorResponse() {
|
private function errorResponse() {
|
||||||
$e = new OAI2XMLError($this->args,$this->errors);
|
$errorResponse = new OAI2XMLResponse($this->uri, $this->verb, $this->args);
|
||||||
|
$oai_node = $errorResponse->doc->documentElement;
|
||||||
|
foreach($this->errors as $e) {
|
||||||
|
$node = $errorResponse->addChild($oai_node,"error",$e->getMessage());
|
||||||
|
$node->setAttribute("code",$e->getOAI2Code());
|
||||||
|
}
|
||||||
header(CONTENT_TYPE);
|
header(CONTENT_TYPE);
|
||||||
$e->display();
|
$errorResponse->display();
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,17 +93,15 @@ class OAI2Server {
|
||||||
*/
|
*/
|
||||||
public function identify() {
|
public function identify() {
|
||||||
|
|
||||||
if (count($this->args) > 1) {
|
if (count($this->args) > 0) {
|
||||||
foreach($args as $key => $val) {
|
foreach($args as $key => $val) {
|
||||||
if(strcmp($key,"verb")!=0) {
|
|
||||||
$this->errors[] = new OAI2Exception('badArgument', $key, $val);
|
$this->errors[] = new OAI2Exception('badArgument', $key, $val);
|
||||||
}
|
}
|
||||||
}
|
$this->errorResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->outputObj = new ANDS_Response_XML($this->args);
|
|
||||||
foreach($this->identifyResponse as $key => $val) {
|
foreach($this->identifyResponse as $key => $val) {
|
||||||
$this->outputObj->add2_verbNode($key, $val);
|
$this->response->addToVerbNode($key, $val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,21 +112,26 @@ class OAI2Server {
|
||||||
*/
|
*/
|
||||||
public function listMetadataFormats() {
|
public function listMetadataFormats() {
|
||||||
|
|
||||||
$checkList = array("ops"=>array("identifier"));
|
foreach ($this->args as $argument => $value) {
|
||||||
$this->checkArgs($checkList);
|
if ($argument != 'identifier') {
|
||||||
|
$this->errors[] = new OAI2Exception('badArgument', $argument, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!empty($this->errors)) {
|
||||||
|
$this->errorResponse();
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ($formats = call_user_func($this->listMetadataFormatsCallback, $this->args['identifier'])) {
|
if ($formats = call_user_func($this->listMetadataFormatsCallback, $this->args['identifier'])) {
|
||||||
$this->outputObj = new ANDS_Response_XML($this->args);
|
|
||||||
foreach($formats as $key => $val) {
|
foreach($formats as $key => $val) {
|
||||||
$cmf = $this->outputObj->add2_verbNode("metadataFormat");
|
$cmf = $this->response->addToVerbNode("metadataFormat");
|
||||||
$this->outputObj->addChild($cmf,'metadataPrefix',$key);
|
$this->response->addChild($cmf,'metadataPrefix',$key);
|
||||||
$this->outputObj->addChild($cmf,'schema',$val['schema']);
|
$this->response->addChild($cmf,'schema',$val['schema']);
|
||||||
$this->outputObj->addChild($cmf,'metadataNamespace',$val['metadataNamespace']);
|
$this->response->addChild($cmf,'metadataNamespace',$val['metadataNamespace']);
|
||||||
}
|
|
||||||
return $outputObj;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
$this->errors[] = new OAI2Exception('noMetadataFormats');
|
$this->errors[] = new OAI2Exception('noMetadataFormats');
|
||||||
|
}
|
||||||
} catch (OAI2Exception $e) {
|
} catch (OAI2Exception $e) {
|
||||||
$this->errors[] = $e;
|
$this->errors[] = $e;
|
||||||
}
|
}
|
||||||
|
@ -128,27 +145,33 @@ class OAI2Server {
|
||||||
*/
|
*/
|
||||||
public function listSets() {
|
public function listSets() {
|
||||||
|
|
||||||
if (isset($this->args['resumptionToken']) && count($this->args) > 2) {
|
if (isset($this->args['resumptionToken'])) {
|
||||||
|
if (count($this->args) > 1) {
|
||||||
$this->errors[] = new OAI2Exception('exclusiveArgument');
|
$this->errors[] = new OAI2Exception('exclusiveArgument');
|
||||||
|
} else {
|
||||||
|
if ((int)$val+TOKEN_VALID < time()) {
|
||||||
|
$this->errors[] = new OAI2Exception('badResumptionToken');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!empty($this->errors)) {
|
||||||
|
$this->errorResponse();
|
||||||
}
|
}
|
||||||
$checkList = array("ops"=>array("resumptionToken"));
|
|
||||||
$this->checkArgs($checkList);
|
|
||||||
|
|
||||||
if ($sets = call_user_func($this->listSetsCallback)) {
|
if ($sets = call_user_func($this->listSetsCallback)) {
|
||||||
|
|
||||||
$this->outputObj = new ANDS_Response_XML($this->args);
|
|
||||||
foreach($sets as $set) {
|
foreach($sets as $set) {
|
||||||
|
|
||||||
$setNode = $this->outputObj->add2_verbNode("set");
|
$setNode = $this->response->addToVerbNode("set");
|
||||||
|
|
||||||
foreach($set as $key => $val) {
|
foreach($set as $key => $val) {
|
||||||
if($key=='setDescription') {
|
if($key=='setDescription') {
|
||||||
$desNode = $this->outputObj->addChild($setNode,$key);
|
$desNode = $this->response->addChild($setNode,$key);
|
||||||
$des = $this->outputObj->doc->createDocumentFragment();
|
$des = $this->response->doc->createDocumentFragment();
|
||||||
$des->appendXML($val);
|
$des->appendXML($val);
|
||||||
$desNode->appendChild($des);
|
$desNode->appendChild($des);
|
||||||
} else {
|
} else {
|
||||||
$this->outputObj->addChild($setNode,$key,$val);
|
$this->response->addChild($setNode,$key,$val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,19 +191,23 @@ class OAI2Server {
|
||||||
*/
|
*/
|
||||||
public function getRecord() {
|
public function getRecord() {
|
||||||
|
|
||||||
$checkList = array("required"=>array("metadataPrefix","identifier"));
|
if (!isset($this->args['metadataPrefix'])) {
|
||||||
$this->checkArgs($checkList);
|
$this->errors[] = new OAI2Exception('missingArgument', 'metadataPrefix');
|
||||||
|
} else {
|
||||||
$metadataPrefix = $this->args['metadataPrefix'];
|
|
||||||
|
|
||||||
$metadataFormats = call_user_func($this->listMetadataFormatsCallback);
|
$metadataFormats = call_user_func($this->listMetadataFormatsCallback);
|
||||||
|
if (!isset($metadataFormats[$this->args['metadataPrefix']])) {
|
||||||
if (!isset($metadataFormats[$metadataPrefix])) {
|
$this->errors[] = new OAI2Exception('cannotDisseminateFormat', 'metadataPrefix', $this->args['metadataPrefix']);
|
||||||
$this->errors[] = new OAI2Exception('cannotDisseminateFormat', 'metadataPrefix', $metadataPrefix);
|
}
|
||||||
|
}
|
||||||
|
if (!isset($this->args['identifier'])) {
|
||||||
|
$this->errors[] = new OAI2Exception('missingArgument', 'identifier');
|
||||||
|
}
|
||||||
|
if (!empty($this->errors)) {
|
||||||
|
$this->errorResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ($record = call_user_func($this->getRecordCallback, $this->args['identifier'], $metadataPrefix)) {
|
if ($record = call_user_func($this->getRecordCallback, $this->args['identifier'], $this->args['metadataPrefix'])) {
|
||||||
|
|
||||||
$identifier = $record['identifier'];
|
$identifier = $record['identifier'];
|
||||||
|
|
||||||
|
@ -192,14 +219,12 @@ class OAI2Server {
|
||||||
(($this->identifyResponse['deletedRecord'] == 'transient') ||
|
(($this->identifyResponse['deletedRecord'] == 'transient') ||
|
||||||
($this->identifyResponse['deletedRecord'] == 'persistent')));
|
($this->identifyResponse['deletedRecord'] == 'persistent')));
|
||||||
|
|
||||||
$this->outputObj = new ANDS_Response_XML($this->args);
|
$cur_record = $this->response->addToVerbNode('record');
|
||||||
$cur_record = $this->outputObj->create_record();
|
$cur_header = $this->response->createHeader($identifier, $datestamp, $set, $cur_record);
|
||||||
$cur_header = $this->outputObj->create_header($identifier, $datestamp, $set, $cur_record);
|
|
||||||
if ($status_deleted) {
|
if ($status_deleted) {
|
||||||
$cur_header->setAttribute("status","deleted");
|
$cur_header->setAttribute("status","deleted");
|
||||||
} else {
|
} else {
|
||||||
$this->add_metadata($cur_record, $record);
|
$this->add_metadata($cur_record, $record);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (OAI2Exception $e) {
|
} catch (OAI2Exception $e) {
|
||||||
|
@ -218,19 +243,37 @@ class OAI2Server {
|
||||||
public function listRecords() {
|
public function listRecords() {
|
||||||
|
|
||||||
if (isset($this->args['resumptionToken'])) {
|
if (isset($this->args['resumptionToken'])) {
|
||||||
if (count($this->args) > 2) {
|
if (count($this->args) > 1) {
|
||||||
$this->errors[] = new OAI2Exception('exclusiveArgument');
|
$this->errors[] = new OAI2Exception('exclusiveArgument');
|
||||||
}
|
|
||||||
$checkList = array("ops"=>array("resumptionToken"));
|
|
||||||
} else {
|
} else {
|
||||||
$checkList = array("required"=>array("metadataPrefix"),"ops"=>array("from","until","set"));
|
if ((int)$val+TOKEN_VALID < time()) {
|
||||||
|
$this->errors[] = new OAI2Exception('badResumptionToken');
|
||||||
}
|
}
|
||||||
$this->checkArgs($checkList);
|
}
|
||||||
|
} else {
|
||||||
$metadataFormats = call_user_func($this->listMetadataFormatsCallback, $this->args);
|
if (!isset($this->args['metadataPrefix'])) {
|
||||||
|
$this->errors[] = new OAI2Exception('missingArgument', 'metadataPrefix');
|
||||||
|
} else {
|
||||||
|
$metadataFormats = call_user_func($this->listMetadataFormatsCallback);
|
||||||
if (!isset($metadataFormats[$this->args['metadataPrefix']])) {
|
if (!isset($metadataFormats[$this->args['metadataPrefix']])) {
|
||||||
$this->errors[] = new OAI2Exception('cannotDisseminateFormat', 'metadataPrefix', $this->args['metadataPrefix']);
|
$this->errors[] = new OAI2Exception('cannotDisseminateFormat', 'metadataPrefix', $this->args['metadataPrefix']);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (isset($this->args['from'])) {
|
||||||
|
if(!checkDateFormat($this->args['from'])) {
|
||||||
|
$this->errors[] = new OAI2Exception('badGranularity', 'from', $this->args['from']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isset($this->args['until'])) {
|
||||||
|
if(!checkDateFormat($this->args['until'])) {
|
||||||
|
$this->errors[] = new OAI2Exception('badGranularity', 'until', $this->args['until']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($this->errors)) {
|
||||||
|
$this->errorResponse();
|
||||||
|
}
|
||||||
|
|
||||||
// Resume previous session?
|
// Resume previous session?
|
||||||
if (isset($this->args['resumptionToken'])) {
|
if (isset($this->args['resumptionToken'])) {
|
||||||
|
@ -247,6 +290,10 @@ class OAI2Server {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!empty($this->errors)) {
|
||||||
|
$this->errorResponse();
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$deliveredRecords = 0;
|
$deliveredRecords = 0;
|
||||||
$metadataPrefix = $this->args['metadataPrefix'];
|
$metadataPrefix = $this->args['metadataPrefix'];
|
||||||
|
@ -255,10 +302,6 @@ class OAI2Server {
|
||||||
$set = isset($this->args['set']) ? $this->args['set'] : '';
|
$set = isset($this->args['set']) ? $this->args['set'] : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($this->errors)) {
|
|
||||||
$this->errorResponse();
|
|
||||||
}
|
|
||||||
|
|
||||||
$maxItems = 1000;
|
$maxItems = 1000;
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -266,25 +309,24 @@ class OAI2Server {
|
||||||
|
|
||||||
$records = call_user_func($this->listRecordsCallback, $metadataPrefix, $from, $until, $set, false, $deliveredRecords, $maxItems);
|
$records = call_user_func($this->listRecordsCallback, $metadataPrefix, $from, $until, $set, false, $deliveredRecords, $maxItems);
|
||||||
|
|
||||||
$this->outputObj = new ANDS_Response_XML($this->args);
|
|
||||||
foreach ($records as $record) {
|
foreach ($records as $record) {
|
||||||
|
|
||||||
$identifier = $record['identifier'];
|
$identifier = $record['identifier'];
|
||||||
$datestamp = formatDatestamp($record['datestamp']);
|
$datestamp = formatDatestamp($record['datestamp']);
|
||||||
$setspec = $record[$SQL['set']];
|
$setspec = $record['set'];
|
||||||
|
|
||||||
$status_deleted = (isset($record['deleted']) && ($record['deleted'] === true) &&
|
$status_deleted = (isset($record['deleted']) && ($record['deleted'] === true) &&
|
||||||
(($this->identifyResponse['deletedRecord'] == 'transient') ||
|
(($this->identifyResponse['deletedRecord'] == 'transient') ||
|
||||||
($this->identifyResponse['deletedRecord'] == 'persistent')));
|
($this->identifyResponse['deletedRecord'] == 'persistent')));
|
||||||
|
|
||||||
if($this->args['verb'] == 'ListRecords') {
|
if($this->args['verb'] == 'ListRecords') {
|
||||||
$cur_record = $this->outputObj->create_record();
|
$cur_record = $this->response->createToVerNode('record');
|
||||||
$cur_header = $this->outputObj->create_header($identifier, $datestamp,$setspec,$cur_record);
|
$cur_header = $this->response->createHeader($identifier, $datestamp,$setspec,$cur_record);
|
||||||
if (!$status_deleted) {
|
if (!$status_deleted) {
|
||||||
$this->add_metadata($cur_record, $record);
|
$this->add_metadata($cur_record, $record);
|
||||||
}
|
}
|
||||||
} else { // for ListIdentifiers, only identifiers will be returned.
|
} else { // for ListIdentifiers, only identifiers will be returned.
|
||||||
$cur_header = $this->outputObj->create_header($identifier, $datestamp,$setspec);
|
$cur_header = $this->response->createHeader($identifier, $datestamp,$setspec);
|
||||||
}
|
}
|
||||||
if ($status_deleted) {
|
if ($status_deleted) {
|
||||||
$cur_header->setAttribute("status","deleted");
|
$cur_header->setAttribute("status","deleted");
|
||||||
|
@ -306,7 +348,7 @@ class OAI2Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($restoken)) {
|
if (isset($restoken)) {
|
||||||
$this->outputObj->create_resumpToken($restoken,$expirationDatetime,$records_count,$deliveredRecords);
|
$this->response->createResumptionToken($restoken,$expirationDatetime,$records_count,$deliveredRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (OAI2Exception $e) {
|
} catch (OAI2Exception $e) {
|
||||||
|
@ -316,78 +358,14 @@ class OAI2Server {
|
||||||
|
|
||||||
private function add_metadata($cur_record, $record) {
|
private function add_metadata($cur_record, $record) {
|
||||||
|
|
||||||
$meta_node = $this->outputObj->addChild($cur_record ,"metadata");
|
$meta_node = $this->response->addChild($cur_record ,"metadata");
|
||||||
|
|
||||||
$schema_node = $this->outputObj->addChild($meta_node, $record['metadata']['container_name']);
|
$schema_node = $this->response->addChild($meta_node, $record['metadata']['container_name']);
|
||||||
foreach ($record['metadata']['container_attributes'] as $name => $value) {
|
foreach ($record['metadata']['container_attributes'] as $name => $value) {
|
||||||
$schema_node->setAttribute($name, $value);
|
$schema_node->setAttribute($name, $value);
|
||||||
}
|
}
|
||||||
foreach ($record['metadata']['fields'] as $name => $value) {
|
foreach ($record['metadata']['fields'] as $name => $value) {
|
||||||
$this->outputObj->addChild($schema_node, $name, $value);
|
$this->response->addChild($schema_node, $name, $value);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Check if provided correct arguments for a request.
|
|
||||||
*
|
|
||||||
* Only number of parameters is checked.
|
|
||||||
* metadataPrefix has to be checked before it is used.
|
|
||||||
* set has to be checked before it is used.
|
|
||||||
* resumptionToken has to be checked before it is used.
|
|
||||||
* from and until can easily checked here because no extra information
|
|
||||||
* is needed.
|
|
||||||
*/
|
|
||||||
private function checkArgs($checkList) {
|
|
||||||
|
|
||||||
$metadataFormats = call_user_func($this->listMetadataFormatsCallback);
|
|
||||||
|
|
||||||
// "verb" has been checked before, no further check is needed
|
|
||||||
$verb = $this->args["verb"];
|
|
||||||
|
|
||||||
$test_args = $this->args;
|
|
||||||
unset($test_args["verb"]);
|
|
||||||
|
|
||||||
if(isset($checkList['required'])) {
|
|
||||||
for($i = 0; $i < count($checkList["required"]); $i++) {
|
|
||||||
|
|
||||||
if (isset($test_args[$checkList['required'][$i]]) == false) {
|
|
||||||
$this->errors[] = new OAI2Exception('missingArgument', $checkList["required"][$i]);
|
|
||||||
} else {
|
|
||||||
// if metadataPrefix is set, it is in required section
|
|
||||||
if(isset($test_args['metadataPrefix'])) {
|
|
||||||
$metadataPrefix = $test_args['metadataPrefix'];
|
|
||||||
if (!isset($metadataFormats[$metadataPrefix])) {
|
|
||||||
$this->errors[] = new OAI2Exception('cannotDisseminateFormat', 'metadataPrefix', $metadataPrefix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unset($test_args[$checkList["required"][$i]]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check to see if there is unwanted
|
|
||||||
foreach($test_args as $key => $val) {
|
|
||||||
|
|
||||||
if(!in_array($key, $checkList["ops"])) {
|
|
||||||
$this->errors[] = new OAI2Exception('badArgument', $key, $val);
|
|
||||||
}
|
|
||||||
switch ($key) {
|
|
||||||
case 'from':
|
|
||||||
case 'until':
|
|
||||||
if(!checkDateFormat($val)) {
|
|
||||||
$this->errors[] = new OAI2Exception('badGranularity', $key, $val);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'resumptionToken':
|
|
||||||
// only check for expiration
|
|
||||||
if((int)$val+TOKEN_VALID < time())
|
|
||||||
$this->errors[] = new OAI2Exception('badResumptionToken');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($this->errors)) {
|
|
||||||
$this->errorResponse();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
75
oai2xml.php
75
oai2xml.php
|
@ -4,8 +4,9 @@ class OAI2XML {
|
||||||
|
|
||||||
public $doc; // DOMDocument. Handle of current XML Document object
|
public $doc; // DOMDocument. Handle of current XML Document object
|
||||||
|
|
||||||
function __construct($request_args) {
|
function __construct($uri, $verb, $request_args) {
|
||||||
|
|
||||||
|
$this->verb = $verb;
|
||||||
$this->doc = new DOMDocument("1.0","UTF-8");
|
$this->doc = new DOMDocument("1.0","UTF-8");
|
||||||
$oai_node = $this->doc->createElement("OAI-PMH");
|
$oai_node = $this->doc->createElement("OAI-PMH");
|
||||||
$oai_node->setAttribute("xmlns","http://www.openarchives.org/OAI/2.0/");
|
$oai_node->setAttribute("xmlns","http://www.openarchives.org/OAI/2.0/");
|
||||||
|
@ -14,7 +15,8 @@ class OAI2XML {
|
||||||
$this->addChild($oai_node,"responseDate",gmdate("Y-m-d\TH:i:s\Z"));
|
$this->addChild($oai_node,"responseDate",gmdate("Y-m-d\TH:i:s\Z"));
|
||||||
$this->doc->appendChild($oai_node);
|
$this->doc->appendChild($oai_node);
|
||||||
|
|
||||||
$request = $this->addChild($this->doc->documentElement,"request",MY_URI);
|
$request = $this->addChild($this->doc->documentElement,"request",$uri);
|
||||||
|
$request->setAttribute('verb', $this->verb);
|
||||||
foreach($request_args as $key => $value) {
|
foreach($request_args as $key => $value) {
|
||||||
$request->setAttribute($key,$value);
|
$request->setAttribute($key,$value);
|
||||||
}
|
}
|
||||||
|
@ -52,16 +54,67 @@ class OAI2XML {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class OAI2XMLError extends OAI2XML {
|
class OAI2XMLResponse extends OAI2XML {
|
||||||
|
|
||||||
function __construct($request_args, $errors) {
|
function __construct($verb, $request_args) {
|
||||||
parent::__construct($request_args);
|
parent::__construct($verb, $request_args);
|
||||||
|
$this->verbNode = $this->addChild($this->doc->documentElement,$this->verb);
|
||||||
$oai_node = $this->doc->documentElement;
|
|
||||||
foreach($errors as $e) {
|
|
||||||
$node = $this->addChild($oai_node,"error",$e->getMessage());
|
|
||||||
$node->setAttribute("code",$e->getCode());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add direct child nodes to verb node (OAI-PMH), e.g. response to ListMetadataFormats.
|
||||||
|
* Different verbs can have different required child nodes.
|
||||||
|
* \see create_record, create_header
|
||||||
|
*
|
||||||
|
* \param $nodeName Type: string. The name of appending node.
|
||||||
|
* \param $value Type: string. The content of appending node.
|
||||||
|
*/
|
||||||
|
function addToVerbNode($nodeName, $value=null) {
|
||||||
|
return $this->addChild($this->verbNode,$nodeName,$value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Headers are enclosed inside of \<record\> to the query of ListRecords, ListIdentifiers and etc.
|
||||||
|
*
|
||||||
|
* \param $identifier Type: string. The identifier string for node \<identifier\>.
|
||||||
|
* \param $timestamp Type: timestamp. Timestapme in UTC format for node \<datastamp\>.
|
||||||
|
* \param $ands_class Type: mix. Can be an array or just a string. Content of \<setSpec\>.
|
||||||
|
* \param $add_to_node Type: DOMElement. Default value is null.
|
||||||
|
* In normal cases, $add_to_node is the \<record\> node created previously. When it is null, the newly created header node is attatched to $this->verbNode.
|
||||||
|
* Otherwise it will be attatched to the desired node defined in $add_to_node.
|
||||||
|
*/
|
||||||
|
function createHeader($identifier,$timestamp,$ands_class, $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 (is_array($ands_class)) {
|
||||||
|
foreach ($ands_class as $setspec) {
|
||||||
|
$this->addChild($header_node,"setSpec",$setspec);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->addChild($header_node,"setSpec",$ands_class);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
196
xml_creater.php
196
xml_creater.php
|
@ -1,196 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* functions and class related to generating XML response file.
|
|
||||||
*
|
|
||||||
* Example: Normal response without error codes
|
|
||||||
* $par_array = array("verb"=>"ListRecords","resumptionToken"=>"9CD1DA87F59C3E960871F4F3C9D093887C17D174");
|
|
||||||
* $test = new ANDS_Response_XML($par_array);
|
|
||||||
* $record_node = $test->create_record();
|
|
||||||
* $test->create_header("function: identifier string",gmdate("Y-m-d\TH:i:s\Z"),"collection",$record_node);
|
|
||||||
* $test->create_metadata($record_node);
|
|
||||||
* $test->display();
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A wraper of DOMDocument for data provider
|
|
||||||
*/
|
|
||||||
class ANDS_XML {
|
|
||||||
|
|
||||||
public $doc; /**< Type: DOMDocument. Handle of current XML Document object */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs an ANDS_XML object.
|
|
||||||
*
|
|
||||||
* @param $par_array Type: array.
|
|
||||||
* Array of request parameters for creating an ANDS_XML object.
|
|
||||||
* \see create_request.
|
|
||||||
*/
|
|
||||||
function __construct($par_array) {
|
|
||||||
$this->doc = new DOMDocument("1.0","UTF-8");
|
|
||||||
// oai_node equals to $this->doc->documentElement;
|
|
||||||
$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);
|
|
||||||
$this->create_request($par_array);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 nade 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, can be used for further expansion.
|
|
||||||
* If no further expansion is expected, return value can be igored.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function addChild($mom_node,$name, $value='') {
|
|
||||||
$added_node = $this->doc->createElement($name,$value);
|
|
||||||
$added_node = $mom_node->appendChild($added_node);
|
|
||||||
return $added_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an OAI request node.
|
|
||||||
*
|
|
||||||
* @param $par_array Type: array
|
|
||||||
* The attributes of a request node. They describe the verb of the request and other associated parameters used in the request.
|
|
||||||
* Keys of the array define attributes, and values are their content.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function create_request($par_array) {
|
|
||||||
$request = $this->addChild($this->doc->documentElement,"request",MY_URI);
|
|
||||||
foreach($par_array as $key => $value) {
|
|
||||||
$request->setAttribute($key,$value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display a doc in a readable, well-formatted way for display or saving
|
|
||||||
*/
|
|
||||||
function display() {
|
|
||||||
$pr = new DOMDocument();
|
|
||||||
$pr->preserveWhiteSpace = false;
|
|
||||||
$pr->formatOutput = true;
|
|
||||||
$pr->loadXML($this->doc->saveXML());
|
|
||||||
echo $pr->saveXML();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate an XML response when a request cannot be finished
|
|
||||||
*
|
|
||||||
* It has only one derived member function
|
|
||||||
*/
|
|
||||||
class ANDS_Error_XML extends ANDS_XML {
|
|
||||||
function __construct($par_array, $error_array) {
|
|
||||||
parent::__construct($par_array);
|
|
||||||
|
|
||||||
$oai_node = $this->doc->documentElement;
|
|
||||||
foreach($error_array as $e) {
|
|
||||||
list($code, $value) = explode("|", $e);
|
|
||||||
$node = $this->addChild($oai_node,"error",$value);
|
|
||||||
$node->setAttribute("code",$code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate an XML response to a request if no error has occured
|
|
||||||
*
|
|
||||||
* This is the class to further develop to suits a publication need
|
|
||||||
*/
|
|
||||||
class ANDS_Response_XML extends ANDS_XML {
|
|
||||||
public $verbNode; /**< Type: DOMElement. Verb node itself. */
|
|
||||||
protected $verb; /**< Type: string. The verb in the request */
|
|
||||||
|
|
||||||
function __construct($par_array) {
|
|
||||||
parent::__construct($par_array);
|
|
||||||
$this->verb = $par_array["verb"];
|
|
||||||
$this->verbNode = $this->addChild($this->doc->documentElement,$this->verb);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add direct child nodes to verb node (OAI-PMH), e.g. response to ListMetadataFormats.
|
|
||||||
* Different verbs can have different required child nodes.
|
|
||||||
* \see create_record, create_header
|
|
||||||
* \see http://www.openarchives.org/OAI/2.0/openarchivesprotocol.htm.
|
|
||||||
*
|
|
||||||
* \param $nodeName Type: string. The name of appending node.
|
|
||||||
* \param $value Type: string. The content of appending node.
|
|
||||||
*/
|
|
||||||
function add2_verbNode($nodeName, $value=null) {
|
|
||||||
return $this->addChild($this->verbNode,$nodeName,$value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an empty \<record\> node. Other nodes will be appended to it later.
|
|
||||||
*/
|
|
||||||
function create_record() {
|
|
||||||
return $this->add2_verbNode("record");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Headers are enclosed inside of \<record\> to the query of ListRecords, ListIdentifiers and etc.
|
|
||||||
*
|
|
||||||
* \param $identifier Type: string. The identifier string for node \<identifier\>.
|
|
||||||
* \param $timestamp Type: timestamp. Timestapme in UTC format for node \<datastamp\>.
|
|
||||||
* \param $ands_class Type: mix. Can be an array or just a string. Content of \<setSpec\>.
|
|
||||||
* \param $add_to_node Type: DOMElement. Default value is null.
|
|
||||||
* In normal cases, $add_to_node is the \<record\> node created previously. When it is null, the newly created header node is attatched to $this->verbNode.
|
|
||||||
* Otherwise it will be attatched to the desired node defined in $add_to_node.
|
|
||||||
*/
|
|
||||||
function create_header($identifier,$timestamp,$ands_class, $add_to_node=null) {
|
|
||||||
if(is_null($add_to_node)) {
|
|
||||||
$header_node = $this->add2_verbNode("header");
|
|
||||||
} else {
|
|
||||||
$header_node = $this->addChild($add_to_node,"header");
|
|
||||||
}
|
|
||||||
$this->addChild($header_node,"identifier",$identifier);
|
|
||||||
$this->addChild($header_node,"datestamp",$timestamp);
|
|
||||||
if (is_array($ands_class)) {
|
|
||||||
foreach ($ands_class as $setspec) {
|
|
||||||
$this->addChild($header_node,"setSpec",$setspec);
|
|
||||||
}
|
|
||||||
} else { $this->addChild($header_node,"setSpec",$ands_class); }
|
|
||||||
return $header_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create metadata node for holding metadata. This is always added to \<record\> node.
|
|
||||||
*
|
|
||||||
* \param $mom_record_node DOMElement. A node acts as the parent node.
|
|
||||||
*
|
|
||||||
* @return $meta_node Type: DOMElement.
|
|
||||||
* The newly created registryObject node which will be used for further expansion.
|
|
||||||
* metadata node itself is maintained by internally by the Class.
|
|
||||||
*/
|
|
||||||
function create_metadata($mom_record_node) {
|
|
||||||
$meta_node = $this->addChild($mom_record_node,"metadata");
|
|
||||||
return $meta_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 create_resumpToken($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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue