First draft
This commit is contained in:
186
src/OAI/Verb/ListRecords.php
Normal file
186
src/OAI/Verb/ListRecords.php
Normal file
@@ -0,0 +1,186 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\OAI\Verb;
|
||||
|
||||
use App\OAI\{
|
||||
RecordOaiDc,
|
||||
RecordOaiDataCite,
|
||||
RecordOaiInterface,
|
||||
ResumptionToken
|
||||
};
|
||||
use App\OAI\Exception\InvalidTokenException;
|
||||
use App\OAI\OaiBase;
|
||||
use App\OAI\OaiError;
|
||||
use \Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
use function \Symfony\Component\String\b;
|
||||
|
||||
/**
|
||||
* Represents a ListRecords response
|
||||
*/
|
||||
final class ListRecords
|
||||
{
|
||||
private RecordOaiInterface $record;
|
||||
private Request $request;
|
||||
private ?string $metadataFormat;
|
||||
private ?ResumptionToken $resumptionToken;
|
||||
|
||||
public function __construct(Request $req)
|
||||
{
|
||||
$this->request = $req;
|
||||
}
|
||||
/**
|
||||
* Returns the XML response
|
||||
* @todo Refactor (complexity...)
|
||||
*/
|
||||
public function response(): string
|
||||
{
|
||||
$this->metadataFormat = $this->request->get('metadataPrefix');
|
||||
$until = $this->request->get('until');
|
||||
$from = $this->request->get('from');
|
||||
$set = $this->request->get('set');
|
||||
$token = $this->request->get('resumptionToken');
|
||||
|
||||
if ($token !== null) {
|
||||
$tokenObj = ResumptionToken::decode($token);
|
||||
$set = $tokenObj->set;
|
||||
$this->metadataFormat = $tokenObj->metadataFormat;
|
||||
$from = $tokenObj->from;
|
||||
$until = $tokenObj->until;
|
||||
}
|
||||
|
||||
$hasErrors = $this->hasErrors($from, $until, $set);
|
||||
|
||||
if ($hasErrors !== false) return $hasErrors->toXML();
|
||||
|
||||
try {
|
||||
$identifiers = $this->getIdentifiers(
|
||||
$set,
|
||||
$from,
|
||||
$until,
|
||||
);
|
||||
}
|
||||
catch (InvalidTokenException $e) {
|
||||
return (new OaiError($e->getCode(), $e->getMessage()))
|
||||
->toXML();
|
||||
}
|
||||
|
||||
if (count($identifiers) === 0) {
|
||||
return (new OaiError('noRecordsMatch', 'No records were found in repository.'))
|
||||
->toXML();
|
||||
}
|
||||
|
||||
$xml = '';
|
||||
|
||||
$xml = $this->createXML($identifiers, $this->metadataFormat);
|
||||
$xml = b($xml)->toUnicodeString()->trim("\n");
|
||||
$xml = $xml->prepend("<ListRecords>\n");
|
||||
$xml = $xml->append("\n</ListRecords>");
|
||||
|
||||
return OaiBase::create($xml->toString(), 'ListRecords', $this->metadataFormat);
|
||||
}
|
||||
|
||||
private function checkGranularity(string $date): bool
|
||||
{
|
||||
$valid = true;
|
||||
$pattern = "/\d{4}-\d{2}-\d{2}/";
|
||||
preg_match($pattern, $date, $matches);
|
||||
|
||||
if (count($matches) === 0) return false;
|
||||
|
||||
$valid &= $matches[0] === $date;
|
||||
$parts = explode('-', $date);
|
||||
$valid &= checkdate((int)$parts[1], (int)$parts[2], (int)$parts[0]);
|
||||
|
||||
return (bool)$valid;
|
||||
}
|
||||
|
||||
private function checkValidSet(string $setspec): bool
|
||||
{
|
||||
// Implement
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Implement limit for cumulative array
|
||||
* @throws InvalidTokenException
|
||||
* @return string[]
|
||||
*/
|
||||
private function getIdentifiers(?string $set, ?string $from, ?string $until,): array
|
||||
{
|
||||
$identifiers = [];
|
||||
$decodedToken = null;
|
||||
$offset = 0;
|
||||
$size = 0;
|
||||
$limit = (int)$_ENV['OAI_LIMIT'];
|
||||
$token = $this->request->get('resumptionToken');
|
||||
|
||||
if ($token !== null) {
|
||||
$decodedToken = ResumptionToken::decode($token);
|
||||
$offset = $decodedToken->cursor;
|
||||
}
|
||||
|
||||
if ($set === null && $this->metadataFormat === 'oai_dc') {
|
||||
// Get resources and size (total number)
|
||||
|
||||
$this->resumptionToken = new ResumptionToken(
|
||||
$offset + $limit,
|
||||
$size,
|
||||
set: $set,
|
||||
metadataFormat: $this->metadataFormat,
|
||||
from: $from,
|
||||
until: $until,
|
||||
);
|
||||
|
||||
return $identifiers;
|
||||
}
|
||||
|
||||
return $identifiers;
|
||||
}
|
||||
|
||||
private function createXML(
|
||||
array $identifiers,
|
||||
string $metadataFormat,
|
||||
): string
|
||||
{
|
||||
$xml = '';
|
||||
|
||||
foreach ($identifiers as $id) {
|
||||
$this->record = match ($metadataFormat) {
|
||||
'oai_dc' => new RecordOaiDc($id['identifier'], verb: 'ListRecords'),
|
||||
'oai_datacite' => new RecordOaiDataCite($id['identifier'], verb: 'ListRecords'),
|
||||
default => new RecordOaiDc($id['identifier'], verb: 'ListRecords'),
|
||||
};
|
||||
$xml .= "\n" . $this->record->toXML();
|
||||
}
|
||||
|
||||
if ($this->resumptionToken->cursor < $this->resumptionToken->size) {
|
||||
$xml .= "\n{$this->resumptionToken->toXML()}";
|
||||
}
|
||||
|
||||
return $xml;
|
||||
}
|
||||
|
||||
private function hasErrors(?string $from, ?string $until, ?string $set): OaiError|false
|
||||
{
|
||||
$error = false;
|
||||
|
||||
if ($from !== null && ! $this->checkGranularity($from) ||
|
||||
$until !== null && ! $this->checkGranularity($until)
|
||||
) {
|
||||
$error = new OaiError('badArgument', "The argument value for 'from' and/or 'until' is invalid.");
|
||||
}
|
||||
|
||||
if (($until !== null && $from !== null) && ($from > $until)) {
|
||||
$error = new OaiError('noRecordsMatch', 'No records were found in repository.');
|
||||
}
|
||||
|
||||
if ($set !== null && ! $this->checkValidSet($set)) {
|
||||
$error = new OaiError('badArgument', "The set '$set' does not exist in this repository.");
|
||||
}
|
||||
|
||||
return $error;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user