Using callbacks to configure server. Removing logic from server
This commit is contained in:
parent
49c64da4e5
commit
1280e99f51
348
ands_tpa.php
348
ands_tpa.php
|
@ -1,348 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* \file
|
||||
* \brief classes related to generating RIF-CS XML response file for ANDS from repository.
|
||||
* It also serves as an exmaple how class ANDS_RIFCS can be used in a particular case.
|
||||
*
|
||||
*/
|
||||
|
||||
require_once('ands_rifcs.php');
|
||||
|
||||
/**
|
||||
* \brief For creating RIF-CS metadata to meet the requirement of ANDS.
|
||||
*
|
||||
* Class ANDS_RIFCS provides all essential functionalities for creating ANDS RIF-CS records.
|
||||
* The protected member functions are the backbone functions which can be used for creating any ANDS RIF-CS records.
|
||||
* At the time of design only data source is database and there is only one set of outputs. Therefore there is only one class has been designed.
|
||||
* Ideally, there should be a separated class for creating actual records which reflect data source and data models.
|
||||
*
|
||||
* Example usage: publish records meet ANDS RIF-CS requirements
|
||||
*
|
||||
* \code
|
||||
* $metadata_node = $outputObj->create_metadata($cur_record);
|
||||
* $obj_node = new ANDS_TPA($outputObj, $metadata_node, $db);
|
||||
* try {
|
||||
* $obj_node->create_obj_node($record[$SQL['set']], $identifier);
|
||||
* } catch (Exception $e) {
|
||||
* echo 'Caught exception: ', $e->getMessage(), " when adding $identifier\n";
|
||||
* }
|
||||
* \endcode
|
||||
* \see Code in action can be seen in record_rif.php
|
||||
*/
|
||||
|
||||
class ANDS_TPA extends ANDS_RIFCS {
|
||||
//! Type: PDO. The database connection of the data source.
|
||||
//! \see __construct.
|
||||
private $db;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* The first two parameters are used by its parent class ANDS_RIFCS. The third is its own private property.
|
||||
*
|
||||
* \param $ands_response_doc ANDS_Response_XML. A XML Doc acts as the parent node.
|
||||
* \param $metadata_node DOMElement. The meta node which all subsequent nodes will be added to.
|
||||
* \param $db Type: PDO. The database connection of the data source.
|
||||
*/
|
||||
function __construct($ands_response_doc, $metadata_node, $db) {
|
||||
parent::__construct($ands_response_doc, $metadata_node);
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is the general entrence of creating actual content. It calls different functions for different type of RIF-CS model.
|
||||
* When anything goes wrong, e.g. found no record, or $set_name is not recognised, an exception will be thrown.
|
||||
* And for this implementation, data are stored in a database therefore a PDO is needed. But the source can be any.
|
||||
*
|
||||
* \param $set_name Type: string. The name of set is going to be created. Can be one of activity, collection or party.
|
||||
* \param $key Type: string. The main identifier used in ANDS system. There can be other identifier.
|
||||
*
|
||||
* \see create_activity, create_collection, create_party
|
||||
*/
|
||||
function create_obj_node($set_name, $key) {
|
||||
$db = $this->db;
|
||||
$set_name = strtolower($set_name);
|
||||
if (in_array($set_name,prepare_set_names())) {
|
||||
try {
|
||||
// Get ori_id and which the original table is:
|
||||
$query = "select ori_table_name, ori_id from oai_headers where oai_identifier = '".$key."'";
|
||||
$res = exec_pdo_query($db, $query);
|
||||
$record = $res->fetch(PDO::FETCH_ASSOC);
|
||||
} catch (PDOException $e) {
|
||||
echo "$key returned no record.\n";
|
||||
echo $e->getMessage();
|
||||
}
|
||||
|
||||
$processor = 'create_'.substr($set_name,6);
|
||||
$this->create_regObject(REG_OBJ_GROUP, $key, MY_URI);
|
||||
$this->$processor($record['ori_table_name'],$record['ori_id']);
|
||||
$this->create_identifier_node($key);
|
||||
$this->create_identifier_node('table='.$record['ori_table_name'].'+id='.$record['ori_id']);
|
||||
} else {
|
||||
throw new Exception('Wrong set name was used: '.$set_name);
|
||||
}
|
||||
}
|
||||
|
||||
/** The processor for creating metadata node of Activity. Called from create_obj_node.
|
||||
* \param $table_name Type: string. The table name will be used to retrieve data from.
|
||||
* \param $id_project Type: integer. Internal project id associated to this activity-project.
|
||||
* \see Function create_obj_node.
|
||||
*/
|
||||
private function create_activity($table_name, $id_project) {
|
||||
$db = $this->db;
|
||||
# // Get ori_id and which the original table is:
|
||||
# $query = "select ori_table_name, ori_id from oai_headers where oai_identifier = '".$key."'";
|
||||
# $res = exec_pdo_query($db, $query);
|
||||
# $record = $res->fetch(PDO::FETCH_ASSOC);
|
||||
# // $id_project will e used later, so save it:
|
||||
# $id_project = $record['ori_id'];
|
||||
// Get the content using the previously obtained infor:
|
||||
$query = sprintf("select inter_no,start_date, end_date,pub_descrip from %s where id_project = %s",$table_name,$id_project);
|
||||
|
||||
try {
|
||||
$res = exec_pdo_query($db,$query);
|
||||
$record = $res->fetch(PDO::FETCH_ASSOC);
|
||||
} catch (Exception $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
|
||||
$this->create_rifcs_node('activity','project');
|
||||
$c = $this->create_name_node();
|
||||
$this->create_namePart($c,'The Plant Accelerator Project '.$record['inter_no']);
|
||||
// Test codes for rich format.
|
||||
# // \n works
|
||||
# $this->create_description_node(sprintf("Line one:%s,\nLine two:%s.\nThird",'a','b'));
|
||||
$this->create_description_node(str_replace("\r\n","\n",$record['pub_descrip']));
|
||||
|
||||
$this->create_description_node('The experiment was carried out between '.$record['start_date'].' and '.$record['end_date'],'note');
|
||||
$query = sprintf("select idr,stype from list_prj_ids_v2 where stype in ('dataset','person')",$id_project);
|
||||
// echo $query;
|
||||
try {
|
||||
$res = $db->query($query,PDO::FETCH_ASSOC);
|
||||
if ($res==false) {
|
||||
throw new Exception($query."\nIt found nothing.\n");
|
||||
}
|
||||
foreach ($res as $record) {
|
||||
switch ($record['stype']) {
|
||||
case 'dataset':
|
||||
$this->create_relatedObject($record['idr'],'hasOutput');
|
||||
break;
|
||||
case 'person':
|
||||
$this->create_relatedObject($record['idr'],'isManagedBy');
|
||||
break;
|
||||
}
|
||||
}
|
||||
// The Plant Accelerator always participates in Activity
|
||||
$this->create_relatedObject('0874ad60-ab4d-11df-aebd-0002a5d5c51b','hasParticipant');
|
||||
} catch (PDOException $e) {
|
||||
process_pdo_error($query, $e);
|
||||
}// end of try-catch block
|
||||
} // end of function create_activity($key, $id_project)
|
||||
|
||||
/** The processor for creating metadata node of Collection. Called from create_obj_node.
|
||||
* \param $table_name Type: string. The table name will be used to retrieve data from.
|
||||
* \param $id_collect Type: integer. Internal collection id associated to this collection-dataset.
|
||||
* \see Function create_obj_node.
|
||||
*/
|
||||
private function create_collection($table_name, $id_collect) {
|
||||
$db = $this->db;
|
||||
try {
|
||||
$query = sprintf("select plant,variety,start_date,end_date,img_freq,anzsrc from %s where id_collect = %s",$table_name,$id_collect);
|
||||
$res = exec_pdo_query($db, $query);
|
||||
$dataset = $res->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$res = exec_pdo_query($db, $query);
|
||||
$record = $res->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$query = 'select id_rep, inter_no, id_project from tpa_project_ids where id_collect = '.$id_collect;
|
||||
$res = exec_pdo_query($db, $query);
|
||||
$prj_info = $res->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$query = 'select email from tpa_person where id_rep = '.$prj_info['id_rep'];
|
||||
$res = exec_pdo_query($db, $query);
|
||||
$email = $res->fetch(PDO::FETCH_ASSOC);
|
||||
} catch (PDOException $e) {
|
||||
echo $query.' was failed\n';
|
||||
echo $e->getMessage();
|
||||
}
|
||||
|
||||
$this->create_rifcs_node('collection','dataset');
|
||||
// Get the project inter_no as the name of this dataset
|
||||
$c = $this->create_name_node();
|
||||
$this->create_namePart($c,'Data set of Plant Accelerator Project '.$prj_info['inter_no']);
|
||||
|
||||
// locatin node: contact person
|
||||
$l_node = $this->create_location_node();
|
||||
$a_node = $this->create_address_node($l_node);
|
||||
$this->create_e_node($a_node, $email['email']);
|
||||
// location node: TPA's physical address
|
||||
$l_node = $this->create_location_node();
|
||||
$a_node = $this->create_address_node($l_node);
|
||||
$this->create_physcial_addr_txt($a_node, 'The Plant Accelerator, Hartley Grove, Urrbrae, SA 5064') ;
|
||||
// Temporal coverage of colletion
|
||||
$dates = array(array('date'=>$dataset['start_date'],'type'=>'dateFrom'),array('date'=>$dataset['end_date'],'type'=>'dateTo'));
|
||||
$this->create_coverage_tempo($dates);
|
||||
// subject
|
||||
$this->create_subject_node($dataset['aznsrc']);
|
||||
// relatedOjbects
|
||||
$query = sprintf("select idr,stype from list_prj_ids_v2(%d) where stype in ('project','person')",$prj_info['id_project']);
|
||||
try {
|
||||
$res = $db->query($query,PDO::FETCH_ASSOC);
|
||||
if ($res==false) {
|
||||
throw new Exception($query."\nIt found nothing.\n");
|
||||
}
|
||||
foreach ($res as $record) {
|
||||
switch ($record['stype']) {
|
||||
case 'project':
|
||||
$this->create_relatedObject($record['idr'],'isOutputOf');
|
||||
break;
|
||||
case 'person':
|
||||
$this->create_relatedObject($record['idr'],'isOwnedBy');
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
process_pdo_error($query, $e);
|
||||
}// end of try-catch block
|
||||
|
||||
// right of accessing
|
||||
$this->create_description_node('For information on rights and access to this dataset, please contact the owner.','accessRights');
|
||||
|
||||
// image data:
|
||||
$imgs = ''; $ex_conf = '';
|
||||
$dic = array('im_type_rgb'=>'RGB','im_type_nir'=>'NIR','im_type_fir'=>'FIR','im_type_nir_roots'=>'NIR Roots','im_type_fluo'=>'Fluorescence');
|
||||
$query = 'select im_type_rgb,im_type_nir,im_type_fir,im_type_nir_roots,im_type_fluo, lines, treatments, replicates, total from ands_collection where id_collect = '. $id_collect;
|
||||
$res = $db->query($query,PDO::FETCH_ASSOC);
|
||||
if ($res==false) {
|
||||
throw new Exception($query."\nIt found nothing.\n");
|
||||
}
|
||||
$info = $res->fetch();
|
||||
foreach ($info as $item => $v) {
|
||||
switch ($item) {
|
||||
case 'im_type_rgb':
|
||||
case 'im_type_nir':
|
||||
case 'im_type_fir':
|
||||
case 'im_type_nir_roots':
|
||||
case 'im_type_fluo':
|
||||
if (!empty($v)) { $imgs .= $dic[$item].', '; }
|
||||
break;
|
||||
default:
|
||||
if (!empty($v)) { $ex_conf .= ' '.$item.' = '.$v.', '; }
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (empty($imgs)) $imgs = "Images data of RGB, FIR, NIR, NIR Roots and Fluorescence cameras., ";
|
||||
$imgs = substr($imgs,0,-2);
|
||||
if (!empty($ex_conf)) $imgs = $imgs."\n".substr($ex_conf,0,-2);
|
||||
$this->create_description_node($imgs);
|
||||
// imaging frequency
|
||||
$this->create_description_node('Imaging frequency: '.$dataset['img_freq'],'note');
|
||||
} // end of function create_collection($key,$id_collect)
|
||||
|
||||
/** The processor for creating metadata node of Party. Called from create_obj_node. As party-person is different to party-group, there are two sub-functions are called accordingly.
|
||||
* \param $table_name Type: string. The table name will be used to retrieve data from.
|
||||
* \param $id_party Type: integer. Internal party id associated to this party.
|
||||
* \see Function create_obj_node.
|
||||
*/
|
||||
private function create_party($table_name, $id_party) {
|
||||
$db = $this->db;
|
||||
$query = sprintf("SELECT set_type FROM oai_headers WHERE ori_table_name = '%s' AND ori_id = %s",$table_name,$id_party);
|
||||
$res = exec_pdo_query($db, $query);
|
||||
$party_type = $res->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (in_array($party_type['set_type'],array('person','group'))) {
|
||||
$this->create_rifcs_node('party',$party_type['set_type']);
|
||||
|
||||
if ($party_type['set_type']=='person') {
|
||||
$this->create_person($table_name, $id_party);
|
||||
} elseif ($party_type['set_type']=='group') {
|
||||
$this->create_group($table_name, $id_party); }
|
||||
} else {
|
||||
throw new Exception('Unsupported set_type: '.$party_type['set_type']);
|
||||
}
|
||||
} // end of function create_part($key,$id_party)
|
||||
|
||||
/** The processor for creating metadata node of Party. Called from create_obj_node. As party-person is different to party-group, there are two sub-functions are called accordingly.
|
||||
* \param $table_name Type: string. The table name will be used to retrieve data from.
|
||||
* \param $id_party Type: integer. Internal party id associated to this party-person.
|
||||
* \see Function create_party.
|
||||
*/
|
||||
private function create_person($table_name, $id_party) {
|
||||
$db = $this->db;
|
||||
$query = sprintf("SELECT id_org, title, first_name, family_name, tel, fax, email, www, address, post_code, city,state,country,duty FROM %s WHERE id_rep = %s",$table_name, $id_party);
|
||||
$res = exec_pdo_query($db, $query);
|
||||
$info = $res->fetch(PDO::FETCH_ASSOC);
|
||||
$c = $this->create_name_node();
|
||||
if (!empty($info['title'])) $this->create_namePart($c,$info['title'],'title');
|
||||
$this->create_namePart($c,$info['family_name'],'family');
|
||||
$this->create_namePart($c,$info['first_name'],'given');
|
||||
|
||||
// locatin node: contact person
|
||||
$l_node = $this->create_location_node();
|
||||
$a_node = $this->create_address_node($l_node);
|
||||
$this->create_e_node($a_node, $info['email']);
|
||||
if (!empty($info['www'])) $this->create_e_node($a_node, $info['www'],'url');
|
||||
$this->create_physcial_fone_fax($a_node, $info['tel'],'telephoneNumber');
|
||||
if (!empty($info['fax'])) $this->create_physcial_fone_fax($a_node, $info['fax'],'faxNumber');
|
||||
$add_txt = trim($info['address']).', '.$info['city'].' '.$info['state'].' '.$info['post_code'].', '.$info['country'];
|
||||
// the strlength of ', , ' is 6
|
||||
if (strlen($add_txt)>6) $this->create_physcial_addr_txt($a_node,$add_txt);
|
||||
|
||||
// related objects:
|
||||
// their group: id_customer is a foreign key of tpa_organisation
|
||||
$query = sprintf("SELECT get_identifier('tpa_organisation',%s)",$info['id_org']);
|
||||
$res = exec_pdo_query($db, $query);
|
||||
$info = $res->fetch(PDO::FETCH_NUM);
|
||||
$this->create_relatedObject($info[0],'isMemberOf');
|
||||
|
||||
// their activities
|
||||
$query = "SELECT list_persons_objs($id_party,'project')";
|
||||
$res = exec_pdo_query($db, $query);
|
||||
$info = $res->fetch(PDO::FETCH_NUM);
|
||||
foreach ($info as $item) {
|
||||
$this->create_relatedObject($item,'isManagerOf');
|
||||
}
|
||||
// their collections
|
||||
$query = "SELECT list_persons_objs($id_party,'dataset')";
|
||||
$res = exec_pdo_query($db, $query);
|
||||
$info = $res->fetch(PDO::FETCH_NUM);
|
||||
foreach ($info as $item) {
|
||||
$this->create_relatedObject($item,'isOwnerOf');
|
||||
}
|
||||
}
|
||||
|
||||
/** The processor for creating metadata node of Party. Called from create_obj_node. As party-person is different to party-group, there are two sub-functions are called accordingly.
|
||||
* \param $table_name Type: string. The table name will be used to retrieve data from.
|
||||
* \param $id_party Type: integer. Internal party id associated to this party-group.
|
||||
* \see Function create_party.
|
||||
*/
|
||||
private function create_group($table_name, $id_party) {
|
||||
$db = $this->db;
|
||||
// echo 'table: ',$table_name,' party: ',$id_party,"\n";
|
||||
$query = sprintf("SELECT customer_name, abn, post_code, address, city, state, country, tel, fax, email, www, description FROM %s WHERE id_org = %s",$table_name, $id_party);
|
||||
//echo $query;
|
||||
$res = exec_pdo_query($db, $query);
|
||||
$info = $res->fetch(PDO::FETCH_ASSOC);
|
||||
$c = $this->create_name_node();
|
||||
$this->create_namePart($c,$info['customer_name']);
|
||||
if (!empty($info['abn'])) $this->create_identifier_node($info['abn'],'abn');
|
||||
|
||||
if (!empty($info['description'])) $this->create_description_node($info['description']);
|
||||
|
||||
$l_node = $this->create_location_node();
|
||||
$a_node = $this->create_address_node($l_node);
|
||||
$this->create_physcial_fone_fax($a_node, $info['tel'],'telephoneNumber');
|
||||
$this->create_physcial_fone_fax($a_node, $info['fax'],'faxNumber');
|
||||
$add_txt = trim($info['address']).', '.$info['city'].' '.$info['state'].' '.$info['post_code'].', '.$info['country'];
|
||||
$this->create_physcial_addr_txt($a_node,$add_txt);
|
||||
|
||||
// related objects:
|
||||
// their members:
|
||||
$query = "SELECT list_pub_members($id_party)";
|
||||
$res = exec_pdo_query($db, $query);
|
||||
$info = $res->fetch(PDO::FETCH_NUM);
|
||||
foreach ($info as $item) {
|
||||
$this->create_relatedObject($item,'hasMember');
|
||||
}
|
||||
}
|
||||
} // end of class ANDS_TPA
|
|
@ -1,76 +0,0 @@
|
|||
<?php
|
||||
//
|
||||
// DATABASE SETUP
|
||||
//
|
||||
$DB_HOST = '';
|
||||
$DB_USER = '';
|
||||
$DB_PASSWD = '';
|
||||
$DB_NAME = '';
|
||||
|
||||
/*
|
||||
* - <b>$SQL</b>: Settings for database and queries from database
|
||||
*
|
||||
* - <b>$DSN</b>: DSN for connecting your database. Reference PDO for details.
|
||||
*
|
||||
*/
|
||||
|
||||
// Data Source Name: This is the universal connection string
|
||||
// if you use something other than mysql edit accordingly.
|
||||
// Example for MySQL
|
||||
// $DSN = "mysql://$DB_USER:$DB_PASSWD@$DB_HOST/$DB_NAME";
|
||||
// Example for Oracle
|
||||
// $DSN = "oci8://$DB_USER:$DB_PASSWD@$DB_NAME";
|
||||
|
||||
$DSN = "mysql:host={$DB_HOST};dbname={$DB_NAME};port=3306;";
|
||||
|
||||
// the charset you store your metadata in your database
|
||||
// currently only utf-8 and iso8859-1 are supported
|
||||
$charset = "utf8";
|
||||
|
||||
// if entities such as < > ' " in your metadata has already been escaped
|
||||
// then set this to true (e.g. you store < as < in your DB)
|
||||
$xmlescaped = false;
|
||||
|
||||
// We store multiple entries for one element in a single row
|
||||
// in the database. SQL['split'] lists the delimiter for these entries.
|
||||
// If you do not do this, do not define $SQL['split']
|
||||
// $SQL['split'] = ';';
|
||||
|
||||
// the name of the table where your store your metadata's header
|
||||
$SQL['table'] = 'oai_headers';
|
||||
|
||||
// the name of the column where you store the unique identifiers
|
||||
// pointing to your item.
|
||||
// this is your internal identifier for the item
|
||||
$SQL['identifier'] = 'oai_identifier';
|
||||
|
||||
$SQL['metadataPrefix'] = 'oai_metadataprefix';
|
||||
|
||||
// If you want to expand the internal identifier in some way
|
||||
// use this (but not for OAI stuff, see next line)
|
||||
$idPrefix = '';
|
||||
|
||||
// this is your external (OAI) identifier for the item
|
||||
// this will be expanded to
|
||||
// oai:$repositoryIdentifier:$idPrefix$SQL['identifier']
|
||||
// should not be changed
|
||||
//
|
||||
// Commented out 24/11/10 14:19:09
|
||||
// $oaiprefix = "oai".$delimiter.$repositoryIdentifier.$delimiter.$idPrefix;
|
||||
$oaiprefix = "";
|
||||
|
||||
// adjust anIdentifier with sample contents an identifier
|
||||
// $sampleIdentifier = $oaiprefix.'anIdentifier';
|
||||
|
||||
// the name of the column where you store your datestamps
|
||||
$SQL['datestamp'] = 'datestamp';
|
||||
|
||||
// the name of the column where you store information whether
|
||||
// a record has been deleted. Leave it as it is if you do not use
|
||||
// this feature.
|
||||
$SQL['deleted'] = 'deleted';
|
||||
|
||||
// to be able to quickly retrieve the sets to which one item belongs,
|
||||
// the setnames are stored for each item
|
||||
// the name of the column where you store sets
|
||||
$SQL['set'] = 'oai_set';
|
|
@ -1,35 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* - <b>$METADATAFORMATS</b>: List of supported metadata formats. It is a two-dimensional array with keys.
|
||||
* Each supported format is one element of this array at the first dimension.
|
||||
* The key is the name of a metadata format.
|
||||
* The exact number of items within each format associated array depends on the nature of a metadata format.
|
||||
* Most definitions are done here but handlers themselves are defined in separated files because only the names of PHP script are listed here.
|
||||
* - metadataPrefix
|
||||
* - schema
|
||||
* - metadataNamespace
|
||||
* - myhandler
|
||||
* - other optional items: record_prefix, record_namespace and etc.
|
||||
*/
|
||||
// define all supported metadata formats, has to be an array
|
||||
//
|
||||
// myhandler is the name of the file that handles the request for the
|
||||
// specific metadata format.
|
||||
// [record_prefix] describes an optional prefix for the metadata
|
||||
// [record_namespace] describe the namespace for this prefix
|
||||
|
||||
|
||||
$METADATAFORMATS = array (
|
||||
'rif' => array('metadataPrefix'=>'rif',
|
||||
'schema'=>'http://services.ands.org.au/sandbox/orca/schemata/registryObjects.xsd',
|
||||
'metadataNamespace'=>'http://ands.org.au/standards/rif-cs/registryObjects/',
|
||||
),
|
||||
'oai_dc' => array('metadataPrefix'=>'oai_dc',
|
||||
'schema'=>'http://www.openarchives.org/OAI/2.0/oai_dc.xsd',
|
||||
'metadataNamespace'=>'http://www.openarchives.org/OAI/2.0/oai_dc/',
|
||||
'record_prefix'=>'dc',
|
||||
'record_namespace' => 'http://purl.org/dc/elements/1.1/'
|
||||
)
|
||||
);
|
||||
|
||||
if (!is_array($METADATAFORMATS)) { exit("Configuration of METADATAFORMAT has been wrongly set. Correct your ".__FILE__);}
|
|
@ -1,28 +0,0 @@
|
|||
<?php
|
||||
/*
|
||||
*
|
||||
* - <b>$SETS</b>: An array with key words . List of supported SETs.
|
||||
*
|
||||
*/
|
||||
|
||||
// define all supported sets in your repository
|
||||
$SETS = array (
|
||||
array('setSpec'=>'class:activity', 'setName'=>'Activities'),
|
||||
array('setSpec'=>'class:collection', 'setName'=>'Collections'),
|
||||
array('setSpec'=>'class:party', 'setName'=>'Parties'),
|
||||
/*
|
||||
array('setSpec'=>'math', 'setName'=>'Mathematics') ,
|
||||
array('setSpec'=>'phys', 'setName'=>'Physics'),
|
||||
|
||||
array('setSpec'=>'phdthesis',
|
||||
'setName'=>'PHD Thesis',
|
||||
'setDescription'=>'<oai_dc:dc 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">
|
||||
<dc:description>This set contains metadata describing
|
||||
electronic music recordings made during the 1950ies</dc:description>
|
||||
</oai_dc:dc>')
|
||||
*/
|
||||
);
|
122
oai2.php
122
oai2.php
|
@ -8,62 +8,15 @@
|
|||
* @see http://www.openarchives.org/OAI/2.0/openarchivesprotocol.htm
|
||||
*
|
||||
* It needs other files:
|
||||
* - oaidp-config.php : Configuration of provider
|
||||
* - oaidp-util.php : Utility functions
|
||||
* - xml_creater.php : XML generating functions
|
||||
*
|
||||
* \todo <b>Remember:</b> to define your own classess for generating metadata records.
|
||||
* In common cases, you have to implement your own code to act fully and correctly.
|
||||
* For generic usage, you can try the ANDS_Response_XML defined in xml_creater.php.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Supported attributes associate to verbs.
|
||||
*/
|
||||
|
||||
if (in_array($_SERVER['REQUEST_METHOD'],array('GET','POST'))) {
|
||||
$args = $_REQUEST;
|
||||
} else {
|
||||
$errors[] = oai_error('badRequestMethod', $_SERVER['REQUEST_METHOD']);
|
||||
}
|
||||
define('MY_URI', 'dev2.moodle.ufsc.br');
|
||||
|
||||
require_once('oaidp-util.php');
|
||||
|
||||
// Always using htmlentities() function to encodes the HTML entities submitted by others.
|
||||
// No one can be trusted.
|
||||
foreach ($args as $key => $val) {
|
||||
$checking = htmlspecialchars(stripslashes($val));
|
||||
if (!is_valid_attrb($checking)) {
|
||||
$errors[] = oai_error('badArgument', $checking);
|
||||
} else {$args[$key] = $checking; }
|
||||
}
|
||||
if (!empty($errors)) {
|
||||
oai_exit();
|
||||
}
|
||||
|
||||
$attribs = array ('from', 'identifier', 'metadataPrefix', 'set', 'resumptionToken', 'until');
|
||||
foreach($attribs as $val) {
|
||||
unset($$val);
|
||||
}
|
||||
|
||||
require_once('oaidp-config.php');
|
||||
require_once('config/metadataformats.php');
|
||||
require_once('config/sets.php');
|
||||
require_once('config/database.php');
|
||||
|
||||
// For generic usage or just trying:
|
||||
// require_once('xml_creater.php');
|
||||
// In common cases, you have to implement your own code to act fully and correctly.
|
||||
require_once('ands_tpa.php');
|
||||
|
||||
// Default, there is no compression supported
|
||||
$compress = FALSE;
|
||||
if (isset($compression) && is_array($compression)) {
|
||||
if (in_array('gzip', $compression) && ini_get('output_buffering')) {
|
||||
$compress = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
require_once('xml_creater.php');
|
||||
require_once('oai2server.php');
|
||||
|
||||
/**
|
||||
|
@ -94,6 +47,73 @@ $identifyResponse["deletedRecord"] = 'no'; // How your repository handles deleti
|
|||
// maintained. It MAY reveal a deleted status for records.
|
||||
$identifyResponse["granularity"] = 'YYYY-MM-DDThh:mm:ssZ';
|
||||
|
||||
$repositoryIdentifier = 'dev2.moodle.ufsc.br.';
|
||||
$oai2 = new OAI2Server($_REQUEST, $identifyResponse,
|
||||
array(
|
||||
'ListMetadataFormats' =>
|
||||
function($identifier = '') {
|
||||
// throws new OAI2Exception('idDoesNotExist', '', $identifier)
|
||||
return
|
||||
array('rif' => array('metadataPrefix'=>'rif',
|
||||
'schema'=>'http://services.ands.org.au/sandbox/orca/schemata/registryObjects.xsd',
|
||||
'metadataNamespace'=>'http://ands.org.au/standards/rif-cs/registryObjects/',
|
||||
),
|
||||
'oai_dc' => array('metadataPrefix'=>'oai_dc',
|
||||
'schema'=>'http://www.openarchives.org/OAI/2.0/oai_dc.xsd',
|
||||
'metadataNamespace'=>'http://www.openarchives.org/OAI/2.0/oai_dc/',
|
||||
'record_prefix'=>'dc',
|
||||
'record_namespace' => 'http://purl.org/dc/elements/1.1/'));
|
||||
},
|
||||
|
||||
$oai2 = new OAI2Server($args, $repositoryIdentifier, $identifyResponse);
|
||||
'ListSets' =>
|
||||
function($resumptionToken = '') {
|
||||
return
|
||||
array (
|
||||
array('setSpec'=>'class:collection', 'setName'=>'Collections'),
|
||||
array('setSpec'=>'math', 'setName'=>'Mathematics') ,
|
||||
array('setSpec'=>'phys', 'setName'=>'Physics'),
|
||||
array('setSpec'=>'phdthesis', 'setName'=>'PHD Thesis',
|
||||
'setDescription'=>
|
||||
'<oai_dc:dc 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"> '.
|
||||
' <dc:description>This set contains metadata describing '.
|
||||
' electronic music recordings made during the 1950ies</dc:description> '.
|
||||
' </oai_dc:dc>'));
|
||||
},
|
||||
|
||||
'ListRecords' =>
|
||||
function($metadataPrefix, $from = '', $until = '', $set = '', $count = false, $deliveredRecords = 0, $maxItems = 0) {
|
||||
// throws new OAI2Exception('noRecordsMatch')
|
||||
// throws new OAI2Exception('noSetHierarchy')
|
||||
if ($count) {
|
||||
return 10;
|
||||
}
|
||||
return array();
|
||||
},
|
||||
|
||||
'GetRecord' =>
|
||||
function($identifier, $metadataPrefix) {
|
||||
// throws new OAI2Exception('idDoesNotExist', '', $identifier) if record not found
|
||||
|
||||
return 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'
|
||||
)
|
||||
));
|
||||
},
|
||||
)
|
||||
);
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
class OAI2Exception extends Exception {
|
||||
|
||||
function __construct($code = 0, $argument = '', $value = '') {
|
||||
|
||||
$this->errorTable = array(
|
||||
'badArgument' => array(
|
||||
'text' => "Attribute '{$argument}' is not allowed to appear in element 'request'.",
|
||||
),
|
||||
'badGranularity' => array(
|
||||
'text' => "The value '{$value}' of attribute '{$argument}' on element 'request' is not valid with respect to its type, 'UTCdatetimeType'.",
|
||||
'code' => 'badArgument',
|
||||
),
|
||||
|
||||
'badResumptionToken' => array(
|
||||
'text' => "The resumptionToken '{$value}' does not exist or has already expired.",
|
||||
),
|
||||
'badRequestMethod' => array(
|
||||
'text' => "The request method '{$argument}' is unknown.",
|
||||
'code' => 'badVerb',
|
||||
),
|
||||
'badVerb' => array(
|
||||
'text' => "The value '{$argument}' of attribute 'verb' on element 'request' is not valid with respect to its type, 'verbType'",
|
||||
),
|
||||
'cannotDisseminateFormat' => array(
|
||||
'text' => "The metadata format '{$value}' given by {$argument} is not supported by this repository.",
|
||||
),
|
||||
'exclusiveArgument' => array(
|
||||
'text' => 'The usage of resumptionToken as an argument allows no other arguments.',
|
||||
'code' => 'badArgument',
|
||||
),
|
||||
'idDoesNotExist' => array(
|
||||
'text' => "The value '{$value}' of the identifier does not exist in this repository.",
|
||||
/*
|
||||
if (!is_valid_uri($value)) {
|
||||
'code' = 'badArgument',
|
||||
'text' .= ' Invalidated URI has been detected.',
|
||||
}
|
||||
*/
|
||||
),
|
||||
'missingArgument' => array(
|
||||
'text' => "The required argument '{$argument}' is missing in the request.",
|
||||
'code' => 'badArgument',
|
||||
),
|
||||
'noRecordsMatch' => array(
|
||||
'text' => 'The combination of the given values results in an empty list.',
|
||||
),
|
||||
'noMetadataFormats' => array(
|
||||
'text' => 'There are no metadata formats available for the specified item.',
|
||||
),
|
||||
'noVerb' => array(
|
||||
'text' => 'The request does not provide any verb.',
|
||||
'code' => 'badVerb',
|
||||
),
|
||||
'noSetHierarchy' => array(
|
||||
'text' => 'This repository does not support sets.',
|
||||
),
|
||||
'sameArgument' => array(
|
||||
'text' => 'Do not use the same argument more than once.',
|
||||
'code' => 'badArgument',
|
||||
),
|
||||
'sameVerb' => array(
|
||||
'text' => 'Do not use verb more than once.',
|
||||
'code' => 'badVerb',
|
||||
),
|
||||
'notImp' => array(
|
||||
'text' => 'Not yet implemented.',
|
||||
'code' => 'debug',
|
||||
),
|
||||
''=> array(
|
||||
'text' => "Unknown error: code: '{'code'}', argument: '{$argument}', value: '{$value}'",
|
||||
'code' => 'badArgument',
|
||||
)
|
||||
);
|
||||
parent::__construct($this->errorTable[$code]['text'], $code);
|
||||
}
|
||||
}
|
634
oai2server.php
634
oai2server.php
|
@ -1,95 +1,75 @@
|
|||
<?php
|
||||
/*
|
||||
* - Actions:
|
||||
* - identify.php : About the provider
|
||||
* - listmetadataformats.php : List supported metadata formats
|
||||
* - listrecords.php : List identifiers and records
|
||||
* - listsets.php : List sets
|
||||
* - getrecord.php : Get a record / Your own implementation for providing metadata records.
|
||||
|
||||
require_once('oai2exception.php');
|
||||
require_once('oai2xml.php');
|
||||
|
||||
/**
|
||||
* The content-type the WWW-server delivers back. For debug-puposes, "text/plain"
|
||||
* is easier to view. On a production site you should use "text/xml".
|
||||
*/
|
||||
define('CONTENT_TYPE', 'Content-Type: text/xml');
|
||||
|
||||
/** After 24 hours resumptionTokens become invalid. Unit is second. */
|
||||
define('TOKEN_VALID',24*3600);
|
||||
|
||||
/** Where token is saved and path is included */
|
||||
define('TOKEN_PREFIX','/tmp/oai_pmh-');
|
||||
|
||||
class OAI2Server {
|
||||
|
||||
public $errors = array();
|
||||
|
||||
/*
|
||||
* @param $delimiter = ':'; should not be changed. Only useful when NODE description is included in the response to Identifier
|
||||
*/
|
||||
function __construct($args, $repositoryIdentifier, $identifyResponse,
|
||||
$delimiter = ':', $sampleIdentifier = false, $show_identifier = false) {
|
||||
function __construct($args, $identifyResponse, $callbacks) {
|
||||
|
||||
$this->args = $args;
|
||||
$this->repositoryIdentier = $repositoryIdentifier;
|
||||
$this->identifyResponse = $identifyResponse;
|
||||
$this->listMetadataFormatsCallback = $callbacks['ListMetadataFormats'];
|
||||
$this->listSetsCallback = $callbacks['ListSets'];
|
||||
$this->listRecordsCallback = $callbacks['ListRecords'];
|
||||
$this->getRecordCallback = $callbacks['GetRecord'];
|
||||
$this->respond();
|
||||
}
|
||||
|
||||
private function respond() {
|
||||
if (!isset($this->args['verb']) || empty($this->args['verb'])) {
|
||||
$this->errors[] = oai_error('noVerb');
|
||||
$this->errors[] = new OAI2Exception('noVerb');
|
||||
} else {
|
||||
switch ($this->args['verb']) {
|
||||
|
||||
case 'Identify':
|
||||
// we never use compression in Identify
|
||||
$compress = FALSE;
|
||||
$this->outputObj = $this->identify();
|
||||
break;
|
||||
case 'Identify': $this->identify(); break;
|
||||
|
||||
case 'ListMetadataFormats':
|
||||
$this->outputObj = $this->listMetadataFormats();
|
||||
break;
|
||||
case 'ListMetadataFormats': $this->listMetadataFormats(); break;
|
||||
|
||||
case 'ListSets':
|
||||
$this->outputObj = $this->listSets();
|
||||
break;
|
||||
case 'ListSets': $this->listSets(); break;
|
||||
|
||||
case 'ListIdentifiers':
|
||||
case 'ListRecords':
|
||||
$this->outputObj = $this->listRecords();
|
||||
break;
|
||||
case 'ListRecords': $this->listRecords(); break;
|
||||
|
||||
case 'GetRecord':
|
||||
$this->outputObj = $this->getRecord();
|
||||
break;
|
||||
case 'GetRecord': $this->getRecord(); break;
|
||||
|
||||
default:
|
||||
// we never use compression with errors
|
||||
$compress = FALSE;
|
||||
$this->errors[] = oai_error('badVerb', $this->args['verb']);
|
||||
default: $this->errors[] = new OAI2Exception('badVerb', $this->args['verb']);
|
||||
}
|
||||
}
|
||||
if (empty($this->errors)) {
|
||||
$this->display();
|
||||
|
||||
if (isset($this->outputObj)) {
|
||||
header(CONTENT_TYPE);
|
||||
$this->outputObj->display();
|
||||
} else {
|
||||
exit("Nothing to output. May be a bug.");
|
||||
}
|
||||
} else {
|
||||
$this->errorResponse();
|
||||
}
|
||||
}
|
||||
|
||||
function errorResponse() {
|
||||
$e = new ANDS_Error_XML($this->args,$this->errors);
|
||||
private function errorResponse() {
|
||||
$e = new OAI2XMLError($this->args,$this->errors);
|
||||
header(CONTENT_TYPE);
|
||||
$e->display();
|
||||
exit();
|
||||
}
|
||||
|
||||
function display() {
|
||||
if (isset($this->outputObj)) {
|
||||
|
||||
if ($compress) {
|
||||
ob_start('ob_gzhandler');
|
||||
}
|
||||
|
||||
header(CONTENT_TYPE);
|
||||
$this->outputObj->display();
|
||||
|
||||
if ($compress) {
|
||||
ob_end_flush();
|
||||
}
|
||||
|
||||
} else {
|
||||
exit("Nothing to output. May be a bug.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Response to Verb Identify
|
||||
*
|
||||
|
@ -97,194 +77,48 @@ class OAI2Server {
|
|||
*
|
||||
* http://www.openarchives.org/OAI/2.0/guidelines-oai-identifier.htm for details
|
||||
*/
|
||||
public function identify($show_identifier, $repositoryIdentifier, $delimiter, $sampleIdentifier) {
|
||||
public function identify() {
|
||||
|
||||
if (count($this->args) > 1) {
|
||||
foreach($args as $key => $val) {
|
||||
if(strcmp($key,"verb")!=0) {
|
||||
$this->errors[] = oai_error('badArgument', $key, $val);
|
||||
$this->errors[] = new OAI2Exception('badArgument', $key, $val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$outputObj = new ANDS_Response_XML($this->args);
|
||||
$this->outputObj = new ANDS_Response_XML($this->args);
|
||||
foreach($this->identifyResponse as $key => $val) {
|
||||
$outputObj->add2_verbNode($key, $val);
|
||||
$this->outputObj->add2_verbNode($key, $val);
|
||||
}
|
||||
|
||||
// A description MAY be included.
|
||||
// Use this if you choose to comply with a specific format of unique identifiers
|
||||
// for items.
|
||||
// See http://www.openarchives.org/OAI/2.0/guidelines-oai-identifier.htm
|
||||
// for details
|
||||
|
||||
// As they will not be changed, using string for simplicity.
|
||||
$output = '';
|
||||
if ($this->show_identifier && $this->repositoryIdentifier && $this->delimiter && $this->sampleIdentifier) {
|
||||
$output .=
|
||||
' <description>
|
||||
<oai-identifier xmlns="http://www.openarchives.org/OAI/2.0/oai-identifier"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/oai-identifier
|
||||
http://www.openarchives.org/OAI/2.0/oai-identifier.xsd">
|
||||
<scheme>oai</scheme>
|
||||
<repositoryIdentifier>'.$repositoryIdentifier.'</repositoryIdentifier>
|
||||
<delimiter>'.$delimiter.'</delimiter>
|
||||
<sampleIdentifier>'.$sampleIdentifier.'</sampleIdentifier>
|
||||
</oai-identifier>
|
||||
</description>'."\n";
|
||||
}
|
||||
|
||||
// A description MAY be included.
|
||||
// This example from arXiv.org is used by the e-prints community, please adjust
|
||||
// see http://www.openarchives.org/OAI/2.0/guidelines-eprints.htm for details
|
||||
|
||||
// To include, change 'false' to 'true'.
|
||||
if (false) {
|
||||
$output .=
|
||||
' <description>
|
||||
<eprints xmlns="http://www.openarchives.org/OAI/1.1/eprints"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.openarchives.org/OAI/1.1/eprints
|
||||
http://www.openarchives.org/OAI/1.1/eprints.xsd">
|
||||
<content>
|
||||
<text>Author self-archived e-prints</text>
|
||||
</content>
|
||||
<metadataPolicy />
|
||||
<dataPolicy />
|
||||
<submissionPolicy />
|
||||
</eprints>
|
||||
</description>'."\n";
|
||||
}
|
||||
|
||||
// If you want to point harvesters to other repositories, you can list their
|
||||
// base URLs. Usage of friends container is RECOMMENDED.
|
||||
// see http://www.openarchives.org/OAI/2.0/guidelines-friends.htm
|
||||
// for details
|
||||
|
||||
// To include, change 'false' to 'true'.
|
||||
if (false) {
|
||||
$output .=
|
||||
' <description>
|
||||
<friends xmlns="http://www.openarchives.org/OAI/2.0/friends/"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/friends/
|
||||
http://www.openarchives.org/OAI/2.0/friends.xsd">
|
||||
<baseURL>http://naca.larc.nasa.gov/oai2.0/</baseURL>
|
||||
<baseURL>http://techreports.larc.nasa.gov/ltrs/oai2.0/</baseURL>
|
||||
<baseURL>http://physnet.uni-oldenburg.de/oai/oai2.php</baseURL>
|
||||
<baseURL>http://cogprints.soton.ac.uk/perl/oai</baseURL>
|
||||
<baseURL>http://ub.uni-duisburg.de:8080/cgi-oai/oai.pl</baseURL>
|
||||
<baseURL>http://rocky.dlib.vt.edu/~jcdlpix/cgi-bin/OAI1.1/jcdlpix.pl</baseURL>
|
||||
</friends>
|
||||
</description>'."\n";
|
||||
}
|
||||
|
||||
// If you want to provide branding information, adjust accordingly.
|
||||
// Usage of friends container is OPTIONAL.
|
||||
// see http://www.openarchives.org/OAI/2.0/guidelines-branding.htm
|
||||
// for details
|
||||
|
||||
// To include, change 'false' to 'true'.
|
||||
if (false) {
|
||||
$output .=
|
||||
' <description>
|
||||
<branding xmlns="http://www.openarchives.org/OAI/2.0/branding/"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/branding/
|
||||
http://www.openarchives.org/OAI/2.0/branding.xsd">
|
||||
<collectionIcon>
|
||||
<url>http://my.site/icon.png</url>
|
||||
<link>http://my.site/homepage.html</link>
|
||||
<title>MySite(tm)</title>
|
||||
<width>88</width>
|
||||
<height>31</height>
|
||||
</collectionIcon>
|
||||
<metadataRendering
|
||||
metadataNamespace="http://www.openarchives.org/OAI/2.0/oai_dc/"
|
||||
mimeType="text/xsl">http://some.where/DCrender.xsl</metadataRendering>
|
||||
<metadataRendering
|
||||
metadataNamespace="http://another.place/MARC"
|
||||
mimeType="text/css">http://another.place/MARCrender.css</metadataRendering>
|
||||
</branding>
|
||||
</description>'."\n";
|
||||
}
|
||||
|
||||
if(strlen($output)>10) {
|
||||
$des = $outputObj->doc->createDocumentFragment();
|
||||
$des->appendXML($output);
|
||||
$outputObj->verbNode->appendChild($des);
|
||||
}
|
||||
|
||||
return $outputObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Response to Verb ListMetadataFormats
|
||||
*
|
||||
* The information of supported metadata formats :
|
||||
* try database table $SQL['table']
|
||||
* else try $METADATAFORMATS array from config-metadataformats.php
|
||||
* The information of supported metadata formats
|
||||
*/
|
||||
public function listMetadataFormats() {
|
||||
global $DSN, $DB_USER, $DB_PASSWD, $METADATAFORMATS, $SQL;
|
||||
|
||||
$checkList = array("ops"=>array("identifier"));
|
||||
$this->checkArgs($checkList);
|
||||
|
||||
// Create a PDO object
|
||||
try {
|
||||
$db = new PDO($DSN, $DB_USER, $DB_PASSWD);
|
||||
} catch (PDOException $e) {
|
||||
exit('Connection failed: ' . $e->getMessage());
|
||||
if ($formats = call_user_func($this->listMetadataFormatsCallback, $this->args['identifier'])) {
|
||||
$this->outputObj = new ANDS_Response_XML($this->args);
|
||||
foreach($formats as $key => $val) {
|
||||
$cmf = $this->outputObj->add2_verbNode("metadataFormat");
|
||||
$this->outputObj->addChild($cmf,'metadataPrefix',$key);
|
||||
$this->outputObj->addChild($cmf,'schema',$val['schema']);
|
||||
$this->outputObj->addChild($cmf,'metadataNamespace',$val['metadataNamespace']);
|
||||
}
|
||||
|
||||
if (isset($this->args['identifier'])) {
|
||||
|
||||
$identifier = $this->args['identifier'];
|
||||
$query = 'select '.$SQL['metadataPrefix'].' FROM '.$SQL['table']. " WHERE ".$SQL['identifier']." = '".$id."'";
|
||||
$res = $db->query($query);
|
||||
|
||||
if ($res==false) {
|
||||
if (SHOW_QUERY_ERROR) {
|
||||
echo __FILE__.','.__LINE__."<br />";
|
||||
echo "Query: $query<br />\n";
|
||||
die($db->errorInfo());
|
||||
} else {
|
||||
$this->errors[] = oai_error('idDoesNotExist','', $identifier);
|
||||
}
|
||||
} else {
|
||||
$record = $res->fetch();
|
||||
if($record===false) {
|
||||
$this->errors[] = oai_error('idDoesNotExist', '', $identifier);
|
||||
} else {
|
||||
$mf = explode(",",$record[$SQL['metadataPrefix']]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//break and clean up on error
|
||||
if (!empty($this->errors)) {
|
||||
$this->errorResponse();
|
||||
}
|
||||
|
||||
$outputObj = new ANDS_Response_XML($this->args);
|
||||
if (isset($mf)) {
|
||||
foreach($mf as $key) {
|
||||
$val = $METADATAFORMATS[$key];
|
||||
$this->addMetedataFormat($outputObj,$key, $val);
|
||||
}
|
||||
} elseif (is_array($METADATAFORMATS)) {
|
||||
foreach($METADATAFORMATS as $key=>$val) {
|
||||
$this->addMetedataFormat($outputObj,$key, $val);
|
||||
}
|
||||
} else { // a very unlikely event
|
||||
$this->errors[] = oai_error('noMetadataFormats');
|
||||
$this->errorResponse();
|
||||
}
|
||||
|
||||
return $outputObj;
|
||||
}
|
||||
$this->errors[] = new OAI2Exception('noMetadataFormats');
|
||||
} catch (OAI2Exception $e) {
|
||||
$this->errors[] = $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Response to Verb ListSets
|
||||
|
@ -293,36 +127,34 @@ class OAI2Server {
|
|||
* This variable is filled in config-sets.php
|
||||
*/
|
||||
public function listSets() {
|
||||
global $SETS;
|
||||
|
||||
$sets = $SETS;
|
||||
|
||||
if (isset($this->args['resumptionToken']) && count($this->args) > 2) {
|
||||
$this->errors[] = oai_error('exclusiveArgument');
|
||||
$this->errors[] = new OAI2Exception('exclusiveArgument');
|
||||
}
|
||||
$checkList = array("ops"=>array("resumptionToken"));
|
||||
$this->checkArgs($checkList);
|
||||
|
||||
if (is_array($sets)) {
|
||||
$outputObj = new ANDS_Response_XML($this->args);
|
||||
if ($sets = call_user_func($this->listSetsCallback)) {
|
||||
|
||||
$this->outputObj = new ANDS_Response_XML($this->args);
|
||||
foreach($sets as $set) {
|
||||
$setNode = $outputObj->add2_verbNode("set");
|
||||
|
||||
$setNode = $this->outputObj->add2_verbNode("set");
|
||||
|
||||
foreach($set as $key => $val) {
|
||||
if($key=='setDescription') {
|
||||
$desNode = $outputObj->addChild($setNode,$key);
|
||||
$des = $outputObj->doc->createDocumentFragment();
|
||||
$desNode = $this->outputObj->addChild($setNode,$key);
|
||||
$des = $this->outputObj->doc->createDocumentFragment();
|
||||
$des->appendXML($val);
|
||||
$desNode->appendChild($des);
|
||||
} else {
|
||||
$outputObj->addChild($setNode,$key,$val);
|
||||
$this->outputObj->addChild($setNode,$key,$val);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->errors[] = oai_error('noSetHierarchy');
|
||||
oai_exit();
|
||||
$this->errors[] = new OAI2Exception('noSetHierarchy');
|
||||
}
|
||||
return $outputObj;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -335,62 +167,44 @@ class OAI2Server {
|
|||
* The reset of information will be extracted from database based those two parameters.
|
||||
*/
|
||||
public function getRecord() {
|
||||
global $METADATAFORMATS, $DSN, $DB_USER, $DB_PASSWD, $SQL;
|
||||
|
||||
$checkList = array("required"=>array("metadataPrefix","identifier"));
|
||||
$this->checkArgs($checkList);
|
||||
|
||||
$metadataPrefix = $this->args['metadataPrefix'];
|
||||
|
||||
if (!isset($METADATAFORMATS[$metadataPrefix])) {
|
||||
$this->errors[] = oai_error('cannotDisseminateFormat', 'metadataPrefix', $metadataPrefix);
|
||||
$metadataFormats = call_user_func($this->listMetadataFormatsCallback);
|
||||
|
||||
if (!isset($metadataFormats[$metadataPrefix])) {
|
||||
$this->errors[] = new OAI2Exception('cannotDisseminateFormat', 'metadataPrefix', $metadataPrefix);
|
||||
}
|
||||
|
||||
// Create a PDO object
|
||||
try {
|
||||
$db = new PDO($DSN, $DB_USER, $DB_PASSWD);
|
||||
} catch (PDOException $e) {
|
||||
exit('Connection failed: ' . $e->getMessage());
|
||||
}
|
||||
if ($record = call_user_func($this->getRecordCallback, $this->args['identifier'], $metadataPrefix)) {
|
||||
|
||||
$identifier = $this->args['identifier'];
|
||||
$query = selectallQuery($metadataPrefix, $identifier);
|
||||
$identifier = $record['identifier'];
|
||||
|
||||
$res = $db->query($query);
|
||||
$datestamp = formatDatestamp($record['datestamp']);
|
||||
|
||||
if ($res===false) {
|
||||
$this->errors[] = oai_error('idDoesNotExist', '', $identifier);
|
||||
} elseif (!$res->rowCount()) { // based on PHP manual, it might only work for some DBs
|
||||
$this->errors[] = oai_error('idDoesNotExist', '', $identifier);
|
||||
}
|
||||
$set = $record['set'];
|
||||
|
||||
if (!empty($this->errors)) {
|
||||
oai_exit();
|
||||
}
|
||||
$status_deleted = (isset($record['deleted']) && ($record['deleted'] == 'true') &&
|
||||
(($this->identifyResponse['deletedRecord'] == 'transient') ||
|
||||
($this->identifyResponse['deletedRecord'] == 'persistent')));
|
||||
|
||||
$record = $res->fetch(PDO::FETCH_ASSOC);
|
||||
if ($record===false) {
|
||||
$this->errors[] = oai_error('idDoesNotExist', '', $identifier);
|
||||
}
|
||||
|
||||
$identifier = $record[$SQL['identifier']];;
|
||||
|
||||
$datestamp = formatDatestamp($record[$SQL['datestamp']]);
|
||||
|
||||
$status_deleted = (isset($record[$SQL['deleted']]) && ($record[$SQL['deleted']] == 'true') &&
|
||||
($this->identifyResponse['deletedRecord'] == 'transient' || $this->identifyResponse['deletedRecord'] == 'persistent'));
|
||||
|
||||
$outputObj = new ANDS_Response_XML($this->args);
|
||||
$cur_record = $outputObj->create_record();
|
||||
$cur_header = $outputObj->create_header($identifier, $datestamp,$record[$SQL['set']],$cur_record);
|
||||
// return the metadata record itself
|
||||
$this->outputObj = new ANDS_Response_XML($this->args);
|
||||
$cur_record = $this->outputObj->create_record();
|
||||
$cur_header = $this->outputObj->create_header($identifier, $datestamp, $set, $cur_record);
|
||||
if ($status_deleted) {
|
||||
$cur_header->setAttribute("status","deleted");
|
||||
} else {
|
||||
call_user_func(array($this, "{$metadataPrefix}_create_metadata"),
|
||||
$outputObj, $cur_record, $identifier, $record[$SQL['set']], $db);
|
||||
$this->add_metadata($cur_record, $record);
|
||||
|
||||
}
|
||||
}
|
||||
} catch (OAI2Exception $e) {
|
||||
$this->errors[] = $e;
|
||||
}
|
||||
return $outputObj;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -402,13 +216,10 @@ class OAI2Server {
|
|||
* Only 'metadataPrefix' is compulsory. All conditions are accessible through global array variable <B>$args</B> by keywords.
|
||||
*/
|
||||
public function listRecords() {
|
||||
global $SQL, $METADATAFORMATS, $DSN, $DB_USER, $DB_PASSWD, $SETS;
|
||||
|
||||
$sets = $SETS;
|
||||
|
||||
if (isset($this->args['resumptionToken'])) {
|
||||
if (count($this->args) > 2) {
|
||||
$this->errors[] = oai_error('exclusiveArgument');
|
||||
$this->errors[] = new OAI2Exception('exclusiveArgument');
|
||||
}
|
||||
$checkList = array("ops"=>array("resumptionToken"));
|
||||
} else {
|
||||
|
@ -416,203 +227,103 @@ class OAI2Server {
|
|||
}
|
||||
$this->checkArgs($checkList);
|
||||
|
||||
$metadataFormats = call_user_func($this->listMetadataFormatsCallback, $this->args);
|
||||
if (!isset($metadataFormats[$this->args['metadataPrefix']])) {
|
||||
$this->errors[] = new OAI2Exception('cannotDisseminateFormat', 'metadataPrefix', $this->args['metadataPrefix']);
|
||||
}
|
||||
|
||||
// Resume previous session?
|
||||
if (isset($this->args['resumptionToken'])) {
|
||||
|
||||
if (!file_exists(TOKEN_PREFIX.$this->args['resumptionToken'])) {
|
||||
$this->errors[] = oai_error('badResumptionToken', '', $this->args['resumptionToken']);
|
||||
$this->errors[] = new OAI2Exception('badResumptionToken', '', $this->args['resumptionToken']);
|
||||
} else {
|
||||
$readings = readResumToken(TOKEN_PREFIX.$this->args['resumptionToken']);
|
||||
if ($readings == false) {
|
||||
$this->errors[] = oai_error('badResumptionToken', '', $this->args['resumptionToken']);
|
||||
} else {
|
||||
list($deliveredrecords, $extquery, $metadataPrefix) = $readings;
|
||||
}
|
||||
}
|
||||
} else { // no, we start a new session
|
||||
$deliveredrecords = 0;
|
||||
$extquery = '';
|
||||
|
||||
if ($readings = $this->readResumptionToken(TOKEN_PREFIX.$this->args['resumptionToken'])) {
|
||||
list($deliveredRecords, $metadataPrefix, $from, $until, $set) = $readings;
|
||||
} else {
|
||||
$this->errors[] = new OAI2Exception('badResumptionToken', '', $this->args['resumptionToken']);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
$deliveredRecords = 0;
|
||||
$metadataPrefix = $this->args['metadataPrefix'];
|
||||
|
||||
if (isset($args['from'])) {
|
||||
$from = checkDateFormat($this->args['from']);
|
||||
$extquery .= fromQuery($from);
|
||||
}
|
||||
|
||||
if (isset($args['until'])) {
|
||||
$until = checkDateFormat($this->args['until']);
|
||||
$extquery .= untilQuery($until);
|
||||
}
|
||||
|
||||
if (isset($args['set'])) {
|
||||
if (is_array($sets)) {
|
||||
$extquery .= setQuery($this->args['set']);
|
||||
} else {
|
||||
$this->errors[] = oai_error('noSetHierarchy');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($METADATAFORMATS[$metadataPrefix])) {
|
||||
$this->errors[] = oai_error('cannotDisseminateFormat', 'metadataPrefix', $metadataPrefix);
|
||||
$from = isset($this->args['from']) ? $this->args['from'] : '';
|
||||
$until = isset($this->args['until']) ? $this->args['until'] : '';
|
||||
$set = isset($this->args['set']) ? $this->args['set'] : '';
|
||||
}
|
||||
|
||||
if (!empty($this->errors)) {
|
||||
$this->errorResponse();
|
||||
}
|
||||
|
||||
// Create a PDO object
|
||||
$maxItems = 1000;
|
||||
try {
|
||||
$db = new PDO($DSN, $DB_USER, $DB_PASSWD);
|
||||
} catch (PDOException $e) {
|
||||
exit('Connection failed: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
$query = selectallQuery($metadataPrefix) . $extquery;
|
||||
$records_count = call_user_func($this->listRecordsCallback, $metadataPrefix, $from, $until, $set, true);
|
||||
|
||||
$res = $db->prepare($query, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL));
|
||||
$r = $res->execute();
|
||||
if ($r===false) {
|
||||
$this->errors[] = oai_error('noRecordsMatch');
|
||||
} else {
|
||||
$r = $res->setFetchMode(PDO::FETCH_ASSOC);
|
||||
if ($r===false) {
|
||||
exit("FetchMode is not supported");
|
||||
}
|
||||
$num_rows = rowCount($metadataPrefix, $extquery, $db);
|
||||
if ($num_rows==0) {
|
||||
$this->errors[] = oai_error('noRecordsMatch');
|
||||
}
|
||||
}
|
||||
$records = call_user_func($this->listRecordsCallback, $metadataPrefix, $from, $until, $set, false, $deliveredRecords, $maxItems);
|
||||
|
||||
if (!empty($this->errors)) {
|
||||
$this->errorResponse();
|
||||
}
|
||||
$this->outputObj = new ANDS_Response_XML($this->args);
|
||||
foreach ($records as $record) {
|
||||
|
||||
// Will we need a new ResumptionToken?
|
||||
if($this->args['verb']=='ListRecords') {
|
||||
$maxItems = MAXRECORDS;
|
||||
} elseif($this->args['verb']=='ListIdentifiers') {
|
||||
$maxItems = MAXIDS;
|
||||
} else {
|
||||
exit("Check ".__FILE__." ".__LINE__.", there is something wrong.");
|
||||
}
|
||||
$maxrec = min($num_rows - $deliveredrecords, $maxItems);
|
||||
|
||||
if ($num_rows - $deliveredrecords > $maxItems) {
|
||||
$cursor = (int)$deliveredrecords + $maxItems;
|
||||
$restoken = createResumToken($cursor, $extquery, $metadataPrefix);
|
||||
$expirationdatetime = gmstrftime('%Y-%m-%dT%TZ', time()+TOKEN_VALID);
|
||||
} elseif (isset($args['resumptionToken'])) {
|
||||
// Last delivery, return empty ResumptionToken
|
||||
$restoken = $args['resumptionToken']; // just used as an indicator
|
||||
unset($expirationdatetime);
|
||||
}
|
||||
|
||||
if (isset($this->args['resumptionToken'])) {
|
||||
$record = $res->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_ABS, $deliveredrecords);
|
||||
}
|
||||
// Record counter
|
||||
$countrec = 0;
|
||||
|
||||
// Publish a batch to $maxrec number of records
|
||||
$outputObj = new ANDS_Response_XML($this->args);
|
||||
while ($countrec++ < $maxrec) {
|
||||
$record = $res->fetch(PDO::FETCH_ASSOC);
|
||||
if ($record===false) {
|
||||
if (SHOW_QUERY_ERROR) {
|
||||
echo __FILE__.",". __LINE__."<br />";
|
||||
print_r($db->errorInfo());
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
$identifier = $oaiprefix.$record[$SQL['identifier']];
|
||||
$datestamp = formatDatestamp($record[$SQL['datestamp']]);
|
||||
$identifier = $record['identifier'];
|
||||
$datestamp = formatDatestamp($record['datestamp']);
|
||||
$setspec = $record[$SQL['set']];
|
||||
|
||||
$status_deleted = (isset($record[$SQL['deleted']]) && ($record[$SQL['deleted']] === true) &&
|
||||
($this->identifyResponse['deletedRecord'] == 'transient' || $this->identifyResponse['deletedRecord'] == 'persistent'));
|
||||
$status_deleted = (isset($record['deleted']) && ($record['deleted'] === true) &&
|
||||
(($this->identifyResponse['deletedRecord'] == 'transient') ||
|
||||
($this->identifyResponse['deletedRecord'] == 'persistent')));
|
||||
|
||||
if($this->args['verb'] == 'ListRecords') {
|
||||
$cur_record = $outputObj->create_record();
|
||||
$cur_header = $outputObj->create_header($identifier, $datestamp,$setspec,$cur_record);
|
||||
// return the metadata record itself
|
||||
$cur_record = $this->outputObj->create_record();
|
||||
$cur_header = $this->outputObj->create_header($identifier, $datestamp,$setspec,$cur_record);
|
||||
if (!$status_deleted) {
|
||||
call_user_func(array($this, "{$metadataPrefix}_create_metadata"),
|
||||
$outputObj, $cur_record, $identifier, $setspec, $db);
|
||||
$this->add_metadata($cur_record, $record);
|
||||
}
|
||||
} else { // for ListIdentifiers, only identifiers will be returned.
|
||||
$cur_header = $outputObj->create_header($identifier, $datestamp,$setspec);
|
||||
$cur_header = $this->outputObj->create_header($identifier, $datestamp,$setspec);
|
||||
}
|
||||
if ($status_deleted) {
|
||||
$cur_header->setAttribute("status","deleted");
|
||||
}
|
||||
}
|
||||
|
||||
// ResumptionToken
|
||||
// Will we need a new ResumptionToken?
|
||||
if ($records_count - $deliveredRecords > $maxItems) {
|
||||
|
||||
$deliveredRecords += $maxItems;
|
||||
$restoken = $this->createResumptionToken($deliveredRecords);
|
||||
|
||||
$expirationDatetime = gmstrftime('%Y-%m-%dT%TZ', time()+TOKEN_VALID);
|
||||
|
||||
} elseif (isset($args['resumptionToken'])) {
|
||||
// Last delivery, return empty ResumptionToken
|
||||
$restoken = null;
|
||||
$expirationDatetime = null;
|
||||
}
|
||||
|
||||
if (isset($restoken)) {
|
||||
if(isset($expirationdatetime)) {
|
||||
$outputObj->create_resumpToken($restoken,$expirationdatetime,$num_rows,$cursor);
|
||||
} else {
|
||||
$outputObj->create_resumpToken('',null,$num_rows,$deliveredrecords);
|
||||
}
|
||||
}
|
||||
return $outputObj;
|
||||
$this->outputObj->create_resumpToken($restoken,$expirationDatetime,$records_count,$deliveredRecords);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a metadata format node to an ANDS_Response_XML
|
||||
* \param &$outputObj
|
||||
* type: ANDS_Response_XML. The ANDS_Response_XML object for output.
|
||||
* \param $key
|
||||
* type string. The name of new node.
|
||||
* \param $val
|
||||
* type: array. Values accessable through keywords 'schema' and 'metadataNamespace'.
|
||||
*
|
||||
*/
|
||||
private function addMetedataFormat(&$outputObj,$key,$val) {
|
||||
$cmf = $outputObj->add2_verbNode("metadataFormat");
|
||||
$outputObj->addChild($cmf,'metadataPrefix',$key);
|
||||
$outputObj->addChild($cmf,'schema',$val['schema']);
|
||||
$outputObj->addChild($cmf,'metadataNamespace',$val['metadataNamespace']);
|
||||
}
|
||||
|
||||
private function rif_create_metadata($outputObj, $cur_record, $identifier, $setspec, $db) {
|
||||
|
||||
$metadata_node = $outputObj->create_metadata($cur_record);
|
||||
$obj_node = new ANDS_TPA($outputObj, $metadata_node, $db);
|
||||
try {
|
||||
$obj_node->create_obj_node($setspec, $identifier);
|
||||
} catch (Exception $e) {
|
||||
echo 'Caught exception: ', $e->getMessage(), " when adding $identifier\n";
|
||||
} catch (OAI2Exception $e) {
|
||||
$this->errors[] = $e;
|
||||
}
|
||||
}
|
||||
|
||||
private function oai_dc_create_metadata($outputObj, $cur_record, $identifier, $setspec, $db) {
|
||||
private function add_metadata($cur_record, $record) {
|
||||
|
||||
$sql = "SELECT dc_title, dc_creator, dc_subject, dc_description, dc_contributor, dc_publisher,
|
||||
dc_date , dc_type , dc_format , dc_identifier , dc_source , dc_language,
|
||||
dc_relation , dc_coverage , dc_rights
|
||||
FROM oai_records
|
||||
WHERE oai_set = '{$setspec}'
|
||||
AND oai_identifier = '{$identifier}'";
|
||||
$meta_node = $this->outputObj->addChild($cur_record ,"metadata");
|
||||
|
||||
$res = exec_pdo_query($db,$sql);
|
||||
$record = $res->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$meta_node = $outputObj->addChild($cur_record ,"metadata");
|
||||
|
||||
$schema_node = $outputObj->addChild($meta_node, 'oai_dc:dc');
|
||||
$schema_node->setAttribute('xmlns:oai_dc', "http://www.openarchives.org/OAI/2.0/oai_dc/");
|
||||
$schema_node->setAttribute('xmlns:dc',"http://purl.org/dc/elements/1.1/");
|
||||
$schema_node->setAttribute('xmlns:xsi',"http://www.w3.org/2001/XMLSchema-instance");
|
||||
$schema_node->setAttribute('xsi:schemaLocation',
|
||||
'http://www.openarchives.org/OAI/2.0/oai_dc/ http://www.openarchives.org/OAI/2.0/oai_dc.xsd');
|
||||
foreach ($record as $r => $v) {
|
||||
if (!empty($v)) {
|
||||
$outputObj->addChild($schema_node, str_replace('_', ':', $r), $v);
|
||||
$schema_node = $this->outputObj->addChild($meta_node, $record['metadata']['container_name']);
|
||||
foreach ($record['metadata']['container_attributes'] as $name => $value) {
|
||||
$schema_node->setAttribute($name, $value);
|
||||
}
|
||||
foreach ($record['metadata']['fields'] as $name => $value) {
|
||||
$this->outputObj->addChild($schema_node, $name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -626,7 +337,8 @@ class OAI2Server {
|
|||
* is needed.
|
||||
*/
|
||||
private function checkArgs($checkList) {
|
||||
global $METADATAFORMATS;
|
||||
|
||||
$metadataFormats = call_user_func($this->listMetadataFormatsCallback);
|
||||
|
||||
// "verb" has been checked before, no further check is needed
|
||||
$verb = $this->args["verb"];
|
||||
|
@ -638,16 +350,13 @@ class OAI2Server {
|
|||
for($i = 0; $i < count($checkList["required"]); $i++) {
|
||||
|
||||
if (isset($test_args[$checkList['required'][$i]]) == false) {
|
||||
$this->errors[] = oai_error('missingArgument', $checkList["required"][$i]);
|
||||
$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'];
|
||||
// Check if the format is supported, it has enough infor (an array), last if a handle has been defined.
|
||||
if (!array_key_exists($metadataPrefix, $METADATAFORMATS) ||
|
||||
!(is_array($METADATAFORMATS[$metadataPrefix]) ||
|
||||
!isset($METADATAFORMATS[$metadataPrefix]['myhandler']))) {
|
||||
$this->errors[] = oai_error('cannotDisseminateFormat', 'metadataPrefix', $metadataPrefix);
|
||||
if (!isset($metadataFormats[$metadataPrefix])) {
|
||||
$this->errors[] = new OAI2Exception('cannotDisseminateFormat', 'metadataPrefix', $metadataPrefix);
|
||||
}
|
||||
}
|
||||
unset($test_args[$checkList["required"][$i]]);
|
||||
|
@ -655,28 +364,61 @@ class OAI2Server {
|
|||
}
|
||||
}
|
||||
|
||||
if (!empty($this->errors)) return;
|
||||
|
||||
// check to see if there is unwanted
|
||||
foreach($test_args as $key => $val) {
|
||||
|
||||
if(!in_array($key, $checkList["ops"])) {
|
||||
$this->errors[] = oai_error('badArgument', $key, $val);
|
||||
$this->errors[] = new OAI2Exception('badArgument', $key, $val);
|
||||
}
|
||||
switch ($key) {
|
||||
case 'from':
|
||||
case 'until':
|
||||
if(!checkDateFormat($val)) {
|
||||
$this->errors[] = oai_error('badGranularity', $key, $val);
|
||||
$this->errors[] = new OAI2Exception('badGranularity', $key, $val);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'resumptionToken':
|
||||
// only check for expairation
|
||||
// only check for expiration
|
||||
if((int)$val+TOKEN_VALID < time())
|
||||
$this->errors[] = oai_error('badResumptionToken');
|
||||
$this->errors[] = new OAI2Exception('badResumptionToken');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->errors)) {
|
||||
$this->errorResponse();
|
||||
}
|
||||
}
|
||||
|
||||
private function createResumptionToken($delivered_records) {
|
||||
|
||||
list($usec, $sec) = explode(" ", microtime());
|
||||
$token = ((int)($usec*1000) + (int)($sec*1000));
|
||||
|
||||
$fp = fopen (TOKEN_PREFIX.$token, 'w');
|
||||
if($fp==false) {
|
||||
exit("Cannot write. Writer permission needs to be changed.");
|
||||
}
|
||||
fputs($fp, "$delivered_records#");
|
||||
fputs($fp, "$metadataPrefix#");
|
||||
fputs($fp, "{$this->args['from']}#");
|
||||
fputs($fp, "{$this->args['until']}#");
|
||||
fputs($fp, "{$this->args['set']}#");
|
||||
fclose($fp);
|
||||
return $token;
|
||||
}
|
||||
|
||||
private function readResumptionToken($resumptionToken) {
|
||||
$rtVal = false;
|
||||
$fp = fopen($resumptionToken, 'r');
|
||||
if ($fp != false) {
|
||||
$filetext = fgets($fp, 255);
|
||||
$textparts = explode('#', $filetext);
|
||||
fclose($fp);
|
||||
unlink($resumptionToken);
|
||||
$rtVal = array_values($textparts);
|
||||
}
|
||||
return $rtVal;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
class OAI2XML {
|
||||
|
||||
public $doc; // DOMDocument. Handle of current XML Document object
|
||||
|
||||
function __construct($request_args) {
|
||||
|
||||
$this->doc = new DOMDocument("1.0","UTF-8");
|
||||
$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);
|
||||
|
||||
$request = $this->addChild($this->doc->documentElement,"request",MY_URI);
|
||||
foreach($request_args as $key => $value) {
|
||||
$request->setAttribute($key,$value);
|
||||
}
|
||||
}
|
||||
|
||||
function display() {
|
||||
$pr = new DOMDocument();
|
||||
$pr->preserveWhiteSpace = false;
|
||||
$pr->formatOutput = true;
|
||||
$pr->loadXML($this->doc->saveXML());
|
||||
echo $pr->saveXML();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
class OAI2XMLError extends OAI2XML {
|
||||
|
||||
function __construct($request_args, $errors) {
|
||||
parent::__construct($request_args);
|
||||
|
||||
$oai_node = $this->doc->documentElement;
|
||||
foreach($errors as $e) {
|
||||
$node = $this->addChild($oai_node,"error",$e->getMessage());
|
||||
$node->setAttribute("code",$e->getCode());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* brief Configuration file of current data provider.
|
||||
*
|
||||
* This is the configuration file for the PHP OAI Data Provider.
|
||||
* The response may may be compressed for better performace:
|
||||
* - Compression : a compression encoding supported by the repository. The recommended values are those defined for the Content-Encoding header in Section 14.11 of RFC 2616 describing HTTP 1.1. A compression element should not be included for the identity encoding, which is implied.
|
||||
* The rest of settings will not normally need to be adjusted. Read source code for details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Whether to show error message for dubug.
|
||||
* For installation, testing and debuging set SHOW_QUERY_ERROR to TRUE
|
||||
* If set to TRUE, application will die and display query and database error message
|
||||
* as soon as there is a problem. Do not set this to TRUE on a production site,
|
||||
* since it will show error messages to everybody.
|
||||
* If set FALSE, will create XML-output, no matter what happens.
|
||||
*/
|
||||
// If everything is running ok, you should use this
|
||||
define('SHOW_QUERY_ERROR',FALSE);
|
||||
|
||||
/**
|
||||
* \property CONTENT_TYPE
|
||||
* The content-type the WWW-server delivers back. For debug-puposes, "text/plain"
|
||||
* is easier to view. On a production site you should use "text/xml".
|
||||
*/
|
||||
#define('CONTENT_TYPE','Content-Type: text/plain');
|
||||
// If everything is running ok, you should use this
|
||||
define('CONTENT_TYPE', 'Content-Type: text/xml');
|
||||
|
||||
// For ANDS to harvest of RIF-CS, originatingSource is plantaccelerator.org.au
|
||||
// $dataSource = "plantaccelerator.org.au";
|
||||
define('DATASOURCE','dev2.moodle.ufsc.br');
|
||||
|
||||
/** Compression methods supported. Optional (multiple). Default: null.
|
||||
*
|
||||
* Currently only gzip is supported (you need output buffering turned on,
|
||||
* and php compiled with libgz).
|
||||
* The client MUST send "Accept-Encoding: gzip" to actually receive
|
||||
*/
|
||||
// $compression = array('gzip');
|
||||
$compression = null;
|
||||
|
||||
// MUST (only one)
|
||||
// You may choose any name, but for repositories to comply with the oai
|
||||
// format it has to be unique identifiers for items records.
|
||||
// see: http://www.openarchives.org/OAI/2.0/guidelines-oai-identifier.htm
|
||||
// Basically use domainname
|
||||
// please adjust
|
||||
|
||||
// For RIF-CS, especially with ANDS, each registryObject much has a group for the ownership of data.
|
||||
// For detail please see ANDS guide on its web site. Each data provider should have only one REG_OBJ_GROUP
|
||||
// for this purpose.
|
||||
define('REG_OBJ_GROUP','Something agreed on');
|
||||
|
||||
/** Maximum mumber of the records to deliver
|
||||
* (verb is ListRecords)
|
||||
* If there are more records to deliver
|
||||
* a ResumptionToken will be generated.
|
||||
*/
|
||||
define('MAXRECORDS',10);
|
||||
|
||||
/** Maximum mumber of identifiers to deliver
|
||||
* (verb is ListIdentifiers)
|
||||
* If there are more identifiers to deliver
|
||||
* a ResumptionToken will be generated.
|
||||
*/
|
||||
define('MAXIDS',40);
|
||||
|
||||
/** After 24 hours resumptionTokens become invalid. Unit is second. */
|
||||
define('TOKEN_VALID',24*3600);
|
||||
$expirationdatetime = gmstrftime('%Y-%m-%dT%TZ', time()+TOKEN_VALID);
|
||||
/** Where token is saved and path is included */
|
||||
define('TOKEN_PREFIX','/tmp/ANDS_DBPD-');
|
||||
|
||||
// The shorthand of xml schema namespace, no need to change this
|
||||
define('XMLSCHEMA', 'http://www.w3.org/2001/XMLSchema-instance');
|
143
oaidp-util.php
143
oaidp-util.php
|
@ -37,7 +37,6 @@ function formatDatestamp($datestamp) {
|
|||
function checkDateFormat($date) {
|
||||
$date = str_replace(array("T","Z")," ",$date);
|
||||
$time_val = strtotime($date);
|
||||
if (SHOW_QUERY_ERROR) { echo "timeval: $time_val\n"; }
|
||||
if(!$time_val) return false;
|
||||
if(strstr($date,":")) {
|
||||
return date("Y-m-d H:i:s",$time_val);
|
||||
|
@ -45,145 +44,3 @@ function checkDateFormat($date) {
|
|||
return date("Y-m-d",$time_val);
|
||||
}
|
||||
}
|
||||
|
||||
/** Retrieve all defined 'setSpec' from configuraiton of $SETS.
|
||||
* It is used by ANDS_TPA::create_obj_node();
|
||||
*/
|
||||
function prepare_set_names() {
|
||||
global $SETS;
|
||||
$n = count($SETS);
|
||||
$a = array_fill(0,$n,'');
|
||||
for ($i = 0; $i <$n; $i++) {
|
||||
$a[$i] = $SETS[$i]['setSpec'];
|
||||
}
|
||||
return $a;
|
||||
}
|
||||
|
||||
// ResumToken section
|
||||
/** 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.
|
||||
* It has three parts which is separated by '#': cursor, extension of query, metadataPrefix.
|
||||
* Called by listrecords.php.
|
||||
*/
|
||||
function createResumToken($cursor, $extquery, $metadataPrefix) {
|
||||
$token = get_token();
|
||||
$fp = fopen (TOKEN_PREFIX.$token, 'w');
|
||||
if($fp==false) {
|
||||
exit("Cannot write. Writer permission needs to be changed.");
|
||||
}
|
||||
fputs($fp, "$cursor#");
|
||||
fputs($fp, "$extquery#");
|
||||
fputs($fp, "$metadataPrefix#");
|
||||
fclose($fp);
|
||||
return $token;
|
||||
}
|
||||
|
||||
/** Read a saved ResumToken */
|
||||
function readResumToken($resumptionToken) {
|
||||
$rtVal = false;
|
||||
$fp = fopen($resumptionToken, 'r');
|
||||
if ($fp!=false) {
|
||||
$filetext = fgets($fp, 255);
|
||||
$textparts = explode('#', $filetext);
|
||||
fclose($fp);
|
||||
unlink ($resumptionToken);
|
||||
$rtVal = array((int)$textparts[0], $textparts[1], $textparts[2]);
|
||||
}
|
||||
return $rtVal;
|
||||
}
|
||||
|
||||
// Here are a couple of queries which might need to be adjusted to
|
||||
// your needs. Normally, if you have correctly named the columns above,
|
||||
// this does not need to be done.
|
||||
|
||||
/** this function should generate a query which will return
|
||||
* all records
|
||||
* the useless condition id_column = id_column is just there to ease
|
||||
* further extensions to the query, please leave it as it is.
|
||||
*/
|
||||
function selectallQuery($metadPrefix = "rif", $id = ''){
|
||||
global $SQL;
|
||||
$query = "SELECT * FROM ".$SQL['table'] . " WHERE ".$SQL['metadataPrefix']." LIKE '%$metadPrefix%'";
|
||||
if ($id != '') {
|
||||
$query .= " AND ".$SQL['identifier']." ='$id'";
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
/** this function will return identifier and datestamp for all records
|
||||
* not very useful
|
||||
*/
|
||||
function idQuery($metadPrefix = "rif", $id = '') {
|
||||
global $SQL;
|
||||
|
||||
if ($SQL['set'] != '') {
|
||||
$query = 'select '.$SQL['identifier'].','.$SQL['datestamp'].','.$SQL['set'].' FROM '.$SQL['table']. " WHERE ".$SQL['metadataPrefix']." LIKE '%$metadPrefix%'";
|
||||
} else {
|
||||
$query = 'select '.$SQL['identifier'].','.$SQL['datestamp'].' FROM '.$SQL['table']. " WHERE ".$SQL['metadataPrefix']." LIKE '%$metadPrefix%'";
|
||||
}
|
||||
|
||||
if ($id != '') {
|
||||
$query .= " AND ".$SQL['identifier']." = '$id'";
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/** filter for until, appends to the end of SQL query */
|
||||
function untilQuery($until) {
|
||||
global $SQL;
|
||||
|
||||
return ' AND '.$SQL['datestamp']." <= '$until'";
|
||||
}
|
||||
|
||||
/** filter for from , appends to the end of SQL query */
|
||||
function fromQuery($from) {
|
||||
global $SQL;
|
||||
|
||||
return ' AND '.$SQL['datestamp']." >= '$from'";
|
||||
}
|
||||
|
||||
/** filter for sets, appends to the end of SQL query */
|
||||
function setQuery($set) {
|
||||
global $SQL;
|
||||
// strip off "class:" which is not saved in database
|
||||
if(strstr($set,"class:")) $set = substr($set,6);
|
||||
return ' AND '.$SQL['set']." LIKE '%$set%'";
|
||||
}
|
||||
|
||||
/** for accurately to assess how many records satisfy conditions for all DBs */
|
||||
function rowCount($metadataPrefix, $extQuery, $db) {
|
||||
global $SQL;
|
||||
$n = 0;
|
||||
$sql = "SELECT COUNT(*) FROM ".$SQL['table'] . " WHERE ".$SQL['metadataPrefix']." LIKE '%$metadataPrefix%'" . $extQuery;
|
||||
if ($res = $db->query($sql)) {
|
||||
$n = $res->fetchColumn();
|
||||
}
|
||||
return $n;
|
||||
}
|
||||
|
||||
/** A worker function for processing an error when a query was executed
|
||||
* \param $query string, original query
|
||||
* \param $e PDOException, the PDOException object
|
||||
*/
|
||||
function process_pdo_error($query, $e) {
|
||||
echo $query.' was failed\n';
|
||||
echo $e->getMessage();
|
||||
}
|
||||
|
||||
/** When query return no result, throw an Exception of Not found.
|
||||
* \param $db PDO
|
||||
* \param $query string
|
||||
* \return $res PDOStatement
|
||||
*/
|
||||
function exec_pdo_query($db, $query) {
|
||||
$res = $db->query($query);
|
||||
if ($res===false) {
|
||||
throw new Exception($query.":\nIt found nothing.\n");
|
||||
} else return $res;
|
||||
}
|
||||
|
|
134
xml_creater.php
134
xml_creater.php
|
@ -1,145 +1,15 @@
|
|||
<?php
|
||||
/**
|
||||
* \file
|
||||
* \brief functions and class related to generating XML response file.
|
||||
* functions and class related to generating XML response file.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* \code
|
||||
* $par_array = array("verb"=>"ListRecords","resumptionToken"=>"9CD1DA87F59C3E960871F4F3C9D093887C17D174");
|
||||
* // Example 1: Error response
|
||||
* $error_array[] = oai_error("badVerb","Rubish");
|
||||
* $error_array[] = oai_error("sameVerb");
|
||||
* $e = new ANDS_Error_XML($par_array,$error_array);
|
||||
* $e->display();
|
||||
*
|
||||
|
||||
* // Example 2: Normal response without error codes
|
||||
* 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();
|
||||
* \endcode
|
||||
*
|
||||
* \see http://www.openarchives.org/OAI/openarchivesprotocol.html#ErrorConditions
|
||||
*/
|
||||
/*
|
||||
http://www.openarchives.org/OAI/openarchivesprotocol.html#ErrorConditions
|
||||
|
||||
badArgument:
|
||||
The request includes illegal arguments, is missing required arguments, includes a repeated argument, or values for arguments have an illegal syntax. Applied to all verbs.
|
||||
|
||||
badResumptionToken:
|
||||
The value of the resumptionToken argument is invalid or expired. Applied to: ListIdentifiers, ListRecords, ListSets
|
||||
|
||||
badVerb:
|
||||
Value of the verb argument is not a legal OAI-PMH verb, the verb argument is missing, or the verb argument is repeated. N/A
|
||||
|
||||
cannotDisseminateFormat:
|
||||
The metadata format identified by the value given for the metadataPrefix argument is not supported by the item or by the repository. Applied to GetRecord, ListIdentifiers, ListRecords
|
||||
|
||||
idDoesNotExist:
|
||||
The value of the identifier argument is unknown or illegal in this repository. Applied to GetRecord, ListMetadataFormats
|
||||
|
||||
noRecordsMatch:
|
||||
The combination of the values of the from, until, set and metadataPrefix arguments results in an empty list. Applied to ListIdentifiers, ListRecords
|
||||
|
||||
noMetadataFormats:
|
||||
There are no metadata formats available for the specified item. Applied to ListMetadataFormats.
|
||||
|
||||
noSetHierarchy:
|
||||
The repository does not support sets. Applied to ListSets, ListIdentifiers, ListRecords
|
||||
|
||||
*/
|
||||
|
||||
/** utility funciton to mapping error codes to readable messages */
|
||||
function oai_error($code, $argument = '', $value = '') {
|
||||
|
||||
switch ($code) {
|
||||
case 'badArgument' :
|
||||
$text = "Attribute '{$argument}' is not allowed to appear in element 'request'.";
|
||||
break;
|
||||
|
||||
case 'badGranularity' :
|
||||
$text = "The value '{$value}' of attribute '{$argument}' on element 'request' is not valid with respect to its type, 'UTCdatetimeType'.";
|
||||
$code = 'badArgument';
|
||||
break;
|
||||
|
||||
case 'badResumptionToken' :
|
||||
$text = "The resumptionToken '{$value}' does not exist or has already expired.";
|
||||
break;
|
||||
|
||||
case 'badRequestMethod' :
|
||||
$text = "The request method '{$argument}' is unknown.";
|
||||
$code = 'badVerb';
|
||||
break;
|
||||
|
||||
case 'badVerb' :
|
||||
$text = "The value '{$argument}' of attribute 'verb' on element 'request' is not valid with respect to its type, 'verbType'";
|
||||
break;
|
||||
|
||||
case 'cannotDisseminateFormat' :
|
||||
$text = "The metadata format '{$value}' given by {$argument} is not supported by this repository.";
|
||||
break;
|
||||
|
||||
case 'exclusiveArgument' :
|
||||
$text = 'The usage of resumptionToken as an argument allows no other arguments.';
|
||||
$code = 'badArgument';
|
||||
break;
|
||||
|
||||
case 'idDoesNotExist' :
|
||||
$text = "The value '{$value}' of the identifier does not exist in this repository.";
|
||||
if (!is_valid_uri($value)) {
|
||||
$code = 'badArgument';
|
||||
$text .= ' Invalidated URI has been detected.';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'missingArgument' :
|
||||
$text = "The required argument '{$argument}' is missing in the request.";
|
||||
$code = 'badArgument';
|
||||
break;
|
||||
|
||||
case 'noRecordsMatch' :
|
||||
$text = 'The combination of the given values results in an empty list.';
|
||||
break;
|
||||
|
||||
case 'noMetadataFormats' :
|
||||
$text = 'There are no metadata formats available for the specified item.';
|
||||
break;
|
||||
|
||||
case 'noVerb' :
|
||||
$text = 'The request does not provide any verb.';
|
||||
$code = 'badVerb';
|
||||
break;
|
||||
|
||||
case 'noSetHierarchy' :
|
||||
$text = 'This repository does not support sets.';
|
||||
break;
|
||||
|
||||
case 'sameArgument' :
|
||||
$text = 'Do not use the same argument more than once.';
|
||||
$code = 'badArgument';
|
||||
break;
|
||||
|
||||
case 'sameVerb' :
|
||||
$text = 'Do not use verb more than once.';
|
||||
$code = 'badVerb';
|
||||
break;
|
||||
|
||||
case 'notImp' :
|
||||
$text = 'Not yet implemented.';
|
||||
$code = 'debug';
|
||||
break;
|
||||
|
||||
default:
|
||||
$text = "Unknown error: code: '{$code}', argument: '{$argument}', value: '{$value}'";
|
||||
$code = 'badArgument';
|
||||
}
|
||||
return $code."|".$text;
|
||||
}
|
||||
|
||||
/**
|
||||
* A wraper of DOMDocument for data provider
|
||||
|
|
Loading…
Reference in New Issue