From 9284e8b677bc6c6bb9d998f3836955d0b0c39562 Mon Sep 17 00:00:00 2001 From: mshroom <32199029+mshroom@users.noreply.github.com> Date: Fri, 11 Sep 2026 13:32:05 +0300 Subject: [PATCH] Improve compatibility with FINNA LIDO profile v1.0 --- src/RecordManager/Base/Record/Lido.php | 75 ++++++++++++++++--- .../Base/Record/LidoTest.php | 10 +++ tests/fixtures/Base/record/lido1.xml | 2 + tests/fixtures/Base/record/lido_ns.xml | 14 +++- 4 files changed, 91 insertions(+), 10 deletions(-) diff --git a/src/RecordManager/Base/Record/Lido.php b/src/RecordManager/Base/Record/Lido.php index a8860b61..48769b6a 100644 --- a/src/RecordManager/Base/Record/Lido.php +++ b/src/RecordManager/Base/Record/Lido.php @@ -58,6 +58,20 @@ class Lido extends AbstractRecord */ protected string $lidoNs = 'http://www.lido-schema.org'; + /** + * SKOS namespace. + * + * @var string + */ + protected string $skosNs = 'http://www.w3.org/2004/02/skos/core#'; + + /** + * RDF namespace. + * + * @var string + */ + protected string $rdfNs = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'; + /** * Main event names reflecting the terminology in the particular LIDO records. * @@ -456,7 +470,11 @@ protected function postProcessRecordForIndexing(?Database $db, &$data): void protected function getISBNs(): array { $arr = []; - foreach ($this->getIdentifiersByType(['isbn'], []) as $identifier) { + $isbns = [ + ...$this->xmlDoc->allValues(path: 'lido/objectPublishedID'), + ...$this->getIdentifiersByType(['isbn'], []), + ]; + foreach ($isbns as $identifier) { if ($isbn = $this->metadataUtils->normalizeISBN($this->checkISBN((string)$identifier))) { $arr[] = $isbn; } else { @@ -492,14 +510,9 @@ protected function getTopicIDs($exclude = ['iconclass']): array { $result = []; foreach ($this->getSubjectNodes($exclude) as $subjectNode) { - foreach ($this->xmlDoc->all($subjectNode, 'subjectConcept/conceptID') as $conceptID) { - if ( - ($id = $this->xmlDoc->value($conceptID)) - && ($type = $this->xmlDoc->attr($conceptID, 'type')) - ) { - if (in_array(mb_strtolower($type, 'UTF-8'), $this->subjectConceptIDTypes)) { - $result[] = $id; - } + foreach ($this->xmlDoc->all($subjectNode, 'subjectConcept') as $concept) { + if ('' !== $id = $this->getFirstConceptIdentifier($concept, $this->subjectConceptIDTypes)) { + $result[] = $id; } } } @@ -1541,4 +1554,48 @@ protected function getThumbnailUrl(): string $urls = $this->getUrls(); return $urls[0] ?? ''; } + + /** + * Get first conceptID identifier or skos:Concept URI of a node + * + * @param array $parentNode The node that contains conceptID and skos:Concept nodes + * @param array $allowedTypes Allowed conceptID types + * + * @return string + */ + protected function getFirstConceptIdentifier(array $parentNode, array $allowedTypes = []): string + { + foreach ($this->xmlDoc->all($parentNode, 'conceptID') as $conceptID) { + if ($id = $this->xmlDoc->value($conceptID)) { + $type = mb_strtolower($this->xmlDoc->attr($conceptID, 'type') ?? '', 'UTF-8'); + if (!$allowedTypes || in_array($type, $allowedTypes)) { + return $id; + } + } + } + return $this->getSkosConceptURI($parentNode); + } + + /** + * Get a skos:Concept URI from a node. + * + * @param array $node Node + * + * @return string + */ + protected function getSkosConceptURI(array $node): string + { + $skosConcepts = [ + ...$this->xmlDoc->all($node, "{{$this->skosNs}}Concept"), + ...$this->xmlDoc->all($node, 'Concept'), + ]; + foreach ($skosConcepts as $skosConcept) { + $uri = $this->xmlDoc->attr($skosConcept, "{{$this->rdfNs}}about") + ?? $this->xmlDoc->attr($skosConcept, 'about'); + if (null !== $uri) { + return $uri; + } + } + return ''; + } } diff --git a/tests/RecordManagerTest/Base/Record/LidoTest.php b/tests/RecordManagerTest/Base/Record/LidoTest.php index 7e760c4b..133b8b81 100644 --- a/tests/RecordManagerTest/Base/Record/LidoTest.php +++ b/tests/RecordManagerTest/Base/Record/LidoTest.php @@ -101,6 +101,7 @@ public function testLido1() '(knp)M011-320623', ], 'isbn' => [ + '9789517718721', '9789518593730', '9789518593731', '9789518593732', @@ -112,6 +113,8 @@ public function testLido1() 'thumbnail' => '', 'allfields' => [ 'knp-247394', + '12345678', + 'URN:ISBN:951-771-872-1', 'Kirja', 'Säädökset', 'Luonnonsuojelusäädökset / toimittanut Raimo Luhtanen', @@ -240,6 +243,7 @@ public function testLido1NonMergedTitle() '(knp)M011-320623', ], 'isbn' => [ + '9789517718721', '9789518593730', '9789518593731', '9789518593732', @@ -251,6 +255,8 @@ public function testLido1NonMergedTitle() 'thumbnail' => '', 'allfields' => [ 'knp-247394', + '12345678', + 'URN:ISBN:951-771-872-1', 'Kirja', 'Säädökset', 'Luonnonsuojelusäädökset / toimittanut Raimo Luhtanen', @@ -525,6 +531,10 @@ public function testNamespaces(): void ], $getTitles->invokeArgs($record, ['fi']) ); + $this->assertEquals( + ['http://www.yso.fi/onto/yso/p19378'], + $reflection->getMethod('getTopicIDs')->invokeArgs($record, []) + ); } /** diff --git a/tests/fixtures/Base/record/lido1.xml b/tests/fixtures/Base/record/lido1.xml index 8e1c39f1..7fc05c24 100644 --- a/tests/fixtures/Base/record/lido1.xml +++ b/tests/fixtures/Base/record/lido1.xml @@ -2,6 +2,8 @@ knp-247394 + 12345678 + URN:ISBN:951-771-872-1 diff --git a/tests/fixtures/Base/record/lido_ns.xml b/tests/fixtures/Base/record/lido_ns.xml index dbc2bfb6..d43c6172 100644 --- a/tests/fixtures/Base/record/lido_ns.xml +++ b/tests/fixtures/Base/record/lido_ns.xml @@ -1,5 +1,5 @@ - + testimuseo-K1554 @@ -11,6 +11,18 @@ + + + + + + + kissa + + + + +