2011-03-09 16:36:27 +01:00
< ? php
2019-03-14 15:42:34 +01:00
namespace Kitodo\Dlf\Plugins ;
2011-03-09 16:36:27 +01:00
/**
2016-09-23 12:24:46 +02:00
* ( c ) Kitodo . Key to digital objects e . V . < contact @ kitodo . org >
*
* This file is part of the Kitodo and TYPO3 projects .
*
* @ license GNU General Public License version 3 or later .
* For the full copyright and license information , please read the
* LICENSE . txt file that was distributed with this source code .
2011-03-09 16:36:27 +01:00
*/
2019-03-13 08:29:51 +01:00
use Kitodo\Dlf\Common\DocumentList ;
use Kitodo\Dlf\Common\Helper ;
use Kitodo\Dlf\Common\Solr ;
2011-03-09 16:36:27 +01:00
/**
2019-03-14 15:42:34 +01:00
* Plugin 'OAI-PMH Interface' for the 'dlf' extension .
2011-03-09 16:36:27 +01:00
*
* @ author Sebastian Meyer < sebastian . meyer @ slub - dresden . de >
* @ package TYPO3
2019-03-14 15:42:34 +01:00
* @ subpackage dlf
2011-03-09 16:36:27 +01:00
* @ access public
*/
2019-03-14 15:42:34 +01:00
class OaiPmh extends \Kitodo\Dlf\Common\AbstractPlugin {
2011-03-09 16:36:27 +01:00
2019-03-14 15:42:34 +01:00
public $scriptRelPath = 'Classes/Plugins/OaiPmh.php' ;
2018-01-09 15:17:30 +01:00
/**
* Did an error occur ?
*
* @ var boolean
* @ access protected
*/
protected $error = FALSE ;
/**
* This holds the OAI DOM object
*
2019-03-13 17:55:50 +01:00
* @ var \DOMDocument
2018-01-09 15:17:30 +01:00
* @ access protected
*/
protected $oai ;
/**
* This holds the configuration for all supported metadata prefixes
*
* @ var array
* @ access protected
*/
protected $formats = array (
'oai_dc' => array (
'schema' => 'http://www.openarchives.org/OAI/2.0/oai_dc.xsd' ,
'namespace' => 'http://www.openarchives.org/OAI/2.0/oai_dc/' ,
'requiredFields' => array ( 'record_id' ),
),
'epicur' => array (
'schema' => 'http://www.persistent-identifier.de/xepicur/version1.0/xepicur.xsd' ,
'namespace' => 'urn:nbn:de:1111-2004033116' ,
'requiredFields' => array ( 'purl' , 'urn' ),
),
'mets' => array (
'schema' => 'http://www.loc.gov/standards/mets/version17/mets.v1-7.xsd' ,
'namespace' => 'http://www.loc.gov/METS/' ,
'requiredFields' => array ( 'location' ),
)
);
/**
* Delete expired resumption tokens
*
* @ access protected
*
* @ return void
*/
protected function deleteExpiredTokens () {
// Delete expired resumption tokens.
$result = $GLOBALS [ 'TYPO3_DB' ] -> exec_DELETEquery (
'tx_dlf_tokens' ,
'tx_dlf_tokens.ident="oai" AND tx_dlf_tokens.tstamp<' . intval ( $GLOBALS [ 'EXEC_TIME' ] - $this -> conf [ 'expired' ])
);
if ( $GLOBALS [ 'TYPO3_DB' ] -> sql_affected_rows () === - 1 ) {
// Deletion failed.
2019-03-14 15:42:34 +01:00
$this -> devLog ( '[\Kitodo\Dlf\Plugins\OaiPmh->deleteExpiredTokens()] Could not delete expired resumption tokens' , SYSLOG_SEVERITY_WARNING );
2018-01-09 15:17:30 +01:00
}
}
/**
* Process error
*
* @ access protected
*
* @ param string $type : Error type
*
2019-03-13 17:55:50 +01:00
* @ return \DOMElement XML node to add to the OAI response
2018-01-09 15:17:30 +01:00
*/
protected function error ( $type ) {
$this -> error = TRUE ;
$error = $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'error' , htmlspecialchars ( $this -> pi_getLL ( $type , $type , FALSE ), ENT_NOQUOTES , 'UTF-8' ));
$error -> setAttribute ( 'code' , $type );
return $error ;
}
/**
* Load URL parameters
*
* @ access protected
*
* @ return void
*/
protected function getUrlParams () {
$allowedParams = array (
'verb' ,
'identifier' ,
'metadataPrefix' ,
'from' ,
'until' ,
'set' ,
'resumptionToken'
);
// Clear plugin variables.
$this -> piVars = array ();
// Set only allowed parameters.
foreach ( $allowedParams as $param ) {
if ( \TYPO3\CMS\Core\Utility\GeneralUtility :: _GP ( $param )) {
$this -> piVars [ $param ] = \TYPO3\CMS\Core\Utility\GeneralUtility :: _GP ( $param );
}
}
}
/**
* Get unqualified Dublin Core data .
* @ see http :// www . openarchives . org / OAI / openarchivesprotocol . html #dublincore
*
* @ access protected
*
* @ param array $metadata : The metadata array
*
2019-03-13 17:55:50 +01:00
* @ return \DOMElement XML node to add to the OAI response
2018-01-09 15:17:30 +01:00
*/
protected function getDcData ( array $metadata ) {
$oai_dc = $this -> oai -> createElementNS ( $this -> formats [ 'oai_dc' ][ 'namespace' ], 'oai_dc:dc' );
$oai_dc -> setAttributeNS ( 'http://www.w3.org/2000/xmlns/' , 'xmlns:dc' , 'http://purl.org/dc/elements/1.1/' );
$oai_dc -> setAttributeNS ( 'http://www.w3.org/2000/xmlns/' , 'xmlns:xsi' , 'http://www.w3.org/2001/XMLSchema-instance' );
$oai_dc -> setAttributeNS ( 'http://www.w3.org/2001/XMLSchema-instance' , 'xsi:schemaLocation' , $this -> formats [ 'oai_dc' ][ 'namespace' ] . ' ' . $this -> formats [ 'oai_dc' ][ 'schema' ]);
$oai_dc -> appendChild ( $this -> oai -> createElementNS ( 'http://purl.org/dc/elements/1.1/' , 'dc:identifier' , htmlspecialchars ( $metadata [ 'record_id' ], ENT_NOQUOTES , 'UTF-8' )));
if ( ! empty ( $metadata [ 'purl' ])) {
$oai_dc -> appendChild ( $this -> oai -> createElementNS ( 'http://purl.org/dc/elements/1.1/' , 'dc:identifier' , htmlspecialchars ( $metadata [ 'purl' ], ENT_NOQUOTES , 'UTF-8' )));
}
if ( ! empty ( $metadata [ 'urn' ])) {
$oai_dc -> appendChild ( $this -> oai -> createElementNS ( 'http://purl.org/dc/elements/1.1/' , 'dc:identifier' , htmlspecialchars ( $metadata [ 'urn' ], ENT_NOQUOTES , 'UTF-8' )));
}
if ( ! empty ( $metadata [ 'title' ])) {
$oai_dc -> appendChild ( $this -> oai -> createElementNS ( 'http://purl.org/dc/elements/1.1/' , 'dc:title' , htmlspecialchars ( $metadata [ 'title' ], ENT_NOQUOTES , 'UTF-8' )));
}
if ( ! empty ( $metadata [ 'author' ])) {
$oai_dc -> appendChild ( $this -> oai -> createElementNS ( 'http://purl.org/dc/elements/1.1/' , 'dc:creator' , htmlspecialchars ( $metadata [ 'author' ], ENT_NOQUOTES , 'UTF-8' )));
}
if ( ! empty ( $metadata [ 'year' ])) {
$oai_dc -> appendChild ( $this -> oai -> createElementNS ( 'http://purl.org/dc/elements/1.1/' , 'dc:date' , htmlspecialchars ( $metadata [ 'year' ], ENT_NOQUOTES , 'UTF-8' )));
}
2012-08-14 14:12:17 +02:00
2018-01-09 15:17:30 +01:00
if ( ! empty ( $metadata [ 'place' ])) {
$oai_dc -> appendChild ( $this -> oai -> createElementNS ( 'http://purl.org/dc/elements/1.1/' , 'dc:coverage' , htmlspecialchars ( $metadata [ 'place' ], ENT_NOQUOTES , 'UTF-8' )));
}
2012-08-14 14:12:17 +02:00
2018-01-09 15:17:30 +01:00
$oai_dc -> appendChild ( $this -> oai -> createElementNS ( 'http://purl.org/dc/elements/1.1/' , 'dc:format' , 'application/mets+xml' ));
$oai_dc -> appendChild ( $this -> oai -> createElementNS ( 'http://purl.org/dc/elements/1.1/' , 'dc:type' , 'Text' ));
2011-03-09 16:36:27 +01:00
2018-01-09 15:17:30 +01:00
if ( ! empty ( $metadata [ 'partof' ])) {
$result = $GLOBALS [ 'TYPO3_DB' ] -> exec_SELECTquery (
'tx_dlf_documents.record_id' ,
'tx_dlf_documents' ,
2019-03-13 08:29:51 +01:00
'tx_dlf_documents.uid=' . intval ( $metadata [ 'partof' ]) . Helper :: whereClause ( 'tx_dlf_documents' ),
2018-01-09 15:17:30 +01:00
'' ,
'' ,
'1'
);
2011-03-09 16:36:27 +01:00
2018-01-09 15:17:30 +01:00
if ( $GLOBALS [ 'TYPO3_DB' ] -> sql_num_rows ( $result )) {
$partof = $GLOBALS [ 'TYPO3_DB' ] -> sql_fetch_assoc ( $result );
2011-03-09 16:36:27 +01:00
2018-01-09 15:17:30 +01:00
$oai_dc -> appendChild ( $this -> oai -> createElementNS ( 'http://purl.org/dc/elements/1.1/' , 'dc:relation' , htmlspecialchars ( $partof [ 'record_id' ], ENT_NOQUOTES , 'UTF-8' )));
}
}
2011-03-09 16:36:27 +01:00
2018-01-09 15:17:30 +01:00
return $oai_dc ;
}
2011-03-09 16:36:27 +01:00
2018-01-09 15:17:30 +01:00
/**
* Get epicur data .
* @ see http :// www . persistent - identifier . de / ? link = 210
*
* @ access protected
*
* @ param array $metadata : The metadata array
*
2019-03-13 17:55:50 +01:00
* @ return \DOMElement XML node to add to the OAI response
2018-01-09 15:17:30 +01:00
*/
protected function getEpicurData ( array $metadata ) {
2011-03-09 16:36:27 +01:00
2018-01-09 15:17:30 +01:00
// Define all XML elements with or without qualified namespace.
if ( empty ( $this -> conf [ 'unqualified_epicur' ])) {
$epicur = $this -> oai -> createElementNS ( $this -> formats [ 'epicur' ][ 'namespace' ], 'epicur:epicur' );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$admin = $this -> oai -> createElementNS ( $this -> formats [ 'epicur' ][ 'namespace' ], 'epicur:administrative_data' );
2011-03-09 16:36:27 +01:00
2018-01-09 15:17:30 +01:00
$delivery = $this -> oai -> createElementNS ( $this -> formats [ 'epicur' ][ 'namespace' ], 'epicur:delivery' );
2011-03-09 16:36:27 +01:00
2018-01-09 15:17:30 +01:00
$update = $this -> oai -> createElementNS ( $this -> formats [ 'epicur' ][ 'namespace' ], 'epicur:update_status' );
2011-03-09 16:36:27 +01:00
2018-01-09 15:17:30 +01:00
$transfer = $this -> oai -> createElementNS ( $this -> formats [ 'epicur' ][ 'namespace' ], 'epicur:transfer' );
2011-03-09 16:36:27 +01:00
2018-01-09 15:17:30 +01:00
$format = $this -> oai -> createElementNS ( $this -> formats [ 'epicur' ][ 'namespace' ], 'epicur:format' , 'text/html' );
2011-03-09 16:36:27 +01:00
2018-01-09 15:17:30 +01:00
$record = $this -> oai -> createElementNS ( $this -> formats [ 'epicur' ][ 'namespace' ], 'epicur:record' );
2011-03-09 16:36:27 +01:00
2018-01-09 15:17:30 +01:00
$identifier = $this -> oai -> createElementNS ( $this -> formats [ 'epicur' ][ 'namespace' ], 'epicur:identifier' , htmlspecialchars ( $metadata [ 'urn' ], ENT_NOQUOTES , 'UTF-8' ));
2011-03-09 16:36:27 +01:00
2018-01-09 15:17:30 +01:00
$resource = $this -> oai -> createElementNS ( $this -> formats [ 'epicur' ][ 'namespace' ], 'epicur:resource' );
2011-03-09 16:36:27 +01:00
2018-01-09 15:17:30 +01:00
$ident = $this -> oai -> createElementNS ( $this -> formats [ 'epicur' ][ 'namespace' ], 'epicur:identifier' , htmlspecialchars ( $metadata [ 'purl' ], ENT_NOQUOTES , 'UTF-8' ));
2011-03-09 16:36:27 +01:00
2018-01-09 15:17:30 +01:00
} else {
$epicur = $this -> oai -> createElement ( 'epicur' );
$epicur -> setAttribute ( 'xmlns' , $this -> formats [ 'epicur' ][ 'namespace' ]);
2011-03-09 16:36:27 +01:00
2018-01-09 15:17:30 +01:00
$admin = $this -> oai -> createElement ( 'administrative_data' );
2011-03-09 16:36:27 +01:00
2018-01-09 15:17:30 +01:00
$delivery = $this -> oai -> createElement ( 'delivery' );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$update = $this -> oai -> createElement ( 'update_status' );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$transfer = $this -> oai -> createElement ( 'transfer' );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$format = $this -> oai -> createElement ( 'format' , 'text/html' );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$record = $this -> oai -> createElement ( 'record' );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$identifier = $this -> oai -> createElement ( 'identifier' , htmlspecialchars ( $metadata [ 'urn' ], ENT_NOQUOTES , 'UTF-8' ));
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$resource = $this -> oai -> createElement ( 'resource' );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$ident = $this -> oai -> createElement ( 'identifier' , htmlspecialchars ( $metadata [ 'purl' ], ENT_NOQUOTES , 'UTF-8' ));
}
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
// Add attributes and build XML tree.
$epicur -> setAttributeNS ( 'http://www.w3.org/2000/xmlns/' , 'xmlns:xsi' , 'http://www.w3.org/2001/XMLSchema-instance' );
$epicur -> setAttributeNS ( 'http://www.w3.org/2001/XMLSchema-instance' , 'xsi:schemaLocation' , $this -> formats [ 'epicur' ][ 'namespace' ] . ' ' . $this -> formats [ 'epicur' ][ 'schema' ]);
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
// Do we update an URN or register a new one?
if ( $metadata [ 'tstamp' ] == $metadata [ 'crdate' ]) {
$update -> setAttribute ( 'type' , 'urn_new' );
} else {
$update -> setAttribute ( 'type' , 'url_update_general' );
}
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$delivery -> appendChild ( $update );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$transfer -> setAttribute ( 'type' , 'http' );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$delivery -> appendChild ( $transfer );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$admin -> appendChild ( $delivery );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$epicur -> appendChild ( $admin );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$identifier -> setAttribute ( 'scheme' , 'urn:nbn:de' );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$record -> appendChild ( $identifier );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$ident -> setAttribute ( 'scheme' , 'url' );
$ident -> setAttribute ( 'type' , 'frontpage' );
$ident -> setAttribute ( 'role' , 'primary' );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$resource -> appendChild ( $ident );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$format -> setAttribute ( 'scheme' , 'imt' );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$resource -> appendChild ( $format );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$record -> appendChild ( $resource );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$epicur -> appendChild ( $record );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
return $epicur ;
}
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
/**
* Get METS data .
* @ see http :// www . loc . gov / standards / mets / docs / mets . v1 - 7. html
*
* @ access protected
*
* @ param array $metadata : The metadata array
*
2019-03-13 17:55:50 +01:00
* @ return \DOMElement XML node to add to the OAI response
2018-01-09 15:17:30 +01:00
*/
protected function getMetsData ( array $metadata ) {
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$mets = NULL ;
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
// Load METS file.
2019-03-13 17:55:50 +01:00
$xml = new \DOMDocument ();
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
if ( $xml -> load ( $metadata [ 'location' ])) {
// Get root element.
$root = $xml -> getElementsByTagNameNS ( $this -> formats [ 'mets' ][ 'namespace' ], 'mets' );
2011-09-13 17:49:30 +02:00
2019-03-13 17:55:50 +01:00
if ( $root -> item ( 0 ) instanceof \DOMNode ) {
// Import node into \DOMDocument.
2018-01-09 15:17:30 +01:00
$mets = $this -> oai -> importNode ( $root -> item ( 0 ), TRUE );
} else {
2019-03-14 15:42:34 +01:00
$this -> devLog ( '[\Kitodo\Dlf\Plugins\OaiPmh->getMetsData([data])] No METS part found in document with location "' . $metadata [ 'location' ] . '"' , SYSLOG_SEVERITY_ERROR , $metadata );
2018-01-09 15:17:30 +01:00
}
} else {
2019-03-14 15:42:34 +01:00
$this -> devLog ( '[\Kitodo\Dlf\Plugins\OaiPmh->getMetsData([data])] Could not load XML file from "' . $metadata [ 'location' ] . '"' , SYSLOG_SEVERITY_ERROR , $metadata );
2018-01-09 15:17:30 +01:00
}
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
if ( $mets === NULL ) {
$mets = $this -> oai -> createElementNS ( 'http://kitodo.org/' , 'kitodo:error' , htmlspecialchars ( $this -> pi_getLL ( 'error' , 'Error!' , FALSE ), ENT_NOQUOTES , 'UTF-8' ));
}
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
return $mets ;
}
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
/**
* The main method of the PlugIn
*
* @ access public
*
* @ param string $content : The PlugIn content
* @ param array $conf : The PlugIn configuration
*
* @ return void
*/
public function main ( $content , $conf ) {
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
// Initialize plugin.
$this -> init ( $conf );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
// Turn cache off.
$this -> setCache ( FALSE );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
// Get GET and POST variables.
$this -> getUrlParams ();
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
// Delete expired resumption tokens.
$this -> deleteExpiredTokens ();
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
// Create XML document.
2019-03-13 17:55:50 +01:00
$this -> oai = new \DOMDocument ( '1.0' , 'UTF-8' );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
// Add processing instruction (aka XSL stylesheet).
if ( ! empty ( $this -> conf [ 'stylesheet' ])) {
// Resolve "EXT:" prefix in file path.
if ( substr ( $this -> conf [ 'stylesheet' ], 0 , 4 ) == 'EXT:' ) {
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
list ( $extKey , $filePath ) = explode ( '/' , substr ( $this -> conf [ 'stylesheet' ], 4 ), 2 );
2017-07-31 16:49:11 +02:00
2018-01-09 15:17:30 +01:00
if ( \TYPO3\CMS\Core\Utility\ExtensionManagementUtility :: isLoaded ( $extKey )) {
$this -> conf [ 'stylesheet' ] = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility :: siteRelPath ( $extKey ) . $filePath ;
}
}
2017-07-31 16:49:11 +02:00
2018-01-09 15:17:30 +01:00
$stylesheet = \TYPO3\CMS\Core\Utility\GeneralUtility :: locationHeaderUrl ( $this -> conf [ 'stylesheet' ]);
2017-07-31 16:49:11 +02:00
2018-01-09 15:17:30 +01:00
} else {
// Use default stylesheet if no custom stylesheet is given.
2019-03-14 15:42:34 +01:00
$stylesheet = \TYPO3\CMS\Core\Utility\GeneralUtility :: locationHeaderUrl ( \TYPO3\CMS\Core\Utility\ExtensionManagementUtility :: siteRelPath ( $this -> extKey ) . 'Resources/Public/Stylesheets/OaiPmh.xsl' );
2018-01-09 15:17:30 +01:00
}
$this -> oai -> appendChild ( $this -> oai -> createProcessingInstruction ( 'xml-stylesheet' , 'type="text/xsl" href="' . htmlspecialchars ( $stylesheet , ENT_NOQUOTES , 'UTF-8' ) . '"' ));
// Create root element.
$root = $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'OAI-PMH' );
$root -> setAttributeNS ( 'http://www.w3.org/2000/xmlns/' , 'xmlns:xsi' , 'http://www.w3.org/2001/XMLSchema-instance' );
$root -> setAttributeNS ( 'http://www.w3.org/2001/XMLSchema-instance' , 'xsi:schemaLocation' , 'http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd' );
// Add response date.
$root -> appendChild ( $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'responseDate' , gmdate ( 'Y-m-d\TH:i:s\Z' , $GLOBALS [ 'EXEC_TIME' ])));
// Get response data.
switch ( $this -> piVars [ 'verb' ]) {
case 'GetRecord' :
$response = $this -> verbGetRecord ();
break ;
case 'Identify' :
$response = $this -> verbIdentify ();
break ;
case 'ListIdentifiers' :
$response = $this -> verbListIdentifiers ();
break ;
case 'ListMetadataFormats' :
$response = $this -> verbListMetadataFormats ();
break ;
case 'ListRecords' :
$response = $this -> verbListRecords ();
break ;
case 'ListSets' :
$response = $this -> verbListSets ();
break ;
default :
$response = $this -> error ( 'badVerb' );
}
// Add request.
$linkConf = array (
'parameter' => $GLOBALS [ 'TSFE' ] -> id ,
'forceAbsoluteUrl' => 1
);
$request = $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'request' , htmlspecialchars ( $this -> cObj -> typoLink_URL ( $linkConf ), ENT_NOQUOTES , 'UTF-8' ));
if ( ! $this -> error ) {
foreach ( $this -> piVars as $key => $value ) {
$request -> setAttribute ( $key , htmlspecialchars ( $value , ENT_NOQUOTES , 'UTF-8' ));
}
}
$root -> appendChild ( $request );
$root -> appendChild ( $response );
$this -> oai -> appendChild ( $root );
$content = $this -> oai -> saveXML ();
// Clean output buffer.
\TYPO3\CMS\Core\Utility\GeneralUtility :: cleanOutputBuffers ();
2017-07-31 16:49:11 +02:00
2018-01-09 15:17:30 +01:00
// Send headers.
header ( 'HTTP/1.1 200 OK' );
header ( 'Cache-Control: no-cache' );
header ( 'Content-Length: ' . strlen ( $content ));
header ( 'Content-Type: text/xml; charset=utf-8' );
header ( 'Date: ' . date ( 'r' , $GLOBALS [ 'EXEC_TIME' ]));
header ( 'Expires: ' . date ( 'r' , $GLOBALS [ 'EXEC_TIME' ] + $this -> conf [ 'expired' ]));
echo $content ;
2017-07-31 16:49:11 +02:00
2018-01-09 15:17:30 +01:00
// Flush output buffer and end script processing.
ob_end_flush ();
exit ;
}
2017-07-31 16:49:11 +02:00
2018-01-09 15:17:30 +01:00
/**
* Continue with resumption token
*
* @ access protected
*
* @ return string Substitution for subpart " ###RESPONSE### "
*/
protected function resume () {
// Get resumption token.
$result = $GLOBALS [ 'TYPO3_DB' ] -> exec_SELECTquery (
'tx_dlf_tokens.options AS options' ,
'tx_dlf_tokens' ,
'tx_dlf_tokens.ident="oai" AND tx_dlf_tokens.token=' . $GLOBALS [ 'TYPO3_DB' ] -> fullQuoteStr ( $this -> piVars [ 'resumptionToken' ], 'tx_dlf_tokens' ),
'' ,
'' ,
'1'
);
if ( ! $GLOBALS [ 'TYPO3_DB' ] -> sql_num_rows ( $result )) {
// No resumption token found or resumption token expired.
return $this -> error ( 'badResumptionToken' );
}
$resArray = $GLOBALS [ 'TYPO3_DB' ] -> sql_fetch_assoc ( $result );
$resultSet = unserialize ( $resArray [ 'options' ]);
return $this -> generateOutputForDocumentList ( $resultSet );
}
/**
* Process verb " GetRecord "
*
* @ access protected
*
* @ return string Substitution for subpart " ###RESPONSE### "
*/
protected function verbGetRecord () {
if ( count ( $this -> piVars ) != 3 || empty ( $this -> piVars [ 'metadataPrefix' ]) || empty ( $this -> piVars [ 'identifier' ])) {
return $this -> error ( 'badArgument' );
}
if ( ! in_array ( $this -> piVars [ 'metadataPrefix' ], array_keys ( $this -> formats ))) {
return $this -> error ( 'cannotDisseminateFormat' );
}
$where = '' ;
if ( ! $this -> conf [ 'show_userdefined' ]) {
$where .= ' AND tx_dlf_collections.fe_cruser_id=0' ;
}
$record = $GLOBALS [ 'TYPO3_DB' ] -> exec_SELECT_mm_query (
'tx_dlf_documents.*,GROUP_CONCAT(DISTINCT tx_dlf_collections.oai_name ORDER BY tx_dlf_collections.oai_name SEPARATOR " ") AS collections' ,
'tx_dlf_documents' ,
'tx_dlf_relations' ,
'tx_dlf_collections' ,
2019-03-13 08:29:51 +01:00
'AND tx_dlf_documents.record_id=' . $GLOBALS [ 'TYPO3_DB' ] -> fullQuoteStr ( $this -> piVars [ 'identifier' ], 'tx_dlf_documents' ) . ' AND tx_dlf_documents.pid=' . intval ( $this -> conf [ 'pages' ]) . ' AND tx_dlf_collections.pid=' . intval ( $this -> conf [ 'pages' ]) . ' AND tx_dlf_relations.ident=' . $GLOBALS [ 'TYPO3_DB' ] -> fullQuoteStr ( 'docs_colls' , 'tx_dlf_relations' ) . $where . Helper :: whereClause ( 'tx_dlf_collections' ),
2018-01-09 15:17:30 +01:00
'tx_dlf_documents.uid' ,
'tx_dlf_documents.tstamp' ,
'1'
);
if ( ! $GLOBALS [ 'TYPO3_DB' ] -> sql_num_rows ( $record )) {
return $this -> error ( 'idDoesNotExist' );
}
$resArray = $GLOBALS [ 'TYPO3_DB' ] -> sql_fetch_assoc ( $record );
// Check for required fields.
foreach ( $this -> formats [ $this -> piVars [ 'metadataPrefix' ]][ 'requiredFields' ] as $required ) {
if ( empty ( $resArray [ $required ])) {
return $this -> error ( 'cannotDisseminateFormat' );
}
}
$GetRecord = $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'GetRecord' );
$recordNode = $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'record' );
$headerNode = $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'header' );
$headerNode -> appendChild ( $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'identifier' , htmlspecialchars ( $resArray [ 'record_id' ], ENT_NOQUOTES , 'UTF-8' )));
$headerNode -> appendChild ( $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'datestamp' , gmdate ( 'Y-m-d\TH:i:s\Z' , $resArray [ 'tstamp' ])));
// Handle deleted documents.
// TODO: Use TYPO3 API functions here!
if ( $resArray [ 'deleted' ] || $resArray [ 'hidden' ]) {
$headerNode -> setAttribute ( 'status' , 'deleted' );
$recordNode -> appendChild ( $headerNode );
} else {
foreach ( explode ( ' ' , $resArray [ 'collections' ]) as $spec ) {
$headerNode -> appendChild ( $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'setSpec' , htmlspecialchars ( $spec , ENT_NOQUOTES , 'UTF-8' )));
}
$recordNode -> appendChild ( $headerNode );
$metadataNode = $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'metadata' );
switch ( $this -> piVars [ 'metadataPrefix' ]) {
case 'oai_dc' :
$metadataNode -> appendChild ( $this -> getDcData ( $resArray ));
break ;
case 'epicur' :
$metadataNode -> appendChild ( $this -> getEpicurData ( $resArray ));
break ;
case 'mets' :
$metadataNode -> appendChild ( $this -> getMetsData ( $resArray ));
break ;
}
$recordNode -> appendChild ( $metadataNode );
}
$GetRecord -> appendChild ( $recordNode );
return $GetRecord ;
}
/**
* Process verb " Identify "
*
* @ access protected
*
2019-03-13 17:55:50 +01:00
* @ return \DOMElement XML node to add to the OAI response
2018-01-09 15:17:30 +01:00
*/
protected function verbIdentify () {
// Check for invalid arguments.
if ( count ( $this -> piVars ) > 1 ) {
return $this -> error ( 'badArgument' );
}
// Get repository name and administrative contact.
// Use default values for an installation with incomplete plugin configuration.
$adminEmail = 'unknown@example.org' ;
$repositoryName = 'Kitodo.Presentation OAI-PMH interface (incomplete configuration)' ;
$result = $GLOBALS [ 'TYPO3_DB' ] -> exec_SELECTquery (
'tx_dlf_libraries.oai_label AS oai_label,tx_dlf_libraries.contact AS contact' ,
'tx_dlf_libraries' ,
2019-03-13 08:29:51 +01:00
'tx_dlf_libraries.pid=' . intval ( $this -> conf [ 'pages' ]) . ' AND tx_dlf_libraries.uid=' . intval ( $this -> conf [ 'library' ]) . Helper :: whereClause ( 'tx_dlf_libraries' ),
2018-01-09 15:17:30 +01:00
'' ,
'' ,
''
);
if ( $GLOBALS [ 'TYPO3_DB' ] -> sql_num_rows ( $result )) {
$resArray = $GLOBALS [ 'TYPO3_DB' ] -> sql_fetch_assoc ( $result );
$adminEmail = htmlspecialchars ( trim ( str_replace ( 'mailto:' , '' , $resArray [ 'contact' ])), ENT_NOQUOTES );
$repositoryName = htmlspecialchars ( $resArray [ 'oai_label' ], ENT_NOQUOTES );
} else {
2019-03-14 15:42:34 +01:00
$this -> devLog ( '[\Kitodo\Dlf\Plugins\OaiPmh->verbIdentify()] Incomplete plugin configuration' , SYSLOG_SEVERITY_NOTICE );
2018-01-09 15:17:30 +01:00
}
// Get earliest datestamp. Use a default value if that fails.
$earliestDatestamp = '0000-00-00T00:00:00Z' ;
$result = $GLOBALS [ 'TYPO3_DB' ] -> exec_SELECTquery (
'tx_dlf_documents.tstamp AS tstamp' ,
'tx_dlf_documents' ,
2018-01-09 15:28:11 +01:00
'tx_dlf_documents.pid=' . intval ( $this -> conf [ 'pages' ]),
2018-01-09 15:17:30 +01:00
'' ,
'tx_dlf_documents.tstamp ASC' ,
'1'
);
if ( $GLOBALS [ 'TYPO3_DB' ] -> sql_num_rows ( $result )) {
list ( $timestamp ) = $GLOBALS [ 'TYPO3_DB' ] -> sql_fetch_row ( $result );
$earliestDatestamp = gmdate ( 'Y-m-d\TH:i:s\Z' , $timestamp );
} else {
2019-03-14 15:42:34 +01:00
$this -> devLog ( '[\Kitodo\Dlf\Plugins\OaiPmh->verbIdentify()] No records found with PID "' . $this -> conf [ 'pages' ] . '"' , SYSLOG_SEVERITY_NOTICE );
2018-01-09 15:17:30 +01:00
}
$linkConf = array (
'parameter' => $GLOBALS [ 'TSFE' ] -> id ,
'forceAbsoluteUrl' => 1
);
$baseURL = htmlspecialchars ( $this -> cObj -> typoLink_URL ( $linkConf ), ENT_NOQUOTES );
// Add identification node.
$Identify = $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'Identify' );
$Identify -> appendChild ( $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'repositoryName' , $repositoryName ));
2018-01-09 15:28:11 +01:00
$Identify -> appendChild ( $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'baseURL' , $baseURL ));
$Identify -> appendChild ( $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'protocolVersion' , '2.0' ));
$Identify -> appendChild ( $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'adminEmail' , $adminEmail ));
$Identify -> appendChild ( $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'earliestDatestamp' , $earliestDatestamp ));
$Identify -> appendChild ( $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'deletedRecord' , 'transient' ));
$Identify -> appendChild ( $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'granularity' , 'YYYY-MM-DDThh:mm:ssZ' ));
2018-01-09 15:17:30 +01:00
return $Identify ;
}
/**
* Process verb " ListIdentifiers "
*
* @ access protected
*
* @ return string Substitution for subpart " ###RESPONSE### "
*/
protected function verbListIdentifiers () {
// If we have a resumption token we can continue our work
if ( ! empty ( $this -> piVars [ 'resumptionToken' ])) {
// "resumptionToken" is an exclusive argument.
if ( count ( $this -> piVars ) > 2 ) {
return $this -> error ( 'badArgument' );
} else {
return $this -> resume ();
}
}
// "metadataPrefix" is required and "identifier" is not allowed.
if ( empty ( $this -> piVars [ 'metadataPrefix' ]) || ! empty ( $this -> piVars [ 'identifier' ])) {
return $this -> error ( 'badArgument' );
}
if ( ! in_array ( $this -> piVars [ 'metadataPrefix' ], array_keys ( $this -> formats ))) {
return $this -> error ( 'cannotDisseminateFormat' );
}
try {
$documentSet = $this -> fetchDocumentUIDs ();
2019-03-13 17:55:50 +01:00
} catch ( \Exception $exception ) {
2018-01-09 15:17:30 +01:00
return $this -> error ( $exception -> getMessage ());
}
2019-03-13 08:29:51 +01:00
$resultSet = \TYPO3\CMS\Core\Utility\GeneralUtility :: makeInstance ( DocumentList :: class );
2018-01-09 15:17:30 +01:00
$resultSet -> reset ();
$resultSet -> add ( $documentSet );
$resultSet -> metadata = array (
'completeListSize' => count ( $documentSet ),
'metadataPrefix' => $this -> piVars [ 'metadataPrefix' ],
);
return $this -> generateOutputForDocumentList ( $resultSet );
}
/**
* Process verb " ListMetadataFormats "
*
* @ access protected
*
2019-03-13 17:55:50 +01:00
* @ return \DOMElement XML node to add to the OAI response
2018-01-09 15:17:30 +01:00
*/
protected function verbListMetadataFormats () {
$resArray = array ();
// Check for invalid arguments.
if ( count ( $this -> piVars ) > 1 ) {
if ( empty ( $this -> piVars [ 'identifier' ]) || count ( $this -> piVars ) > 2 ) {
return $this -> error ( 'badArgument' );
}
// Check given identifier.
$result = $GLOBALS [ 'TYPO3_DB' ] -> exec_SELECTquery (
'tx_dlf_documents.*' ,
'tx_dlf_documents' ,
'tx_dlf_documents.pid=' . intval ( $this -> conf [ 'pages' ]) . ' AND tx_dlf_documents.record_id=' . $GLOBALS [ 'TYPO3_DB' ] -> fullQuoteStr ( $this -> piVars [ 'identifier' ], 'tx_dlf_documents' ),
'' ,
'' ,
'1'
);
if ( ! $GLOBALS [ 'TYPO3_DB' ] -> sql_num_rows ( $result )) {
return $this -> error ( 'idDoesNotExist' );
}
$resArray = $GLOBALS [ 'TYPO3_DB' ] -> sql_fetch_assoc ( $result );
}
// Add metadata formats node.
$ListMetadaFormats = $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'ListMetadataFormats' );
foreach ( $this -> formats as $prefix => $details ) {
if ( ! empty ( $resArray )) {
foreach ( $details [ 'requiredFields' ] as $required ) {
if ( empty ( $resArray [ $required ])) {
// Skip metadata formats whose requirements are not met.
continue 2 ;
}
}
}
// Add format node.
$format = $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'metadataFormat' );
$format -> appendChild ( $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'metadataPrefix' , htmlspecialchars ( $prefix , ENT_NOQUOTES , 'UTF-8' )));
$format -> appendChild ( $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'schema' , htmlspecialchars ( $details [ 'schema' ], ENT_NOQUOTES , 'UTF-8' )));
$format -> appendChild ( $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'metadataNamespace' , htmlspecialchars ( $details [ 'namespace' ], ENT_NOQUOTES , 'UTF-8' )));
$ListMetadaFormats -> appendChild ( $format );
}
return $ListMetadaFormats ;
}
/**
* Process verb " ListRecords "
*
* @ access protected
*
* @ return string Substitution for subpart " ###RESPONSE### "
*/
protected function verbListRecords () {
// Check for invalid arguments.
if ( ! empty ( $this -> piVars [ 'resumptionToken' ])) {
// "resumptionToken" is an exclusive argument.
if ( count ( $this -> piVars ) > 2 ) {
return $this -> error ( 'badArgument' );
} else {
return $this -> resume ();
}
}
if ( empty ( $this -> piVars [ 'metadataPrefix' ]) || ! empty ( $this -> piVars [ 'identifier' ])) {
// "metadataPrefix" is required and "identifier" is not allowed.
return $this -> error ( 'badArgument' );
}
// Check "metadataPrefix" for valid value.
if ( ! in_array ( $this -> piVars [ 'metadataPrefix' ], array_keys ( $this -> formats ))) {
return $this -> error ( 'cannotDisseminateFormat' );
}
try {
$documentSet = $this -> fetchDocumentUIDs ();
2019-03-13 17:55:50 +01:00
} catch ( \Exception $exception ) {
2018-01-09 15:17:30 +01:00
return $this -> error ( $exception -> getMessage ());
}
2019-03-13 08:29:51 +01:00
$resultSet = \TYPO3\CMS\Core\Utility\GeneralUtility :: makeInstance ( DocumentList :: class );
2018-01-09 15:17:30 +01:00
$resultSet -> reset ();
$resultSet -> add ( $documentSet );
$resultSet -> metadata = array (
'completeListSize' => count ( $documentSet ),
'metadataPrefix' => $this -> piVars [ 'metadataPrefix' ],
);
return $this -> generateOutputForDocumentList ( $resultSet );
}
/**
* Process verb " ListSets "
*
* @ access protected
*
* @ return string Substitution for subpart " ###RESPONSE### "
*/
protected function verbListSets () {
// Check for invalid arguments.
if ( count ( $this -> piVars ) > 1 ) {
if ( ! empty ( $this -> piVars [ 'resumptionToken' ])) {
return $this -> error ( 'badResumptionToken' );
} else {
return $this -> error ( 'badArgument' );
}
}
$where = '' ;
if ( ! $this -> conf [ 'show_userdefined' ]) {
$where = ' AND tx_dlf_collections.fe_cruser_id=0' ;
}
$result = $GLOBALS [ 'TYPO3_DB' ] -> exec_SELECTquery (
'tx_dlf_collections.oai_name AS oai_name,tx_dlf_collections.label AS label' ,
'tx_dlf_collections' ,
2019-03-13 08:29:51 +01:00
'tx_dlf_collections.sys_language_uid IN (-1,0) AND NOT tx_dlf_collections.oai_name=\'\' AND tx_dlf_collections.pid=' . intval ( $this -> conf [ 'pages' ]) . $where . Helper :: whereClause ( 'tx_dlf_collections' ),
2018-01-09 15:17:30 +01:00
'tx_dlf_collections.oai_name' ,
'tx_dlf_collections.oai_name' ,
''
);
if ( ! $GLOBALS [ 'TYPO3_DB' ] -> sql_num_rows ( $result )) {
return $this -> error ( 'noSetHierarchy' );
}
$ListSets = $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'ListSets' );
while ( $resArray = $GLOBALS [ 'TYPO3_DB' ] -> sql_fetch_assoc ( $result )) {
$set = $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'set' );
$set -> appendChild ( $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'setSpec' , htmlspecialchars ( $resArray [ 'oai_name' ], ENT_NOQUOTES , 'UTF-8' )));
$set -> appendChild ( $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'setName' , htmlspecialchars ( $resArray [ 'label' ], ENT_NOQUOTES , 'UTF-8' )));
$ListSets -> appendChild ( $set );
}
return $ListSets ;
}
/**
* @ return array
2019-03-13 17:55:50 +01:00
* @ throws \Exception
2018-01-09 15:17:30 +01:00
*/
2018-01-09 15:28:11 +01:00
private function fetchDocumentUIDs () {
2018-01-09 15:17:30 +01:00
$solr_query = '' ;
if ( ! $this -> conf [ 'show_userdefined' ]) {
$where = ' AND tx_dlf_collections.fe_cruser_id=0' ;
}
2017-07-31 16:49:11 +02:00
2018-01-09 15:17:30 +01:00
// Check "set" for valid value.
if ( ! empty ( $this -> piVars [ 'set' ])) {
2017-07-31 16:49:11 +02:00
2018-01-09 15:17:30 +01:00
// For SOLR we need the index_name of the collection,
// For DB Query we need the UID of the collection
$result = $GLOBALS [ 'TYPO3_DB' ] -> exec_SELECTquery (
'tx_dlf_collections.index_name AS index_name, tx_dlf_collections.uid AS uid, tx_dlf_collections.index_search as index_query ' ,
'tx_dlf_collections' ,
2018-01-09 15:28:11 +01:00
'tx_dlf_collections.pid=' . intval ( $this -> conf [ 'pages' ]) . ' AND tx_dlf_collections.oai_name=' . $GLOBALS [ 'TYPO3_DB' ] -> fullQuoteStr ( $this -> piVars [ 'set' ],
2019-03-13 08:29:51 +01:00
'tx_dlf_collections' ) . $where . Helper :: whereClause ( 'tx_dlf_collections' ),
2018-01-09 15:17:30 +01:00
'' ,
'' ,
'1'
);
2017-07-31 16:49:11 +02:00
2018-01-09 15:17:30 +01:00
if ( ! $GLOBALS [ 'TYPO3_DB' ] -> sql_num_rows ( $result )) {
2019-03-13 17:55:50 +01:00
throw new \Exception ( 'noSetHierarchy' );
2018-01-09 15:17:30 +01:00
}
2017-07-31 16:49:11 +02:00
2018-01-09 15:17:30 +01:00
$resArray = $GLOBALS [ 'TYPO3_DB' ] -> sql_fetch_assoc ( $result );
2017-07-31 16:49:11 +02:00
2018-01-09 15:28:11 +01:00
if ( $resArray [ 'index_query' ] != " " ) {
$solr_query .= '(' . $resArray [ 'index_query' ] . ')' ;
2018-01-09 15:17:30 +01:00
} else {
2018-01-09 15:28:11 +01:00
$solr_query .= 'collection:' . '"' . $resArray [ 'index_name' ] . '"' ;
2018-01-09 15:17:30 +01:00
}
} else {
// If no set is specified we have to query for all collections
$solr_query .= 'collection:* NOT collection:""' ;
2017-07-31 16:49:11 +02:00
2018-01-09 15:17:30 +01:00
}
2017-07-31 16:49:11 +02:00
2018-01-09 15:17:30 +01:00
// Check for required fields.
foreach ( $this -> formats [ $this -> piVars [ 'metadataPrefix' ]][ 'requiredFields' ] as $required ) {
2018-01-09 15:28:11 +01:00
$solr_query .= ' NOT ' . $required . ':""' ;
2018-01-09 15:17:30 +01:00
}
2011-09-13 17:49:30 +02:00
2018-06-12 15:47:08 +02:00
// toplevel="true" is always required
$solr_query .= ' AND toplevel:"true"' ;
2018-01-09 15:17:30 +01:00
$from = " * " ;
// Check "from" for valid value.
if ( ! empty ( $this -> piVars [ 'from' ])) {
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
// Is valid format?
if ( is_array ( $date_array = strptime ( $this -> piVars [ 'from' ],
'%Y-%m-%dT%H:%M:%SZ' )) || is_array ( $date_array = strptime ( $this -> piVars [ 'from' ], '%Y-%m-%d' ))) {
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$timestamp = gmmktime ( $date_array [ 'tm_hour' ], $date_array [ 'tm_min' ], $date_array [ 'tm_sec' ], $date_array [ 'tm_mon' ] + 1 ,
$date_array [ 'tm_mday' ], $date_array [ 'tm_year' ] + 1900 );
2017-07-31 16:49:11 +02:00
2018-01-09 15:28:11 +01:00
$from = date ( " Y-m-d " , $timestamp ) . 'T' . date ( " H:i:s " , $timestamp ) . '.000Z' ;
2017-07-31 16:49:11 +02:00
2018-01-09 15:17:30 +01:00
} else {
2019-03-13 17:55:50 +01:00
throw new \Exception ( 'badArgument' );
2018-01-09 15:17:30 +01:00
}
}
2017-07-31 16:49:11 +02:00
2018-01-09 15:17:30 +01:00
$until = " * " ;
// Check "until" for valid value.
if ( ! empty ( $this -> piVars [ 'until' ])) {
2017-07-31 16:49:11 +02:00
2018-01-09 15:17:30 +01:00
// Is valid format?
if ( is_array ( $date_array = strptime ( $this -> piVars [ 'until' ],
'%Y-%m-%dT%H:%M:%SZ' )) || is_array ( $date_array = strptime ( $this -> piVars [ 'until' ], '%Y-%m-%d' ))) {
2017-07-31 16:49:11 +02:00
2018-01-09 15:17:30 +01:00
$timestamp = gmmktime ( $date_array [ 'tm_hour' ], $date_array [ 'tm_min' ], $date_array [ 'tm_sec' ], $date_array [ 'tm_mon' ] + 1 ,
$date_array [ 'tm_mday' ], $date_array [ 'tm_year' ] + 1900 );
2017-07-31 16:49:11 +02:00
2018-01-09 15:28:11 +01:00
$until = date ( " Y-m-d " , $timestamp ) . 'T' . date ( " H:i:s " , $timestamp ) . '.999Z' ;
2017-07-31 16:49:11 +02:00
2018-01-09 15:17:30 +01:00
if ( $from != " * " && $from > $until ) {
2019-03-13 17:55:50 +01:00
throw new \Exception ( 'badArgument' );
2018-01-09 15:17:30 +01:00
}
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
} else {
2019-03-13 17:55:50 +01:00
throw new \Exception ( 'badArgument' );
2018-01-09 15:17:30 +01:00
}
}
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
// Check "from" and "until" for same granularity.
if ( ! empty ( $this -> piVars [ 'from' ]) && ! empty ( $this -> piVars [ 'until' ])) {
if ( strlen ( $this -> piVars [ 'from' ]) != strlen ( $this -> piVars [ 'until' ])) {
2019-03-13 17:55:50 +01:00
throw new \Exception ( 'badArgument' );
2018-01-09 15:17:30 +01:00
}
}
2011-09-13 17:49:30 +02:00
2018-01-09 15:28:11 +01:00
$solr_query .= ' AND timestamp:[' . $from . ' TO ' . $until . ']' ;
2018-01-09 15:17:30 +01:00
2018-01-09 15:28:11 +01:00
$documentSet = array ();
2018-01-09 15:17:30 +01:00
2019-03-13 08:29:51 +01:00
$solr = Solr :: getInstance ( $this -> conf [ 'solrcore' ]);
2018-01-09 15:17:30 +01:00
2018-06-14 14:37:41 +02:00
if ( intval ( $this -> conf [ 'solr_limit' ]) > 0 ) {
$solr -> limit = intval ( $this -> conf [ 'solr_limit' ]);
}
2018-01-09 15:17:30 +01:00
// We only care about the UID in the results and want them sorted
2018-08-02 09:10:47 +02:00
$parameters = array (
" fields " => " uid " ,
" sort " => array (
" uid " => " asc "
)
);
2018-01-09 15:17:30 +01:00
$result = $solr -> search_raw ( $solr_query , $parameters );
if ( empty ( $result )) {
2019-03-13 17:55:50 +01:00
throw new \Exception ( 'noRecordsMatch' );
2018-01-09 15:17:30 +01:00
}
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
foreach ( $result as $doc ) {
$documentSet [] = $doc -> uid ;
}
return $documentSet ;
}
/**
2019-03-13 08:29:51 +01:00
* @ param \Kitodo\Dlf\Common\DocumentList $documentListSet
* @ return \DOMElement
2018-01-09 15:17:30 +01:00
*/
private function generateOutputForDocumentList ( $documentListSet ) {
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$documentsToProcess = $documentListSet -> removeRange ( 0 , intval ( $this -> conf [ 'limit' ]));
$verb = $this -> piVars [ 'verb' ];
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$documents = $GLOBALS [ 'TYPO3_DB' ] -> exec_SELECT_mm_query (
'tx_dlf_documents.*,GROUP_CONCAT(DISTINCT tx_dlf_collections.oai_name ORDER BY tx_dlf_collections.oai_name SEPARATOR " ") AS collections' ,
'tx_dlf_documents' ,
'tx_dlf_relations' ,
'tx_dlf_collections' ,
2019-03-13 08:29:51 +01:00
'AND tx_dlf_documents.uid IN (' . implode ( ',' , $GLOBALS [ 'TYPO3_DB' ] -> cleanIntArray ( $documentsToProcess )) . ') AND tx_dlf_documents.pid=' . intval ( $this -> conf [ 'pages' ]) . ' AND tx_dlf_collections.pid=' . intval ( $this -> conf [ 'pages' ]) . ' AND tx_dlf_relations.ident=' . $GLOBALS [ 'TYPO3_DB' ] -> fullQuoteStr ( 'docs_colls' , 'tx_dlf_relations' ) . Helper :: whereClause ( 'tx_dlf_collections' ),
2018-01-09 15:17:30 +01:00
'tx_dlf_documents.uid' ,
'tx_dlf_documents.tstamp' ,
$this -> conf [ 'limit' ]
);
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$output = $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , $verb );
while ( $resArray = $GLOBALS [ 'TYPO3_DB' ] -> sql_fetch_assoc ( $documents )) {
// Add header node.
$header = $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'header' );
$header -> appendChild ( $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'identifier' , htmlspecialchars ( $resArray [ 'record_id' ], ENT_NOQUOTES , 'UTF-8' )));
$header -> appendChild ( $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'datestamp' , gmdate ( 'Y-m-d\TH:i:s\Z' , $resArray [ 'tstamp' ])));
// Check if document is deleted or hidden.
// TODO: Use TYPO3 API functions here!
if ( $resArray [ 'deleted' ] || $resArray [ 'hidden' ]) {
// Add "deleted" status.
$header -> setAttribute ( 'status' , 'deleted' );
if ( $verb == 'ListRecords' ) {
// Add record node.
$record = $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'record' );
2011-09-13 17:49:30 +02:00
2018-01-09 15:17:30 +01:00
$record -> appendChild ( $header );
$output -> appendChild ( $record );
} elseif ( $verb == 'ListIdentifiers' ) {
$output -> appendChild ( $header );
}
} else {
// Add sets.
foreach ( explode ( ' ' , $resArray [ 'collections' ]) as $spec ) {
$header -> appendChild ( $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'setSpec' , htmlspecialchars ( $spec , ENT_NOQUOTES , 'UTF-8' )));
}
if ( $verb == 'ListRecords' ) {
// Add record node.
$record = $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'record' );
$record -> appendChild ( $header );
// Add metadata node.
$metadata = $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'metadata' );
$metadataPrefix = $this -> piVars [ 'metadataPrefix' ];
2018-01-09 15:28:11 +01:00
if ( ! $metadataPrefix ) {
2018-01-09 15:17:30 +01:00
// If we resume an action the metadataPrefix is stored with the documentSet
$metadataPrefix = $documentListSet -> metadata [ 'metadataPrefix' ];
}
switch ( $metadataPrefix ) {
case 'oai_dc' :
$metadata -> appendChild ( $this -> getDcData ( $resArray ));
break ;
case 'epicur' :
$metadata -> appendChild ( $this -> getEpicurData ( $resArray ));
break ;
case 'mets' :
$metadata -> appendChild ( $this -> getMetsData ( $resArray ));
break ;
}
$record -> appendChild ( $metadata );
$output -> appendChild ( $record );
} elseif ( $verb == 'ListIdentifiers' ) {
$output -> appendChild ( $header );
}
}
}
$output -> appendChild ( $this -> generateResumptionTokenForDocumentListSet ( $documentListSet ));
return $output ;
}
/**
2019-03-13 08:29:51 +01:00
* @ param \Kitodo\Dlf\Common\DocumentList $documentListSet
* @ return \DOMElement
2018-01-09 15:17:30 +01:00
*/
2018-01-09 15:28:11 +01:00
private function generateResumptionTokenForDocumentListSet ( $documentListSet ) {
2018-01-09 15:17:30 +01:00
if ( $documentListSet -> count () != 0 ) {
$token = uniqid ();
$GLOBALS [ 'TYPO3_DB' ] -> exec_INSERTquery (
'tx_dlf_tokens' ,
2018-01-09 15:28:11 +01:00
array (
2018-01-09 15:17:30 +01:00
'tstamp' => $GLOBALS [ 'EXEC_TIME' ],
'token' => $token ,
'options' => serialize ( $documentListSet ),
'ident' => 'oai' ,
)
);
2018-01-09 15:28:11 +01:00
if ( $GLOBALS [ 'TYPO3_DB' ] -> sql_affected_rows () == 1 ) {
2018-08-22 09:57:43 +02:00
$resumptionToken = $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'resumptionToken' , htmlspecialchars ( $token , ENT_NOQUOTES , 'UTF-8' ));
2018-01-09 15:17:30 +01:00
} else {
2019-03-14 15:42:34 +01:00
$this -> devLog ( '[\Kitodo\Dlf\Plugins\OaiPmh->verb' . $this -> piVars [ 'verb' ] . '()] Could not create resumption token' , SYSLOG_SEVERITY_ERROR );
2018-08-22 09:57:43 +02:00
2018-01-09 15:17:30 +01:00
}
2018-08-22 09:57:43 +02:00
} else {
// Result set complete. We don't need a token.
$resumptionToken = $this -> oai -> createElementNS ( 'http://www.openarchives.org/OAI/2.0/' , 'resumptionToken' );
2018-01-09 15:17:30 +01:00
}
$resumptionToken -> setAttribute ( 'cursor' , intval ( $documentListSet -> metadata [ 'completeListSize' ]) - count ( $documentListSet ));
2018-01-09 15:28:11 +01:00
$resumptionToken -> setAttribute ( 'completeListSize' , $documentListSet -> metadata [ 'completeListSize' ]);
2018-01-09 15:17:30 +01:00
$resumptionToken -> setAttribute ( 'expirationDate' , gmdate ( 'Y-m-d\TH:i:s\Z' , $GLOBALS [ 'EXEC_TIME' ] + $this -> conf [ 'expired' ]));
return $resumptionToken ;
}
2018-01-09 15:28:11 +01:00
private function devLog ( $message , $severity , $data = NULL ) {
2018-01-09 15:17:30 +01:00
if ( TYPO3_DLOG ) {
\TYPO3\CMS\Core\Utility\GeneralUtility :: devLog ( $message , $this -> extKey , $severity , $data );
}
}
2011-09-13 17:49:30 +02:00
2018-01-04 08:40:27 +01:00
}