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("\n"); $xml = $xml->append("\n"); 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; } }