diff --git a/src/api/endpoints/class-tainacan-rest-oaipmh-expose-controller.php b/src/api/endpoints/class-tainacan-rest-oaipmh-expose-controller.php index 581910ceb..dbd39e334 100644 --- a/src/api/endpoints/class-tainacan-rest-oaipmh-expose-controller.php +++ b/src/api/endpoints/class-tainacan-rest-oaipmh-expose-controller.php @@ -24,6 +24,8 @@ class REST_Oaipmh_Expose_Controller extends REST_Controller { $this->list_sets = new \Tainacan\OAIPMHExpose\OAIPMH_List_Sets(); $this->list_metadata_formats = new \Tainacan\OAIPMHExpose\OAIPMH_List_Metadata_Formats(); $this->list_records = new \Tainacan\OAIPMHExpose\OAIPMH_List_Records(); + $this->get_record = new \Tainacan\OAIPMHExpose\OAIPMH_Get_Record(); + $this->identify = new \Tainacan\OAIPMHExpose\OAIPMH_Identify(); } public function register_routes() { @@ -77,10 +79,32 @@ class REST_Oaipmh_Expose_Controller extends REST_Controller { $this->list_records->list_records($request); break; + case 'GetRecord': + + if ( !isset($request['metadataPrefix']) ) { + $this->get_record->config(); + $this->get_record->errors[] = $this->get_record->oai_error('missingArgument','metadataPrefix'); + $this->get_record->oai_exit( $request, $this->get_record->errors ); + } + + if( !isset($request['identifier']) ){ + $this->get_record->config(); + $this->get_record->errors[] = $this->get_record->oai_error('missingArgument','identifier'); + $this->get_record->oai_exit( $request, $this->get_record->errors ); + } + + $this->get_record->get_record( $request ); + + break; + case 'ListMetadataFormats': $this->list_metadata_formats->list_metadata_formats($request); break; + case 'Identify': + $this->identify->identify($request); + break; + default: $this->controller_oai->config(); $this->controller_oai->errors[] = $this->controller_oai->oai_error('noVerb'); diff --git a/src/oaipmh-expose/class-tainacan-oaipmh-expose.php b/src/oaipmh-expose/class-tainacan-oaipmh-expose.php index 32885d4d6..93a9c00f6 100644 --- a/src/oaipmh-expose/class-tainacan-oaipmh-expose.php +++ b/src/oaipmh-expose/class-tainacan-oaipmh-expose.php @@ -26,21 +26,19 @@ class OAIPMH_Expose { var $xmlescaped; var $text; var $code; + /** - * @signature - config - * @return begin the class - * @author: Eduardo + * */ public function config() { $this->CONTENT_TYPE = 'Content-Type: text/xml'; $this->identifyResponse["repositoryName"] = get_bloginfo( 'name'); $this->identifyResponse['protocolVersion'] = '2.0'; - $this->identifyResponse['baseURL'] = get_bloginfo( 'url').'/oai/socialdb-oai/'; + $this->identifyResponse['baseURL'] = get_bloginfo( 'url').'wp-json/tainacan/v2/oai/'; $this->identifyResponse["earliestDatestamp"] = '2006-06-01'; - $this->identifyResponse["deletedRecord"] = 'no'; + $this->identifyResponse["deletedRecord"] = 'transient'; $this->identifyResponse["granularity"] = 'YYYY-MM-DDThh:mm:ssZ'; - //$this->deletedRecord = $identifyResponse["deletedRecord"]; // a shorthand for checking the configuration of Deleted Records if (strcmp($this->identifyResponse["granularity"], 'YYYY-MM-DDThh:mm:ssZ') == 0) { $this->identifyResponse["earliestDatestamp"] = $this->identifyResponse["earliestDatestamp"] . 'T00:00:00Z'; } @@ -82,6 +80,7 @@ class OAIPMH_Expose { /** After 24 hours resumptionTokens become invalid. Unit is second. */ define('TOKEN_VALID', 24 * 3600); define('MY_URI', get_bloginfo( 'url' )); + $this->expirationdatetime = gmstrftime('%Y-%m-%dT%TZ', time() + TOKEN_VALID); /** Where token is saved and path is included */ @@ -110,44 +109,6 @@ class OAIPMH_Expose { $this->xmlescaped = false; } - /** Dump information of a varible for debugging, - * only works when SHOW_QUERY_ERROR is true. - * \param $var_name Type: string Name of variable is being debugded - * \param $var Type: mix Any type of varibles used in PHP - * \see SHOW_QUERY_ERROR in oaidp-config.php - */ - function debug_var_dump($var_name, $var) { - if (SHOW_QUERY_ERROR) { - echo "Dumping \${$var_name}: \n"; - var_dump($var) . "\n"; - } - } - - /** Prints human-readable information about a variable for debugging, - * only works when SHOW_QUERY_ERROR is true. - * \param $var_name Type: string Name of variable is being debugded - * \param $var Type: mix Any type of varibles used in PHP - * \see SHOW_QUERY_ERROR in oaidp-config.php - */ - function debug_print_r($var_name, $var) { - if (SHOW_QUERY_ERROR) { - echo "Printing \${$var_name}: \n"; - print_r($var) . "\n"; - } - } - - /** Prints a message for debugging, - * only works when SHOW_QUERY_ERROR is true. - * PHP function print_r can be used to construct message with return parameter sets to true. - * \param $msg Type: string Message needs to be shown - * \see SHOW_QUERY_ERROR in oaidp-config.php - */ - function debug_message($msg) { - if (!SHOW_QUERY_ERROR) - return; - echo $msg, "\n"; - } - /** Check if provided correct arguments for a request. * * Only number of parameters is checked. @@ -254,6 +215,7 @@ class OAIPMH_Expose { return date("Y-m-d", $time_val); } } + /** Retrieve all defined 'setSpec' from configuraiton of $SETS. * It is used by ANDS_TPA::create_obj_node(); */ @@ -266,6 +228,7 @@ class OAIPMH_Expose { } return $a; } + /** Finish a request when there is an error: send back errors. */ function oai_exit($args,$errors) { header($this->CONTENT_TYPE); @@ -332,43 +295,6 @@ class OAIPMH_Expose { return $rtVal; } - /** - * function has_mapping($collection_id) - * @param int $collection_id - * @return boolean - * @author: Eduardo Humberto - */ - public function has_mapping($collection_id) { - - } - - /** - * function get_mapping_harvested($collection_id) - * @param int $collection_id - * @return boolean - * @author: Eduardo Humberto - */ - public function get_mapping_harvested($collection_id) { - - } - - /** - * function list_collections_mapped() - * @author: Eduardo Humberto - */ - public function get_harvesting_mappings() { - - } - - /** - * function list_collections_mapped() - * @description metodo em retornar apenas as colecoes mapeadas - * @author: Eduardo Humberto - */ - public function list_collections_mapped() { - - } - /** utility funciton to mapping error codes to readable messages */ function oai_error($code, $argument = '', $value = '') { switch ($code) { diff --git a/src/oaipmh-expose/class-tainacan-oaipmh-get-record.php b/src/oaipmh-expose/class-tainacan-oaipmh-get-record.php new file mode 100644 index 000000000..1139cc715 --- /dev/null +++ b/src/oaipmh-expose/class-tainacan-oaipmh-get-record.php @@ -0,0 +1,233 @@ +collection_repository = Repositories\Collections::get_instance(); + $this->item_repository = Repositories\Items::get_instance(); + } + + /** + * @param $params + * @return bool|Entities\Item + * @throws \Exception + */ + public function get_item( $params ) { + + $id = str_replace('oai:'.$this->repositoryIdentifier.':','', $params['identifier']); + $item = new Entities\Item( $id ); + + if( !$item->get_id() ){ + return false; + } + + $item->collection = $item->get_collection(); + return $item; + } + + + /** + * @param $data + * @throws \Exception + */ + public function get_record( $data ) { + session_write_close(); + + $this->config(); + $this->initiate_variables( $data ); + + $item = $this->get_item( $data ); + + if( $item ){ + $formats = $this->get_metadata_formats(); + $prefix = ( $data['metadataPrefix'] === 'oai_dc') ? 'dublin-core' : $data['metadataPrefix']; + + if( empty($formats) || !in_array($prefix, $formats) ){ + $this->errors[] = $this->oai_error('cannotDisseminateFormat'); + $this->oai_exit($data,$this->errors); + } + }else{ + $this->errors[] = $this->oai_error('idDoesNotExist'); + $this->oai_exit( $data, $this->errors); + } + + $this->xml_creater = new Xml_Response($data); + + $collection = $item->collection; + $identifier = 'oai:'.$this->repositoryIdentifier.':'. $item->get_id(); + $datestamp = $this->formatDatestamp($item->get_creation_date()); + $setspec = $collection->get_id(); + $cur_record = $this->xml_creater->create_record(); + + $this->xml_creater->create_header($identifier, $datestamp, $setspec,$cur_record, ( $item->get_status() === 'trash' ) ? true : false ); + + if( $item->get_status() !== 'trash' ){ + $this->working_node = $this->xml_creater->create_metadata($cur_record); + $this->create_metadata_node( $item, $collection, $cur_record); + } + + ob_start('ob_gzhandler'); + header($this->CONTENT_TYPE); + + if (isset($this->xml_creater)) { + $this->xml_creater->display(); + } else { + exit("There is a bug in codes"); + } + + ob_end_flush(); + } + + /** + * Gets the current mapper object, if one was chosen by the user, false Otherwise + */ + public function get_current_mapper() { + $prefix = ($this->metadataPrefix === 'oai_dc') ? 'dublin-core' : $this->metadataPrefix; + + return \Tainacan\Mappers_Handler::get_instance()->get_mapper($prefix); + } + + /** + * @signature - create_metadata_node + * @param \Tainacan\Entities\Item $item + * @param wp_post $collection O objeto da colecao + * @return Adciona no noh os valores necessarios + * @description - Metodo responsavel realizar o povoamento no noh metadata + * @author: Eduardo + */ + protected function create_metadata_node( $item, $collection,$record_node = null) { + $this->working_node = $this->xml_creater->addChild($this->working_node, 'oai_dc:dc'); + $this->working_node->setAttribute('xmlns:oai_dc', "http://www.openarchives.org/OAI/2.0/oai_dc/"); + $this->working_node->setAttribute('xmlns:dc', "http://purl.org/dc/elements/1.1/"); + $this->working_node->setAttribute('xmlns:xsi', "http://www.w3.org/2001/XMLSchema-instance"); + $this->working_node->setAttribute('xsi:schemaLocation', 'http://www.openarchives.org/OAI/2.0/oai_dc/ http://www.openarchives.org/OAI/2.0/oai_dc.xsd'); + $maps = $this->map_item_metadata($item); + + try{ + if ($maps) { + foreach ($maps as $key => $val) { + $this->xml_creater->addChild($this->working_node, $key, html_entity_decode($val)); + } + } + }catch(Exception $e){ + var_dump($e,$this->working_node,'dc:' . $key); + } + } + + /** + * Gets an Item as input and return an array of ItemMetadataObjects + * If a mapper is selected, the array keys will be the slugs of the metadata + * declared by the mapper, in the same order. + * Note that if one of the metadata is not mapped, this array item will be null + */ + private function map_item_metadata(\Tainacan\Entities\Item $item) { + $prefix = ($this->metadataPrefix === 'oai_dc') ? 'dublin-core' : $this->metadataPrefix; + $mapper = $this->get_current_mapper(); + $metadata = $item->get_metadata(); + if (!$mapper) { + return $metadata; + } + $pre = []; + foreach ($metadata as $item_metadata) { + $metadatum = $item_metadata->get_metadatum(); + $meta_mappings = $metadatum->get_exposer_mapping(); + if ( array_key_exists($prefix, $meta_mappings) ) { + + $pre[ $meta_mappings[$prefix] ] = $item_metadata; + } + } + + // reorder + $return = []; + foreach ( $mapper->metadata as $meta_slug => $meta ) { + if ( array_key_exists($meta_slug, $pre) ) { + $return[$meta_slug] = $pre[$meta_slug]; + } else { + $return[$meta_slug] = null; + } + } + + return $return; + + } + + /** + * @param $data + */ + public function initiate_variables( $data ) { + + if ( isset($data['resumptionToken']) ) { + + if ( !file_exists(TOKEN_PREFIX . $data['resumptionToken']) ) { + $this->errors[] = $this->oai_error('badResumptionToken', '', $data['resumptionToken']); + } else { + $readings = $this->readResumToken(TOKEN_PREFIX . $data['resumptionToken']); + if ($readings == false) { + $this->errors[] = $this->oai_error('badResumptionToken', '', $data['resumptionToken']); + } else { + list($this->deliveredrecords, $this->from, $this->until, $sets, $this->metadataPrefix) = $readings; + if($sets=='-'){ + $this->sets = array(); + }else{ + $this->sets = explode(',', $sets); + } + } + } + + } else { + $this->deliveredrecords = 0; + + if (isset($data['set'])) { + if (is_array($data['set'])) { + $this->sets = $data['set']; + } else { + $this->sets = array($data['set']); + } + } else { + $this->sets = array(); + } + + if (isset($data['from'])) { + $this->from = $data['from']; + } else { + $this->from = '-'; + } + + if (isset($data['until'])) { + $this->until = $data['until']; + } else { + $this->until = '-'; + } + + $this->metadataPrefix = $data['metadataPrefix']; + } + + if(is_array($this->errors)&&count($this->errors)>0){ + $this->oai_exit($data,$this->errors); + } + } +} \ No newline at end of file diff --git a/src/oaipmh-expose/class-tainacan-oaipmh-identify.php b/src/oaipmh-expose/class-tainacan-oaipmh-identify.php new file mode 100644 index 000000000..3624fbb48 --- /dev/null +++ b/src/oaipmh-expose/class-tainacan-oaipmh-identify.php @@ -0,0 +1,42 @@ +config(); + $this->xml_creater = new Xml_Response($data); + $this->xml_creater->add2_verbNode('repositoryName',$this->identifyResponse["repositoryName"]); + $this->xml_creater->add2_verbNode('baseURL',$this->identifyResponse["baseURL"]); + $this->xml_creater->add2_verbNode('protocolVersion',$this->identifyResponse["protocolVersion"]); + $this->xml_creater->add2_verbNode('earliestDatestamp',$this->identifyResponse["earliestDatestamp"]); + $this->xml_creater->add2_verbNode('deletedRecord',$this->identifyResponse["deletedRecord"]); + $this->xml_creater->add2_verbNode('granularity',$this->identifyResponse["granularity"]); + $this->xml_creater->add2_verbNode('adminEmail',$this->adminEmail); + + $description_node = $this->xml_creater->add2_verbNode('description'); + $this->working_node = $this->xml_creater->addChild($description_node, 'oai-identifier'); + $this->working_node->setAttribute('xmlns', "http://www.openarchives.org/OAI/2.0/oai-identifier"); + $this->working_node->setAttribute('xmlns:xsi', "http://www.w3.org/2001/XMLSchema-instance"); + $this->working_node->setAttribute('xsi:schemaLocation', 'http://www.openarchives.org/OAI/2.0/oai-identifier http://www.openarchives.org/OAI/2.0/oai-identifier.xsd'); + $this->xml_creater->addChild($this->working_node, 'scheme', 'oai'); + $this->xml_creater->addChild($this->working_node, 'repositoryIdentifier', $this->repositoryIdentifier); + $this->xml_creater->addChild($this->working_node, 'delimiter', ':'); + $this->xml_creater->addChild($this->working_node, 'sampleIdentifier', 'oai:'.$this->repositoryIdentifier.':1'); + + header($this->CONTENT_TYPE); + if (isset($this->xml_creater)) { + $this->xml_creater->display(); + } else { + exit("There is a bug in codes"); + } + } + +} \ No newline at end of file diff --git a/src/oaipmh-expose/class-tainacan-oaipmh-list-records.php b/src/oaipmh-expose/class-tainacan-oaipmh-list-records.php index f42b06c29..bf8215a8b 100644 --- a/src/oaipmh-expose/class-tainacan-oaipmh-list-records.php +++ b/src/oaipmh-expose/class-tainacan-oaipmh-list-records.php @@ -65,7 +65,8 @@ class OAIPMH_List_Records extends OAIPMH_Expose { 'posts_per_page' => $this->MAXRECORDS, 'paged' => $this->deliveredrecords == 0 ? 1 : ( $this->deliveredrecords / 100 ) + 1, 'order' => 'DESC', - 'orderby' => 'ID' + 'orderby' => 'ID', + 'post_status' => array( 'trash', 'publish' ) ]; if( !empty($this->sets) ){ @@ -127,9 +128,13 @@ class OAIPMH_List_Records extends OAIPMH_Expose { $datestamp = $this->formatDatestamp($item->get_creation_date()); $setspec = $collection->get_id(); $cur_record = $this->xml_creater->create_record(); - $cur_header = $this->xml_creater->create_header($identifier, $datestamp, $setspec,$cur_record); - $this->working_node = $this->xml_creater->create_metadata($cur_record); - $this->create_metadata_node( $item, $collection, $cur_record); + $cur_header = $this->xml_creater->create_header($identifier, $datestamp, $setspec,$cur_record, ( $item->get_status() === 'trash' ) ? true : false ); + + if( $item->get_status() !== 'trash' ){ + $this->working_node = $this->xml_creater->create_metadata($cur_record); + $this->create_metadata_node( $item, $collection, $cur_record); + } + } //resumptionToken diff --git a/src/oaipmh-expose/class-tainacan-xml-response.php b/src/oaipmh-expose/class-tainacan-xml-response.php index 52934684e..42a19fecd 100644 --- a/src/oaipmh-expose/class-tainacan-xml-response.php +++ b/src/oaipmh-expose/class-tainacan-xml-response.php @@ -45,12 +45,17 @@ class Xml_Response extends Xml_Create { * In normal cases, $add_to_node is the \ 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) { + public function create_header($identifier, $timestamp, $ands_class, $add_to_node = null, $is_deleted = false) { if (is_null($add_to_node)) { $header_node = $this->add2_verbNode("header"); } else { $header_node = $this->addChild($add_to_node, "header"); } + + if( $is_deleted ){ + $header_node->setAttribute('status', "deleted"); + } + $this->addChild($header_node, "identifier", $identifier); $this->addChild($header_node, "datestamp", $timestamp); if (is_array($ands_class)) {