create xml helpers classes (ref. #181)
This commit is contained in:
parent
43110bf9b9
commit
fbad6dd2fc
|
@ -55,8 +55,8 @@ class REST_Oaipmh_Expose_Controller extends REST_Controller {
|
|||
|
||||
default:
|
||||
$this->controller_oai->config();
|
||||
$this->controller_oai->errors[] = $this->controller_oai->oai_error('badArgument', $verb);
|
||||
$this->controller_oai->oai_exit( [], $this->controller_oai->errors);
|
||||
$this->controller_oai->errors[] = $this->controller_oai->oai_error('noVerb');
|
||||
$this->controller_oai->oai_exit( $request, $this->controller_oai->errors);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,10 +82,10 @@ class OAIPMH_Expose {
|
|||
$this->expirationdatetime = gmstrftime('%Y-%m-%dT%TZ', time() + TOKEN_VALID);
|
||||
|
||||
/** Where token is saved and path is included */
|
||||
//if(!is_dir(dirname(__FILE__).'/../../data/tokens/')){
|
||||
// mkdir(dirname(__FILE__).'/../../data/socialdb_tokens/');
|
||||
//}
|
||||
//define('TOKEN_PREFIX', dirname(__FILE__).'/../../data/tokens/');
|
||||
$token_path = $this->create_token_dir();
|
||||
if($token_path){
|
||||
define('TOKEN_PREFIX', $token_path);
|
||||
}
|
||||
|
||||
$this->SETS = array(
|
||||
array('setSpec' => 'class:activity', 'setName' => 'Activities'),
|
||||
|
@ -213,6 +213,7 @@ class OAIPMH_Expose {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Validates an identifier. The pattern is: '/^[-a-z\.0-9]+$/i' which means
|
||||
* it accepts -, letters and numbers.
|
||||
* Used only by function <B>oai_error</B> code idDoesNotExist.
|
||||
|
@ -221,6 +222,7 @@ class OAIPMH_Expose {
|
|||
function is_valid_uri($url) {
|
||||
return((bool) preg_match('/^[-a-z\.0-9]+$/i', $url));
|
||||
}
|
||||
|
||||
/** Validates attributes come with the query.
|
||||
* It accepts letters, numbers, ':', '_', '.' and -.
|
||||
* Here there are few more match patterns than is_valid_uri(): ':_'.
|
||||
|
@ -229,12 +231,14 @@ class OAIPMH_Expose {
|
|||
function is_valid_attrb($attrb) {
|
||||
return preg_match("/^[_a-zA-Z0-9\-\:\.]+$/", $attrb);
|
||||
}
|
||||
|
||||
/** All datestamps used in this system are GMT even
|
||||
* return value from database has no TZ information
|
||||
*/
|
||||
function formatDatestamp($datestamp) {
|
||||
return date("Y-m-d\TH:i:s\Z", strtotime($datestamp));
|
||||
}
|
||||
|
||||
/** The database uses datastamp without time-zone information.
|
||||
* It needs to clean all time-zone informaion from time string and reformat it
|
||||
*/
|
||||
|
@ -264,18 +268,37 @@ class OAIPMH_Expose {
|
|||
/** Finish a request when there is an error: send back errors. */
|
||||
function oai_exit($args,$errors) {
|
||||
header($this->CONTENT_TYPE);
|
||||
$e = new ANDS_Error_XML($args, $errors);
|
||||
$e = new XML_Error($args, $errors);
|
||||
$e->display();
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* LOG
|
||||
*/
|
||||
protected function create_token_dir() {
|
||||
$upload_dir = wp_upload_dir();
|
||||
$upload_dir = trailingslashit( $upload_dir['basedir'] );
|
||||
$logs_folder = $upload_dir . 'tainacan/tokens';
|
||||
|
||||
if (!is_dir($logs_folder)) {
|
||||
if (!mkdir($logs_folder)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $logs_folder;
|
||||
}
|
||||
|
||||
/** Generate a string based on the current Unix timestamp in microseconds for creating resumToken file name. */
|
||||
function get_token() {
|
||||
list($usec, $sec) = explode(" ", microtime());
|
||||
return ((int) ($usec * 1000) + (int) ($sec * 1000));
|
||||
}
|
||||
/** Create a token file.
|
||||
|
||||
/**
|
||||
*
|
||||
* Create a token file.
|
||||
* It has three parts which is separated by '#': cursor, extension of query, metadataPrefix.
|
||||
* Called by listrecords.php.
|
||||
*/
|
||||
|
@ -293,6 +316,7 @@ class OAIPMH_Expose {
|
|||
fclose($fp);
|
||||
return $token;
|
||||
}
|
||||
|
||||
/** Read a saved ResumToken */
|
||||
function readResumToken($resumptionToken) {
|
||||
$rtVal = false;
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
namespace Tainacan\OAIPMHExpose;
|
||||
|
||||
/**
|
||||
* A wraper of DOMDocument for data provider
|
||||
*/
|
||||
class Xml_Create {
|
||||
public $doc;
|
||||
|
||||
/**
|
||||
* Constructs an Xml_Create object.
|
||||
*
|
||||
* @param $par_array Type: array.
|
||||
* Array of request parameters for creating an ANDS_XML object.
|
||||
* \see create_request.
|
||||
*/
|
||||
public function __construct($par_array) {
|
||||
$this->doc = new \DOMDocument("1.0", "UTF-8");
|
||||
//to have indented output, not just a line
|
||||
$this->doc->preserveWhiteSpace = false;
|
||||
$this->doc->formatOutput = true;
|
||||
|
||||
// ------------- Interresting part here ------------
|
||||
//creating an xslt adding processing line
|
||||
//$xslt = $this->doc->createProcessingInstruction('xml-stylesheet', ' type="text/xsl" href="'. get_template_directory_uri().'/controllers/export/oai2.xsl"');
|
||||
|
||||
//var_dump($xslt);
|
||||
//exit();
|
||||
//adding it to the xml
|
||||
//this->doc->appendChild($xslt);
|
||||
|
||||
|
||||
// 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.
|
||||
*/
|
||||
public function addChild($mom_node, $name, $value = '') {
|
||||
$added_node = $this->doc->createElement($name, $value);
|
||||
$added_node = $mom_node->appendChild($added_node);
|
||||
|
||||
return $added_node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add 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 addChildDC($mom_node, $name, $value = '') {
|
||||
$added_node = $this->doc->createElementNS('http://purl.org/dc/elements/1.1/',$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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
namespace Tainacan\OAIPMHExpose;
|
||||
|
||||
/**
|
||||
* Generate an XML response when a request cannot be finished
|
||||
*
|
||||
* It has only one derived member function
|
||||
*/
|
||||
class XML_Error extends XML_Create {
|
||||
|
||||
public function __construct($par_array, $error_array) {
|
||||
parent::__construct($par_array);
|
||||
$oai_node = $this->doc->documentElement;
|
||||
|
||||
if($error_array){
|
||||
foreach ($error_array as $e) {
|
||||
list($code, $value) = explode("|", $e);
|
||||
$node = $this->addChild($oai_node, "error", $value);
|
||||
$node->setAttribute("code", $code);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
<?php
|
||||
namespace Tainacan\OAIPMHExpose;
|
||||
|
||||
/**
|
||||
* 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 Xml_Response extends Xml_Create {
|
||||
|
||||
public $verbNode;
|
||||
protected $verb;
|
||||
|
||||
public 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.
|
||||
*/
|
||||
public 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.
|
||||
*/
|
||||
public 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.
|
||||
*/
|
||||
public 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.
|
||||
*/
|
||||
public 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.
|
||||
*/
|
||||
public 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