Compare commits

4 Commits
main ... dasi

Author SHA1 Message Date
Matteo Gallo
3e0623f0db Configuration improvements 2026-05-08 13:20:14 +02:00
Matteo Gallo
d1b3bd32f8 Processing of the verb Identify 2026-05-07 20:31:04 +02:00
Matteo Gallo
63522577a3 Namespace update (to make it consistent with what is declared in composer.json) 2026-05-07 15:29:10 +02:00
Matteo Gallo
b9501417b0 Symfony version alignment with main application 2026-04-30 20:44:28 +02:00
27 changed files with 994 additions and 228 deletions

View File

@@ -1,18 +1,19 @@
{
"name": "cnr/oai-symfony",
"autoload" : {
"psr-4" : {
"App\\" : "src/"
"OaiSymfony\\" : "src/"
}
},
"require": {
"symfony/http-foundation": "^6.1",
"symfony/http-kernel": "^6.1",
"symfony/routing": "^6.1",
"symfony/dependency-injection": "^6.1",
"symfony/string": "^6.1",
"symfony/serializer": "^7.1",
"symfony/property-access": "^7.1",
"symfony/config": "^7.3"
"symfony/http-foundation": "^6.4",
"symfony/http-kernel": "^6.4",
"symfony/routing": "^6.4",
"symfony/dependency-injection": "^6.4",
"symfony/string": "^6.4",
"symfony/serializer": "^6.4",
"symfony/property-access": "^6.4",
"symfony/config": "^6.4"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.64",

282
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "7e0dc2a83935172b6d868c5374e35276",
"content-hash": "616ed5c2ce6b04dd0246826b3c03d7c8",
"packages": [
{
"name": "psr/container",
@@ -161,34 +161,34 @@
},
{
"name": "symfony/config",
"version": "v7.4.8",
"version": "v6.4.34",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
"reference": "2d19dde43fa2ff720b9a40763ace7226594f503b"
"reference": "ce9cb0c0d281aaf188b802d4968e42bfb60701e9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/config/zipball/2d19dde43fa2ff720b9a40763ace7226594f503b",
"reference": "2d19dde43fa2ff720b9a40763ace7226594f503b",
"url": "https://api.github.com/repos/symfony/config/zipball/ce9cb0c0d281aaf188b802d4968e42bfb60701e9",
"reference": "ce9cb0c0d281aaf188b802d4968e42bfb60701e9",
"shasum": ""
},
"require": {
"php": ">=8.2",
"php": ">=8.1",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/filesystem": "^7.1|^8.0",
"symfony/filesystem": "^5.4|^6.0|^7.0",
"symfony/polyfill-ctype": "~1.8"
},
"conflict": {
"symfony/finder": "<6.4",
"symfony/finder": "<5.4",
"symfony/service-contracts": "<2.5"
},
"require-dev": {
"symfony/event-dispatcher": "^6.4|^7.0|^8.0",
"symfony/finder": "^6.4|^7.0|^8.0",
"symfony/messenger": "^6.4|^7.0|^8.0",
"symfony/event-dispatcher": "^5.4|^6.0|^7.0",
"symfony/finder": "^5.4|^6.0|^7.0",
"symfony/messenger": "^5.4|^6.0|^7.0",
"symfony/service-contracts": "^2.5|^3",
"symfony/yaml": "^6.4|^7.0|^8.0"
"symfony/yaml": "^5.4|^6.0|^7.0"
},
"type": "library",
"autoload": {
@@ -216,7 +216,7 @@
"description": "Helps you find, load, combine, autofill and validate configuration values of any kind",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/config/tree/v7.4.8"
"source": "https://github.com/symfony/config/tree/v6.4.34"
},
"funding": [
{
@@ -236,7 +236,7 @@
"type": "tidelift"
}
],
"time": "2026-03-24T13:12:05+00:00"
"time": "2026-02-24T17:34:50+00:00"
},
{
"name": "symfony/dependency-injection",
@@ -1317,86 +1317,6 @@
],
"time": "2026-04-10T17:25:58+00:00"
},
{
"name": "symfony/polyfill-php84",
"version": "v1.37.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php84.git",
"reference": "88486db2c389b290bf87ff1de7ebc1e13e42bb06"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/88486db2c389b290bf87ff1de7ebc1e13e42bb06",
"reference": "88486db2c389b290bf87ff1de7ebc1e13e42bb06",
"shasum": ""
},
"require": {
"php": ">=7.2"
},
"type": "library",
"extra": {
"thanks": {
"url": "https://github.com/symfony/polyfill",
"name": "symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php84\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php84/tree/v1.37.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2026-04-10T18:47:49+00:00"
},
{
"name": "symfony/polyfill-php85",
"version": "v1.37.0",
@@ -1479,25 +1399,25 @@
},
{
"name": "symfony/property-access",
"version": "v7.4.8",
"version": "v6.4.32",
"source": {
"type": "git",
"url": "https://github.com/symfony/property-access.git",
"reference": "b7dad9dae8b8a47ef7ecc76c8569e7d8c7d90cfc"
"reference": "6dfa655ac9e9860c05cabb287f34da86b18c237e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/property-access/zipball/b7dad9dae8b8a47ef7ecc76c8569e7d8c7d90cfc",
"reference": "b7dad9dae8b8a47ef7ecc76c8569e7d8c7d90cfc",
"url": "https://api.github.com/repos/symfony/property-access/zipball/6dfa655ac9e9860c05cabb287f34da86b18c237e",
"reference": "6dfa655ac9e9860c05cabb287f34da86b18c237e",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/property-info": "^6.4.32|~7.3.10|^7.4.4|^8.0.4"
"php": ">=8.1",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/property-info": "^6.4.32|~7.3.10|^7.4.4"
},
"require-dev": {
"symfony/cache": "^6.4|^7.0|^8.0",
"symfony/var-exporter": "^6.4.1|^7.0.1|^8.0"
"symfony/cache": "^5.4|^6.0|^7.0"
},
"type": "library",
"autoload": {
@@ -1536,7 +1456,7 @@
"reflection"
],
"support": {
"source": "https://github.com/symfony/property-access/tree/v7.4.8"
"source": "https://github.com/symfony/property-access/tree/v6.4.32"
},
"funding": [
{
@@ -1556,7 +1476,7 @@
"type": "tidelift"
}
],
"time": "2026-03-24T13:12:05+00:00"
"time": "2026-01-05T08:25:17+00:00"
},
{
"name": "symfony/property-info",
@@ -1737,59 +1657,57 @@
},
{
"name": "symfony/serializer",
"version": "v7.4.8",
"version": "v6.4.36",
"source": {
"type": "git",
"url": "https://github.com/symfony/serializer.git",
"reference": "006fd51717addf2df2bd1a64dafef6b7fab6b455"
"reference": "90e4e0187dca57331ea301506545aa26895b7787"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/serializer/zipball/006fd51717addf2df2bd1a64dafef6b7fab6b455",
"reference": "006fd51717addf2df2bd1a64dafef6b7fab6b455",
"url": "https://api.github.com/repos/symfony/serializer/zipball/90e4e0187dca57331ea301506545aa26895b7787",
"reference": "90e4e0187dca57331ea301506545aa26895b7787",
"shasum": ""
},
"require": {
"php": ">=8.2",
"php": ">=8.1",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-php84": "^1.30"
"symfony/polyfill-ctype": "~1.8"
},
"conflict": {
"phpdocumentor/reflection-docblock": "<5.2|>=7",
"phpdocumentor/type-resolver": "<1.5.1",
"symfony/dependency-injection": "<6.4",
"symfony/property-access": "<6.4",
"symfony/property-info": "<6.4",
"symfony/type-info": "<7.2.5",
"symfony/uid": "<6.4",
"doctrine/annotations": "<1.12",
"phpdocumentor/reflection-docblock": "<3.2.2",
"phpdocumentor/type-resolver": "<1.4.0",
"symfony/dependency-injection": "<5.4",
"symfony/property-access": "<5.4",
"symfony/property-info": "<5.4.24|>=6,<6.2.11",
"symfony/uid": "<5.4",
"symfony/validator": "<6.4",
"symfony/yaml": "<6.4"
"symfony/yaml": "<5.4"
},
"require-dev": {
"phpdocumentor/reflection-docblock": "^5.2|^6.0",
"phpstan/phpdoc-parser": "^1.0|^2.0",
"doctrine/annotations": "^1.12|^2",
"phpdocumentor/reflection-docblock": "^3.2|^4.0|^5.0",
"seld/jsonlint": "^1.10",
"symfony/cache": "^6.4|^7.0|^8.0",
"symfony/config": "^6.4|^7.0|^8.0",
"symfony/console": "^6.4|^7.0|^8.0",
"symfony/dependency-injection": "^7.2|^8.0",
"symfony/error-handler": "^6.4|^7.0|^8.0",
"symfony/filesystem": "^6.4|^7.0|^8.0",
"symfony/form": "^6.4|^7.0|^8.0",
"symfony/http-foundation": "^6.4|^7.0|^8.0",
"symfony/http-kernel": "^6.4|^7.0|^8.0",
"symfony/messenger": "^6.4|^7.0|^8.0",
"symfony/mime": "^6.4|^7.0|^8.0",
"symfony/property-access": "^6.4|^7.0|^8.0",
"symfony/property-info": "^6.4|^7.0|^8.0",
"symfony/cache": "^5.4|^6.0|^7.0",
"symfony/config": "^5.4|^6.0|^7.0",
"symfony/console": "^5.4|^6.0|^7.0",
"symfony/dependency-injection": "^5.4|^6.0|^7.0",
"symfony/error-handler": "^5.4|^6.0|^7.0",
"symfony/filesystem": "^5.4|^6.0|^7.0",
"symfony/form": "^5.4|^6.0|^7.0",
"symfony/http-foundation": "^5.4|^6.0|^7.0",
"symfony/http-kernel": "^5.4|^6.0|^7.0",
"symfony/messenger": "^5.4|^6.0|^7.0",
"symfony/mime": "^5.4|^6.0|^7.0",
"symfony/property-access": "^5.4.26|^6.3|^7.0",
"symfony/property-info": "^5.4.24|^6.2.11|^7.0",
"symfony/translation-contracts": "^2.5|^3",
"symfony/type-info": "^7.2.5|^8.0",
"symfony/uid": "^6.4|^7.0|^8.0",
"symfony/validator": "^6.4|^7.0|^8.0",
"symfony/var-dumper": "^6.4|^7.0|^8.0",
"symfony/var-exporter": "^6.4|^7.0|^8.0",
"symfony/yaml": "^6.4|^7.0|^8.0"
"symfony/uid": "^5.4|^6.0|^7.0",
"symfony/validator": "^6.4|^7.0",
"symfony/var-dumper": "^5.4|^6.0|^7.0",
"symfony/var-exporter": "^5.4|^6.0|^7.0",
"symfony/yaml": "^5.4|^6.0|^7.0"
},
"type": "library",
"autoload": {
@@ -1817,7 +1735,7 @@
"description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/serializer/tree/v7.4.8"
"source": "https://github.com/symfony/serializer/tree/v6.4.36"
},
"funding": [
{
@@ -1837,7 +1755,7 @@
"type": "tidelift"
}
],
"time": "2026-03-30T21:34:42+00:00"
"time": "2026-03-30T15:37:17+00:00"
},
{
"name": "symfony/service-contracts",
@@ -5493,6 +5411,86 @@
],
"time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/polyfill-php84",
"version": "v1.37.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php84.git",
"reference": "88486db2c389b290bf87ff1de7ebc1e13e42bb06"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/88486db2c389b290bf87ff1de7ebc1e13e42bb06",
"reference": "88486db2c389b290bf87ff1de7ebc1e13e42bb06",
"shasum": ""
},
"require": {
"php": ">=7.2"
},
"type": "library",
"extra": {
"thanks": {
"url": "https://github.com/symfony/polyfill",
"name": "symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php84\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php84/tree/v1.37.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2026-04-10T18:47:49+00:00"
},
{
"name": "symfony/process",
"version": "v7.4.8",

17
config/oai_settings.yaml Normal file
View File

@@ -0,0 +1,17 @@
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'
services:
_defaults:
autowire: true
autoconfigure: true
OaiSymfony\Controller\:
resource: '../src/Controller/'
tags: ['controller.service_arguments']
OaiSymfony\Routing\OaiRouteLoader:
tags: ['routing.loader']

3
config/routes.yaml Normal file
View File

@@ -0,0 +1,3 @@
oai_routes:
resource: '../src/Controller/'
type: attribute

659
public/oai2.xsl Normal file
View File

@@ -0,0 +1,659 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
XSL Transform to convert OAI 2.0 responses into XHTML
By Christopher Gutteridge, University of Southampton
v1.1
-->
<!--
Copyright (c) 2006 University of Southampton, UK. SO17 1BJ.
EPrints 3 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
EPrints 3 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with EPrints 3; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-->
<!--
All the elements really needed for EPrints are done but if
you want to use this XSL for other OAI archive you may want
to make some minor changes or additions.
Not Done
The 'about' section of 'record'
The 'compession' part of 'identify'
The optional attributes of 'resumptionToken'
The optional 'setDescription' container of 'set'
All the links just link to oai_dc versions of records.
-->
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:oai="http://www.openarchives.org/OAI/2.0/"
>
<xsl:output method="html"/>
<xsl:template name="style">
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%;
}
<xsl:call-template name='xmlstyle' />
</xsl:template>
<xsl:variable name='identifier' select="substring-before(concat(substring-after(/oai:OAI-PMH/oai:request,'identifier='),'&amp;'),'&amp;')" />
<xsl:template match="/">
<html>
<head>
<title>OAI 2.0 Request Results</title>
<style><xsl:call-template name="style"/></style>
</head>
<body>
<h1>OAI 2.0 Request Results</h1>
<xsl:call-template name="quicklinks"/>
<p class="intro">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 <a href="#moreinfo">bottom of the page</a>.</p>
<xsl:apply-templates select="/oai:OAI-PMH" />
<xsl:call-template name="quicklinks"/>
<h2><a name="moreinfo">About the XSLT</a></h2>
<p>An XSLT file has converted the <a href="http://www.openarchives.org">OAI-PMH 2.0</a> 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 <a href="http://www.ecs.soton.ac.uk/people/cjg">Christopher Gutteridge</a> at the University of Southampton as part of the <a href="http://www.eprints.org/software/">GNU EPrints system</a>, and is freely redistributable under the <a href="http://www.gnu.org">GPL</a>.</p><p>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.</p><p>For more information or to download the XSL file please see the <a href="http://software.eprints.org/xslt.php">OAI to XHTML XSLT homepage</a>.</p>
</body>
</html>
</xsl:template>
<xsl:template name="quicklinks">
<ul class="quicklinks">
<li><a href="?verb=Identify">Identify</a> | </li>
<li><a href="?verb=ListRecords&amp;metadataPrefix=oai_dc">ListRecords</a> | </li>
<li><a href="?verb=ListSets">ListSets</a> | </li>
<li><a href="?verb=ListMetadataFormats">ListMetadataFormats</a> | </li>
<li><a href="?verb=ListIdentifiers&amp;metadataPrefix=oai_dc">ListIdentifiers</a></li>
</ul>
</xsl:template>
<xsl:template match="/oai:OAI-PMH">
<table class="values">
<tr><td class="key">Datestamp of response</td>
<td class="value"><xsl:value-of select="oai:responseDate"/></td></tr>
<tr><td class="key">Request URL</td>
<td class="value"><xsl:value-of select="oai:request"/></td></tr>
</table>
<!-- verb: [<xsl:value-of select="oai:request/@verb" />]<br /> -->
<xsl:choose>
<xsl:when test="oai:error">
<h2>OAI Error(s)</h2>
<p>The request could not be completed due to the following error or errors.</p>
<div class="results">
<xsl:apply-templates select="oai:error"/>
</div>
</xsl:when>
<xsl:otherwise>
<p>Request was of type <xsl:value-of select="oai:request/@verb"/>.</p>
<div class="results">
<xsl:apply-templates select="oai:Identify" />
<xsl:apply-templates select="oai:GetRecord"/>
<xsl:apply-templates select="oai:ListRecords"/>
<xsl:apply-templates select="oai:ListSets"/>
<xsl:apply-templates select="oai:ListMetadataFormats"/>
<xsl:apply-templates select="oai:ListIdentifiers"/>
</div>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- ERROR -->
<xsl:template match="/oai:OAI-PMH/oai:error">
<table class="values">
<tr><td class="key">Error Code</td>
<td class="value"><xsl:value-of select="@code"/></td></tr>
</table>
<p class="error"><xsl:value-of select="." /></p>
</xsl:template>
<!-- IDENTIFY -->
<xsl:template match="/oai:OAI-PMH/oai:Identify">
<table class="values">
<tr><td class="key">Repository Name</td>
<td class="value"><xsl:value-of select="oai:repositoryName"/></td></tr>
<tr><td class="key">Base URL</td>
<td class="value"><xsl:value-of select="oai:baseURL"/></td></tr>
<tr><td class="key">Protocol Version</td>
<td class="value"><xsl:value-of select="oai:protocolVersion"/></td></tr>
<tr><td class="key">Earliest Datestamp</td>
<td class="value"><xsl:value-of select="oai:earliestDatestamp"/></td></tr>
<tr><td class="key">Deleted Record Policy</td>
<td class="value"><xsl:value-of select="oai:deletedRecord"/></td></tr>
<tr><td class="key">Granularity</td>
<td class="value"><xsl:value-of select="oai:granularity"/></td></tr>
<xsl:apply-templates select="oai:adminEmail"/>
</table>
<xsl:apply-templates select="oai:description"/>
<!--no warning about unsupported descriptions -->
</xsl:template>
<xsl:template match="/oai:OAI-PMH/oai:Identify/oai:adminEmail">
<tr><td class="key">Admin Email</td>
<td class="value"><xsl:value-of select="."/></td></tr>
</xsl:template>
<!--
Identify / Unsupported Description
-->
<xsl:template match="oai:description/*" priority="-100">
<h2>Unsupported Description Type</h2>
<p>The XSL currently does not support this type of description.</p>
<div class="xmlSource">
<xsl:apply-templates select="." mode='xmlMarkup' />
</div>
</xsl:template>
<!--
Identify / OAI-Identifier
-->
<xsl:template match="id:oai-identifier" xmlns:id="http://www.openarchives.org/OAI/2.0/oai-identifier">
<h2>OAI-Identifier</h2>
<table class="values">
<tr><td class="key">Scheme</td>
<td class="value"><xsl:value-of select="id:scheme"/></td></tr>
<tr><td class="key">Repository Identifier</td>
<td class="value"><xsl:value-of select="id:repositoryIdentifier"/></td></tr>
<tr><td class="key">Delimiter</td>
<td class="value"><xsl:value-of select="id:delimiter"/></td></tr>
<tr><td class="key">Sample OAI Identifier</td>
<td class="value"><xsl:value-of select="id:sampleIdentifier"/></td></tr>
</table>
</xsl:template>
<!--
Identify / EPrints
-->
<xsl:template match="ep:eprints" xmlns:ep="http://www.openarchives.org/OAI/1.1/eprints">
<h2>EPrints Description</h2>
<xsl:if test="ep:content">
<h3>Content</h3>
<xsl:apply-templates select="ep:content"/>
</xsl:if>
<xsl:if test="ep:submissionPolicy">
<h3>Submission Policy</h3>
<xsl:apply-templates select="ep:submissionPolicy"/>
</xsl:if>
<h3>Metadata Policy</h3>
<xsl:apply-templates select="ep:metadataPolicy"/>
<h3>Data Policy</h3>
<xsl:apply-templates select="ep:dataPolicy"/>
<xsl:apply-templates select="ep:comment"/>
</xsl:template>
<xsl:template match="ep:content|ep:dataPolicy|ep:metadataPolicy|ep:submissionPolicy" xmlns:ep="http://www.openarchives.org/OAI/1.1/eprints">
<xsl:if test="ep:text">
<p><xsl:value-of select="ep:text" /></p>
</xsl:if>
<xsl:if test="ep:URL">
<div><a href="{ep:URL}"><xsl:value-of select="ep:URL" /></a></div>
</xsl:if>
</xsl:template>
<xsl:template match="ep:comment" xmlns:ep="http://www.openarchives.org/OAI/1.1/eprints">
<h3>Comment</h3>
<div><xsl:value-of select="."/></div>
</xsl:template>
<!--
Identify / Friends
-->
<xsl:template match="fr:friends" xmlns:fr="http://www.openarchives.org/OAI/2.0/friends/">
<h2>Friends</h2>
<ul>
<xsl:apply-templates select="fr:baseURL"/>
</ul>
</xsl:template>
<xsl:template match="fr:baseURL" xmlns:fr="http://www.openarchives.org/OAI/2.0/friends/">
<li><xsl:value-of select="."/>
<xsl:text> </xsl:text>
<a class="link" href="{.}?verb=Identify">Identify</a></li>
</xsl:template>
<!--
Identify / Branding
-->
<xsl:template match="br:branding" xmlns:br="http://www.openarchives.org/OAI/2.0/branding/">
<h2>Branding</h2>
<xsl:apply-templates select="br:collectionIcon"/>
<xsl:apply-templates select="br:metadataRendering"/>
</xsl:template>
<xsl:template match="br:collectionIcon" xmlns:br="http://www.openarchives.org/OAI/2.0/branding/">
<h3>Icon</h3>
<xsl:choose>
<xsl:when test="link!=''">
<a href="{br:link}"><img src="{br:url}" alt="{br:title}" width="{br:width}" height="{br:height}" border="0" /></a>
</xsl:when>
<xsl:otherwise>
<img src="{br:url}" alt="{br:title}" width="{br:width}" height="{br:height}" border="0" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="br:metadataRendering" xmlns:br="http://www.openarchives.org/OAI/2.0/branding/">
<h3>Metadata Rendering Rule</h3>
<table class="values">
<tr><td class="key">URL</td>
<td class="value"><xsl:value-of select="."/></td></tr>
<tr><td class="key">Namespace</td>
<td class="value"><xsl:value-of select="@metadataNamespace"/></td></tr>
<tr><td class="key">Mime Type</td>
<td class="value"><xsl:value-of select="@mimetype"/></td></tr>
</table>
</xsl:template>
<!--
Identify / Gateway
-->
<xsl:template match="gw:gateway" xmlns:gw="http://www.openarchives.org/OAI/2.0/gateway/x">
<h2>Gateway Information</h2>
<table class="values">
<tr><td class="key">Source</td>
<td class="value"><xsl:value-of select="gw:source"/></td></tr>
<tr><td class="key">Description</td>
<td class="value"><xsl:value-of select="gw:gatewayDescription"/></td></tr>
<xsl:apply-templates select="gw:gatewayAdmin"/>
<xsl:if test="gw:gatewayURL">
<tr><td class="key">URL</td>
<td class="value"><xsl:value-of select="gw:gatewayURL"/></td></tr>
</xsl:if>
<xsl:if test="gw:gatewayNotes">
<tr><td class="key">Notes</td>
<td class="value"><xsl:value-of select="gw:gatewayNotes"/></td></tr>
</xsl:if>
</table>
</xsl:template>
<xsl:template match="gw:gatewayAdmin" xmlns:gw="http://www.openarchives.org/OAI/2.0/gateway/">
<tr><td class="key">Admin</td>
<td class="value"><xsl:value-of select="."/></td></tr>
</xsl:template>
<!-- GetRecord -->
<xsl:template match="oai:GetRecord">
<xsl:apply-templates select="oai:record" />
</xsl:template>
<!-- ListRecords -->
<xsl:template match="oai:ListRecords">
<xsl:apply-templates select="oai:record" />
<xsl:apply-templates select="oai:resumptionToken" />
</xsl:template>
<!-- ListIdentifiers -->
<xsl:template match="oai:ListIdentifiers">
<xsl:apply-templates select="oai:header" />
<xsl:apply-templates select="oai:resumptionToken" />
</xsl:template>
<!-- ListSets -->
<xsl:template match="oai:ListSets">
<xsl:apply-templates select="oai:set" />
<xsl:apply-templates select="oai:resumptionToken" />
</xsl:template>
<xsl:template match="oai:set">
<h2>Set</h2>
<table class="values">
<tr><td class="key">setName</td>
<td class="value"><xsl:value-of select="oai:setName"/></td></tr>
<xsl:apply-templates select="oai:setSpec" />
</table>
</xsl:template>
<!-- ListMetadataFormats -->
<xsl:template match="oai:ListMetadataFormats">
<xsl:choose>
<xsl:when test="$identifier">
<p>This is a list of metadata formats available for the record "<xsl:value-of select='$identifier' />". Use these links to view the metadata: <xsl:apply-templates select="oai:metadataFormat/oai:metadataPrefix" /></p>
</xsl:when>
<xsl:otherwise>
<p>This is a list of metadata formats available from this archive.</p>
</xsl:otherwise>
</xsl:choose>
<xsl:apply-templates select="oai:metadataFormat" />
</xsl:template>
<xsl:template match="oai:metadataFormat">
<h2>Metadata Format</h2>
<table class="values">
<tr><td class="key">metadataPrefix</td>
<td class="value"><a class="link" href="?verb=ListRecords&amp;metadataPrefix={oai:metadataPrefix}"><xsl:value-of select="oai:metadataPrefix"/></a></td></tr>
<tr><td class="key">metadataNamespace</td>
<td class="value"><xsl:value-of select="oai:metadataNamespace"/></td></tr>
<tr><td class="key">schema</td>
<td class="value"><a href="{oai:schema}"><xsl:value-of select="oai:schema"/></a></td></tr>
</table>
</xsl:template>
<xsl:template match="oai:metadataPrefix">
<xsl:text> </xsl:text><a class="link" href="?verb=GetRecord&amp;metadataPrefix={.}&amp;identifier={$identifier}"><xsl:value-of select='.' /></a>
</xsl:template>
<!-- record object -->
<xsl:template match="oai:record">
<h2 class="oaiRecordTitle">OAI Record: <xsl:value-of select="oai:header/oai:identifier"/></h2>
<div class="oaiRecord">
<xsl:apply-templates select="oai:header" />
<xsl:apply-templates select="oai:metadata" />
<xsl:apply-templates select="oai:about" />
</div>
</xsl:template>
<xsl:template match="oai:header">
<h3>OAI Record Header</h3>
<table class="values">
<tr><td class="key">OAI Identifier</td>
<td class="value">
<xsl:value-of select="oai:identifier"/>
<xsl:text> </xsl:text><a class="link" href="?verb=GetRecord&amp;metadataPrefix=oai_dc&amp;identifier={oai:identifier}">oai_dc</a>
<xsl:text> </xsl:text><a class="link" href="?verb=ListMetadataFormats&amp;identifier={oai:identifier}">formats</a>
</td></tr>
<tr><td class="key">Datestamp</td>
<td class="value"><xsl:value-of select="oai:datestamp"/></td></tr>
<xsl:apply-templates select="oai:setSpec" />
</table>
<xsl:if test="@status='deleted'">
<p>This record has been deleted.</p>
</xsl:if>
</xsl:template>
<xsl:template match="oai:about">
<p>"about" part of record container not supported by the XSL</p>
</xsl:template>
<xsl:template match="oai:metadata">
&#160;
<div class="metadata">
<xsl:apply-templates select="*" />
</div>
</xsl:template>
<!-- oai setSpec object -->
<xsl:template match="oai:setSpec">
<tr><td class="key">setSpec</td>
<td class="value"><xsl:value-of select="."/>
<xsl:text> </xsl:text><a class="link" href="?verb=ListIdentifiers&amp;metadataPrefix=oai_dc&amp;set={.}">Identifiers</a>
<xsl:text> </xsl:text><a class="link" href="?verb=ListRecords&amp;metadataPrefix=oai_dc&amp;set={.}">Records</a>
</td></tr>
</xsl:template>
<!-- oai resumptionToken -->
<xsl:template match="oai:resumptionToken">
<p>There are more results.</p>
<table class="values">
<tr><td class="key">resumptionToken:</td>
<td class="value"><xsl:value-of select="."/>
<xsl:text> </xsl:text>
<a class="link" href="?verb={/oai:OAI-PMH/oai:request/@verb}&amp;resumptionToken={.}">Resume</a></td></tr>
</table>
</xsl:template>
<!-- unknown metadata format -->
<xsl:template match="oai:metadata/*" priority='-100'>
<h3>Unknown Metadata Format</h3>
<div class="xmlSource">
<xsl:apply-templates select="." mode='xmlMarkup' />
</div>
</xsl:template>
<!-- oai_dc record -->
<xsl:template match="oai_dc:dc" xmlns:oai_dc="http://www.openarchives.org/OAI/2.0/oai_dc/" >
<div class="dcdata">
<h3>Dublin Core Metadata (oai_dc)</h3>
<table class="dcdata">
<xsl:apply-templates select="*" />
</table>
</div>
</xsl:template>
<xsl:template match="dc:title" xmlns:dc="http://purl.org/dc/elements/1.1/">
<tr><td class="key">Title</td><td class="value"><xsl:value-of select="."/></td></tr></xsl:template>
<xsl:template match="dc:creator" xmlns:dc="http://purl.org/dc/elements/1.1/">
<tr><td class="key">Author or Creator</td><td class="value"><xsl:value-of select="."/></td></tr></xsl:template>
<xsl:template match="dc:subject" xmlns:dc="http://purl.org/dc/elements/1.1/">
<tr><td class="key">Subject and Keywords</td><td class="value"><xsl:value-of select="."/></td></tr></xsl:template>
<xsl:template match="dc:description" xmlns:dc="http://purl.org/dc/elements/1.1/">
<tr><td class="key">Description</td><td class="value"><xsl:value-of select="."/></td></tr></xsl:template>
<xsl:template match="dc:publisher" xmlns:dc="http://purl.org/dc/elements/1.1/">
<tr><td class="key">Publisher</td><td class="value"><xsl:value-of select="."/></td></tr></xsl:template>
<xsl:template match="dc:contributor" xmlns:dc="http://purl.org/dc/elements/1.1/">
<tr><td class="key">Other Contributor</td><td class="value"><xsl:value-of select="."/></td></tr></xsl:template>
<xsl:template match="dc:date" xmlns:dc="http://purl.org/dc/elements/1.1/">
<tr><td class="key">Date</td><td class="value"><xsl:value-of select="."/></td></tr></xsl:template>
<xsl:template match="dc:type" xmlns:dc="http://purl.org/dc/elements/1.1/">
<tr><td class="key">Resource Type</td><td class="value"><xsl:value-of select="."/></td></tr></xsl:template>
<xsl:template match="dc:format" xmlns:dc="http://purl.org/dc/elements/1.1/">
<tr><td class="key">Format</td><td class="value"><xsl:value-of select="."/></td></tr></xsl:template>
<xsl:template match="dc:identifier" xmlns:dc="http://purl.org/dc/elements/1.1/">
<tr><td class="key">Resource Identifier</td><td class="value"><xsl:value-of select="."/></td></tr></xsl:template>
<xsl:template match="dc:source" xmlns:dc="http://purl.org/dc/elements/1.1/">
<tr><td class="key">Source</td><td class="value"><xsl:value-of select="."/></td></tr></xsl:template>
<xsl:template match="dc:language" xmlns:dc="http://purl.org/dc/elements/1.1/">
<tr><td class="key">Language</td><td class="value"><xsl:value-of select="."/></td></tr></xsl:template>
<xsl:template match="dc:relation" xmlns:dc="http://purl.org/dc/elements/1.1/">
<tr><td class="key">Relation</td><td class="value">
<xsl:choose>
<xsl:when test='starts-with(.,"http" )'>
<xsl:choose>
<xsl:when test='string-length(.) &gt; 50'>
<a class="link" href="{.}">URL</a>
<i> URL not shown as it is very long.</i>
</xsl:when>
<xsl:otherwise>
<a href="{.}"><xsl:value-of select="."/></a>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</td></tr></xsl:template>
<xsl:template match="dc:coverage" xmlns:dc="http://purl.org/dc/elements/1.1/">
<tr><td class="key">Coverage</td><td class="value"><xsl:value-of select="."/></td></tr></xsl:template>
<xsl:template match="dc:rights" xmlns:dc="http://purl.org/dc/elements/1.1/">
<tr><td class="key">Rights Management</td><td class="value"><xsl:value-of select="."/></td></tr></xsl:template>
<!-- XML Pretty Maker -->
<xsl:template match="node()" mode='xmlMarkup'>
<div class="xmlBlock">
&lt;<span class="xmlTagName"><xsl:value-of select='name(.)' /></span><xsl:apply-templates select="@*" mode='xmlMarkup'/>&gt;<xsl:apply-templates select="node()" mode='xmlMarkup' />&lt;/<span class="xmlTagName"><xsl:value-of select='name(.)' /></span>&gt;
</div>
</xsl:template>
<xsl:template match="text()" mode='xmlMarkup'><span class="xmlText"><xsl:value-of select='.' /></span></xsl:template>
<xsl:template match="@*" mode='xmlMarkup'>
<xsl:text> </xsl:text><span class="xmlAttrName"><xsl:value-of select='name()' /></span>="<span class="xmlAttrValue"><xsl:value-of select='.' /></span>"
</xsl:template>
<xsl:template name="xmlstyle">
.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;
}
</xsl:template>
</xsl:stylesheet>

View File

@@ -2,14 +2,16 @@
declare(strict_types=1);
namespace App\Controller;
namespace OaiSymfony\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Attribute\Route;
use App\Enum\OaiVerbs;
use App\OAI\OaiError;
use App\OAI\Verb\{
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use OaiSymfony\Enum\OaiVerbs;
use OaiSymfony\OAI\OaiError;
use OaiSymfony\OAI\Verb\{
GetRecord,
Identify,
ListRecords,
@@ -20,8 +22,16 @@ use App\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;
}

View File

@@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
namespace OaiSymfony\DependencyInjection;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
class OaiSymfonyExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container): void
{
// Carica lo YAML
$loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../../config'));
$loader->load('oai_settings.yaml');
}
}

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace App\Enum;
namespace OaiSymfony\Enum;
/**
* @todo Modify according to sets in DB or remove

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace App\Enum;
namespace OaiSymfony\Enum;
enum OaiVerbs: string
{

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace App\OAI\Exception;
namespace OaiSymfony\OAI\Exception;
final class IdentifierNotFoundException extends \Exception
{

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace App\OAI\Exception;
namespace OaiSymfony\OAI\Exception;
final class InvalidFormatException extends \Exception
{

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace App\OAI\Exception;
namespace OaiSymfony\OAI\Exception;
final class InvalidTokenException extends \Exception
{

View File

@@ -2,11 +2,12 @@
declare(strict_types=1);
namespace App\OAI;
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);

View File

@@ -2,12 +2,12 @@
declare(strict_types=1);
namespace App\OAI;
namespace OaiSymfony\OAI;
/**
* @todo Use Symfony serializer to generate XML?
*/
use App\OAI\OaiBase;
use OaiSymfony\OAI\OaiBase;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
@@ -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');
}
}

View File

@@ -2,13 +2,13 @@
declare(strict_types=1);
namespace App\OAI;
namespace OaiSymfony\OAI;
use AC\DB\Connection;
use App\OAI\RecordOaiInterface;
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');
}
}

View File

@@ -2,10 +2,10 @@
declare(strict_types=1);
namespace App\OAI;
namespace OaiSymfony\OAI;
use App\OAI\RecordOaiInterface;
use App\OAI\Exception\IdentifierNotFoundException;
use OaiSymfony\OAI\RecordOaiInterface;
use OaiSymfony\OAI\Exception\IdentifierNotFoundException;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;

View File

@@ -2,10 +2,10 @@
declare(strict_types=1);
namespace App\OAI;
namespace OaiSymfony\OAI;
use App\OAI\RecordOaiInterface;
use App\OAI\Exception\IdentifierNotFoundException;
use OaiSymfony\OAI\RecordOaiInterface;
use OaiSymfony\OAI\Exception\IdentifierNotFoundException;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace App\OAI;
namespace OaiSymfony\OAI;
interface RecordOaiInterface
{

View File

@@ -2,9 +2,9 @@
declare(strict_types=1);
namespace App\OAI;
namespace OaiSymfony\OAI;
use App\OAI\Exception\InvalidTokenException;
use OaiSymfony\OAI\Exception\InvalidTokenException;
use DateTime;
use DateTimeImmutable;
use Symfony\Component\Serializer\Attribute\Ignore;

View File

@@ -2,17 +2,17 @@
declare(strict_types=1);
namespace App\OAI\Verb;
namespace OaiSymfony\OAI\Verb;
use App\OAI\{
use OaiSymfony\OAI\{
RecordOaiDc,
RecordOaiDataCite,
RecordOaiInterface
};
use App\OAI\Exception\IdentifierNotFoundException;
use App\OAI\Exception\InvalidFormatException;
use App\OAI\OaiBase;
use App\OAI\OaiError;
use OaiSymfony\OAI\Exception\IdentifierNotFoundException;
use OaiSymfony\OAI\Exception\InvalidFormatException;
use OaiSymfony\OAI\OaiBase;
use OaiSymfony\OAI\OaiError;
/**
* Metadata for a single OAI record

View File

@@ -2,10 +2,11 @@
declare(strict_types=1);
namespace App\OAI\Verb;
namespace OaiSymfony\OAI\Verb;
use App\OAI\OaiIdentify;
use App\OAI\OaiBase;
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');
}
}

View File

@@ -2,12 +2,12 @@
declare(strict_types=1);
namespace App\OAI\Verb;
namespace OaiSymfony\OAI\Verb;
use App\OAI\ResumptionToken;
use App\OAI\Exception\InvalidTokenException;
use App\OAI\OaiBase;
use App\OAI\OaiError;
use OaiSymfony\OAI\ResumptionToken;
use OaiSymfony\OAI\Exception\InvalidTokenException;
use OaiSymfony\OAI\OaiBase;
use OaiSymfony\OAI\OaiError;
use AC\DB\Connection;
use \Symfony\Component\HttpFoundation\Request;

View File

@@ -2,10 +2,10 @@
declare(strict_types=1);
namespace App\OAI\Verb;
namespace OaiSymfony\OAI\Verb;
use App\OAI\OaiBase;
use App\OAI\OaiError;
use OaiSymfony\OAI\OaiBase;
use OaiSymfony\OAI\OaiError;
use AC\DB\Connection;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;

View File

@@ -2,17 +2,17 @@
declare(strict_types=1);
namespace App\OAI\Verb;
namespace OaiSymfony\OAI\Verb;
use App\OAI\{
use OaiSymfony\OAI\{
RecordOaiDc,
RecordOaiDataCite,
RecordOaiInterface,
ResumptionToken
};
use App\OAI\Exception\InvalidTokenException;
use App\OAI\OaiBase;
use App\OAI\OaiError;
use OaiSymfony\OAI\Exception\InvalidTokenException;
use OaiSymfony\OAI\OaiBase;
use OaiSymfony\OAI\OaiError;
use \Symfony\Component\HttpFoundation\Request;
use function \Symfony\Component\String\b;

View File

@@ -2,10 +2,10 @@
declare(strict_types=1);
namespace App\OAI\Verb;
namespace OaiSymfony\OAI\Verb;
use App\OAI\OaiBase;
use App\OAI\OaiError;
use OaiSymfony\OAI\OaiBase;
use OaiSymfony\OAI\OaiError;
use AC\DB\Connection;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;

15
src/OaiSymfonyBundle.php Normal file
View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace OaiSymfony;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class OaiSymfonyBundle extends Bundle
{
public function getPath(): string
{
return \dirname(__DIR__);
}
}

View File

@@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
namespace OaiSymfony\Routing;
use Symfony\Component\Config\Loader\Loader;
use Symfony\Component\Routing\RouteCollection;
class OaiRouteLoader extends Loader
{
private bool $isLoaded = false;
public function load(mixed $resource, string $type = null): RouteCollection
{
if ($this->isLoaded) {
throw new \RuntimeException('Do not add the OaiRouteLoader twice');
}
$routes = $this->import(__DIR__ . '/../../config/routes.yaml', 'yaml');
$this->isLoaded = true;
return $routes;
}
public function supports(mixed $resource, string $type = null): bool
{
return 'oai_symfony' === $type;
}
}