diff --git a/config/oai_settings.yaml b/config/oai_settings.yaml new file mode 100644 index 0000000..09de70b --- /dev/null +++ b/config/oai_settings.yaml @@ -0,0 +1,5 @@ +parameters: + oai.repository_name: DASI OAI-PMH repository + oai.base_url: http://localhost/dasi/oai + oai.admin_email: info@dasiproject.eu + oai.xsl_path: 'bundles/oaisymfony/oai2.xsl' \ No newline at end of file diff --git a/public/oai2.xsl b/public/oai2.xsl new file mode 100644 index 0000000..c231307 --- /dev/null +++ b/public/oai2.xsl @@ -0,0 +1,659 @@ + + + + + + + + + + + + + + + +td.value { + vertical-align: top; + padding-left: 1em; + padding: 3px; +} +td.key { + background-color: #e0e0ff; + padding: 3px; + text-align: right; + border: 1px solid #c0c0c0; + white-space: nowrap; + font-weight: bold; + vertical-align: top; +} +.dcdata td.key { + background-color: #ffffe0; +} +body { + margin: 1em 2em 1em 2em; +} +h1, h2, h3 { + font-family: sans-serif; + clear: left; +} +h1 { + padding-bottom: 4px; + margin-bottom: 0px; +} +h2 { + margin-bottom: 0.5em; +} +h3 { + margin-bottom: 0.3em; + font-size: medium; +} +.link { + border: 1px outset #88f; + background-color: #c0c0ff; + padding: 1px 4px 1px 4px; + font-size: 80%; + text-decoration: none; + font-weight: bold; + font-family: sans-serif; + color: black; +} +.link:hover { + color: red; +} +.link:active { + color: red; + border: 1px inset #88f; + background-color: #a0a0df; +} +.oaiRecord, .oaiRecordTitle { + background-color: #f0f0ff; + border-style: solid; + border-color: #d0d0d0; +} +h2.oaiRecordTitle { + background-color: #e0e0ff; + font-size: medium; + font-weight: bold; + padding: 10px; + border-width: 2px 2px 0px 2px; + margin: 0px; +} +.oaiRecord { + margin-bottom: 3em; + border-width: 2px; + padding: 10px; +} + +.results { + margin-bottom: 1.5em; +} +ul.quicklinks { + margin-top: 2px; + padding: 4px; + text-align: left; + border-bottom: 2px solid #ccc; + border-top: 2px solid #ccc; + clear: left; +} +ul.quicklinks li { + font-size: 80%; + display: inline; + list-stlye: none; + font-family: sans-serif; +} +p.intro { + font-size: 80%; +} + + + + + + + + + OAI 2.0 Request Results + + + +

OAI 2.0 Request Results

+ +

You are viewing an HTML version of the XML OAI response. To see the underlying XML use your web browsers view source option. More information about this XSLT is at the bottom of the page.

+ + +

About the XSLT

+

An XSLT file has converted the OAI-PMH 2.0 responses into XHTML which looks nice in a browser which supports XSLT such as Mozilla, Firebird and Internet Explorer. The XSLT file was created by Christopher Gutteridge at the University of Southampton as part of the GNU EPrints system, and is freely redistributable under the GPL.

If you want to use the XSL file on your own OAI interface you may but due to the way XSLT works you must install the XSL file on the same server as the OAI script, you can't just link to this copy.

For more information or to download the XSL file please see the OAI to XHTML XSLT homepage.

+ + + +
+ + + + + + + + + + + + +
Datestamp of response
Request URL
+ + + +

OAI Error(s)

+

The request could not be completed due to the following error or errors.

+
+ +
+
+ +

Request was of type .

+
+ + + + + + +
+
+
+
+ + + + + + + + +
Error Code
+

+
+ + + + + + + + + + + + + + + + + + +
Repository Name
Base URL
Protocol Version
Earliest Datestamp
Deleted Record Policy
Granularity
+ + +
+ + + Admin Email + + + + + + +

Unsupported Description Type

+

The XSL currently does not support this type of description.

+
+ +
+
+ + + + + +

OAI-Identifier

+ + + + + + + + + +
Scheme
Repository Identifier
Delimiter
Sample OAI Identifier
+
+ + + + + +

EPrints Description

+ +

Content

+ +
+ +

Submission Policy

+ +
+

Metadata Policy

+ +

Data Policy

+ + +
+ + + +

+
+ +
+
+
+ + +

Comment

+
+
+ + + + + +

Friends

+
    + +
+
+ + +
  • + +Identify
  • +
    + + + + + +

    Branding

    + + +
    + + +

    Icon

    + + + {br:title} + + + {br:title} + + +
    + + +

    Metadata Rendering Rule

    + + + + + + + +
    URL
    Namespace
    Mime Type
    +
    + + + + + + +

    Gateway Information

    + + + + + + + + + + + + + + +
    Source
    Description
    URL
    Notes
    +
    + + + Admin + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Set

    + + + + +
    setName
    +
    + + + + + + +

    This is a list of metadata formats available for the record "". Use these links to view the metadata:

    +
    + +

    This is a list of metadata formats available from this archive.

    +
    +
    + +
    + + +

    Metadata Format

    + + + + + + + +
    metadataPrefix
    metadataNamespace
    schema
    +
    + + + + + + + + +

    OAI Record:

    +
    + + + +
    +
    + + +

    OAI Record Header

    + + + + + + +
    OAI Identifier + + oai_dc + formats +
    Datestamp
    + +

    This record has been deleted.

    +
    +
    + + + +

    "about" part of record container not supported by the XSL

    +
    + + +   + + + + + + + + + + setSpec + + Identifiers + Records + + + + + + + + +

    There are more results.

    + + + +
    resumptionToken: + +Resume
    +
    + + + + +

    Unknown Metadata Format

    +
    + +
    +
    + + + + +
    +

    Dublin Core Metadata (oai_dc)

    + + +
    +
    +
    + + +Title + + +Author or Creator + + +Subject and Keywords + + +Description + + +Publisher + + +Other Contributor + + +Date + + +Resource Type + + +Format + + +Resource Identifier + + +Source + + +Language + + +Relation + + + + + URL + URL not shown as it is very long. + + + + + + + + + + + + + +Coverage + + +Rights Management + + + + +
    + <></> +
    +
    + + + + + ="" + + + +.xmlSource { + font-size: 70%; + border: solid #c0c0a0 1px; + background-color: #ffffe0; + padding: 2em 2em 2em 0em; +} +.xmlBlock { + padding-left: 2em; +} +.xmlTagName { + color: #800000; + font-weight: bold; +} +.xmlAttrName { + font-weight: bold; +} +.xmlAttrValue { + color: #0000c0; +} + + +
    + diff --git a/src/Controller/OaiController.php b/src/Controller/OaiController.php index 0b073ad..7de40e6 100644 --- a/src/Controller/OaiController.php +++ b/src/Controller/OaiController.php @@ -7,6 +7,8 @@ namespace OaiSymfony\Controller; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Attribute\Route; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; + use OaiSymfony\Enum\OaiVerbs; use OaiSymfony\OAI\OaiError; use OaiSymfony\OAI\Verb\{ @@ -20,8 +22,16 @@ use OaiSymfony\OAI\Verb\{ final class OaiController { - #[Route('/oai', methods: 'get')] - public function index(Request $request): Response + public function __construct( + private readonly ?ParameterBagInterface $params + ) + { + } + + #[Route('/oai', methods: 'get', name: 'oai')] + public function index( + Request $request + ): Response { $res = new Response(); $res->headers->set('Content-Type', 'text/xml'); @@ -29,7 +39,7 @@ final class OaiController $verb = $request->get('verb'); if ($query === null || $verb === null) { - $error = new OaiError('badVerb', 'The verb argument is missing'); + $error = new OaiError($this->params, 'badVerb', 'The verb argument is missing'); $res->setContent($error->toXML()); return $res; } @@ -37,7 +47,7 @@ final class OaiController $validVerb = OaiVerbs::tryFrom($verb); if (! $validVerb) { - $error = new OaiError('badVerb', "'{$verb}' is not a valid OAI-PMH verb"); + $error = new OaiError($this->params, 'badVerb', "'{$verb}' is not a valid OAI-PMH verb"); $res->setContent($error->toXML()); return $res; } @@ -51,13 +61,13 @@ final class OaiController || $validVerb === OaiVerbs::GetRecord) && ($mdPrefix === null && $resumptionToken === null) ) { - $error = new OaiError('badArgument', 'The \'metadataPrefix\' argument is missing.'); + $error = new OaiError($this->params, 'badArgument', 'The \'metadataPrefix\' argument is missing.'); $res->setContent($error->toXML()); return $res; } return match ($validVerb->value) { - 'Identify' => $this->identify($res, (new Identify)->response()), + 'Identify' => $this->identify($res, (new Identify($this->params))->response()), 'GetRecord' => $this->getRecord($request, $res), 'ListRecords' => $this->listRecords($request, $res), 'ListSets' => $this->listSets($res), @@ -76,7 +86,7 @@ final class OaiController { $identifier = $req->get('identifier'); if (! $this->checkIdentifier($identifier)) { - $error = new OaiError('idDoesNotExist', "The identifier '$identifier' is illegal."); + $error = new OaiError($this->params, 'idDoesNotExist', "The identifier '$identifier' is illegal."); $res->setContent($error->toXML()); return $res; } diff --git a/src/DependencyInjection/OaiSymfonyExtension.php b/src/DependencyInjection/OaiSymfonyExtension.php new file mode 100644 index 0000000..012954e --- /dev/null +++ b/src/DependencyInjection/OaiSymfonyExtension.php @@ -0,0 +1,20 @@ +load('oai_settings.yaml'); + } +} diff --git a/src/OAI/OaiBase.php b/src/OAI/OaiBase.php index 53aa213..f5021b6 100644 --- a/src/OAI/OaiBase.php +++ b/src/OAI/OaiBase.php @@ -7,6 +7,7 @@ namespace OaiSymfony\OAI; use \DOMDocument; use function Symfony\Component\String\b; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; /** * Creates the base XML document containing dynamically generated responses @@ -15,14 +16,17 @@ use function Symfony\Component\String\b; final class OaiBase { /** - * @param string $content The dynamically generated XML response - * @param string $nodeName The root node name to be imported + * @param ParameterBagInterface $params Config parameters + * @param string $content The dynamically generated XML response + * @param string $nodeName The root node name to be imported + * @param string|null $metadataFormat + * @return string */ - public static function create(string $content, string $nodeName, string $metadataFormat = 'oai_dc'): string + public static function create(ParameterBagInterface $params, string $content, string $nodeName, ?string $metadataFormat = 'oai_dc'): string { $main = new DOMDocument(encoding: 'UTF-8'); $main->formatOutput = true; - $xslt = $main->createProcessingInstruction('xml-stylesheet', 'type="text/xsl" href="/xslt/oai2.xsl"'); + $xslt = $main->createProcessingInstruction('xml-stylesheet', 'type="text/xsl" href="' . $params->get('oai.xsl_path') . '"'); $main->appendChild($xslt); $imported = new DOMDocument(encoding: 'UTF-8'); @@ -35,7 +39,7 @@ final class OaiBase $root->setAttribute('xsi:schemaLocation', 'http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd'); $responseDate = $main->createElement('responseDate', date("Y-m-d\TH:i:s\Z")); $root->appendChild($responseDate); - $request = $main->createElement('request', 'https://www.yourdomain.com/oai'); + $request = $main->createElement('request', $params->get('oai.base_url')); if ($nodeName !== 'error') { $request->setAttribute('verb', $nodeName); diff --git a/src/OAI/OaiError.php b/src/OAI/OaiError.php index 8259977..7a7cee8 100644 --- a/src/OAI/OaiError.php +++ b/src/OAI/OaiError.php @@ -15,6 +15,7 @@ use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Loader\AttributeLoader; use Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter; use Symfony\Component\Serializer\Attribute\SerializedName; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; final class OaiError { @@ -24,9 +25,10 @@ final class OaiError public string $description; public function __construct( - $code, - $description, - private Serializer $serializer = new Serializer() + private readonly ?ParameterBagInterface $params, + string $code, + string $description, + private ?Serializer $serializer = null, ) { $this->code = $code; @@ -63,10 +65,10 @@ final class OaiError 'xml_root_node_name' => 'error', // Don't include the XML declaration, handled by OaiBase 'encoder_ignored_node_types' => [ - \XML_PI_NODE, + \XML_PI_NODE, ], ]); - return OaiBase::create($content, 'error'); + return OaiBase::create($this->params, $content, 'error'); } } \ No newline at end of file diff --git a/src/OAI/OaiIdentify.php b/src/OAI/OaiIdentify.php index 688516a..47bc7a4 100644 --- a/src/OAI/OaiIdentify.php +++ b/src/OAI/OaiIdentify.php @@ -4,11 +4,11 @@ declare(strict_types=1); namespace OaiSymfony\OAI; -use AC\DB\Connection; use OaiSymfony\OAI\RecordOaiInterface; use Symfony\Component\Serializer\Encoder\XmlEncoder; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use Symfony\Component\Serializer\Serializer; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; /** * Serializes an Identify response @@ -16,7 +16,8 @@ use Symfony\Component\Serializer\Serializer; final class OaiIdentify implements RecordOaiInterface { public function __construct( - private Serializer $serializer = new Serializer(), + private readonly ?ParameterBagInterface $params, + private ?Serializer $serializer = null, ) { $this->serializer = new Serializer( @@ -24,6 +25,7 @@ final class OaiIdentify implements RecordOaiInterface [new XmlEncoder()] ); } + /** * This should get literal values from settings / config */ @@ -32,10 +34,10 @@ final class OaiIdentify implements RecordOaiInterface $datestamp = $this->getEarliestDatestamp(); $response = [ - 'repositoryName' => 'Your bloody repo name', - 'baseURL' => "https://www.yourdomain.com/oai", - 'protocolVersion' => 2.0, - 'adminEmail' => 'crazyadmin@yourdomain.com', + 'repositoryName' => $this->params->get('oai.repository_name'), + 'baseURL' => $this->params->get('oai.base_url'), + 'protocolVersion' => '2.0', + 'adminEmail' => $this->params->get('oai.admin_email'), 'earliestDatestamp' => $datestamp, 'deletedRecord' => 'no', 'granularity' => 'YYYY-MM-DD', @@ -48,12 +50,13 @@ final class OaiIdentify implements RecordOaiInterface 'xml_root_node_name' => 'Identify', // Don't include the XML declaration, handled by OaiBase 'encoder_ignored_node_types' => [ - \XML_PI_NODE, + \XML_PI_NODE, ], ] ); return $content; } + /** * This should return the earliest datestamp from the repo's database * considering all available OAI resources @@ -61,6 +64,6 @@ final class OaiIdentify implements RecordOaiInterface private function getEarliestDatestamp(): string { // Implement - return date('YYYY-MM-DD'); + return '[TODO] ' . date('Y-m-d'); } } diff --git a/src/OAI/Verb/Identify.php b/src/OAI/Verb/Identify.php index 63cdab7..0bc13b6 100644 --- a/src/OAI/Verb/Identify.php +++ b/src/OAI/Verb/Identify.php @@ -6,6 +6,7 @@ namespace OaiSymfony\OAI\Verb; use OaiSymfony\OAI\OaiIdentify; use OaiSymfony\OAI\OaiBase; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; /** * Identify data for the repository @@ -14,16 +15,19 @@ final class Identify { public readonly OaiIdentify $identify; - public function __construct() + public function __construct( + private readonly ?ParameterBagInterface $params + ) { - $this->identify = new OaiIdentify; + $this->identify = new OaiIdentify($this->params); } + /** * Returns the XML response */ public function response(): string { - $xml = $this->identify->toXML(); - return OaiBase::create($xml, 'Identify'); + $xml = $this->identify->toXML(); + return OaiBase::create($this->params, $xml, 'Identify'); } } diff --git a/src/OaiSymfonyBundle.php b/src/OaiSymfonyBundle.php new file mode 100644 index 0000000..e84d1c2 --- /dev/null +++ b/src/OaiSymfonyBundle.php @@ -0,0 +1,15 @@ +