From 46415af17c8f37fa4564e0c7ee850061762ec8e2 Mon Sep 17 00:00:00 2001 From: Christian Marsilius Date: Tue, 24 Mar 2026 18:01:37 +0100 Subject: [PATCH 1/2] pkp/pkp-lib#7527 stamp context identity metadata --- CrossrefPlugin.php | 6 +++--- filter/ArticleCrossrefXmlFilter.php | 30 ++++++++++++++++++++++++++++- filter/IssueCrossrefXmlFilter.php | 10 +++++----- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/CrossrefPlugin.php b/CrossrefPlugin.php index 2cbb67e..eb6ee43 100644 --- a/CrossrefPlugin.php +++ b/CrossrefPlugin.php @@ -488,9 +488,9 @@ function ($attribute, $value, $fail) use ($context, $publication) { ]; $metadata = [ - 'publisherInstitution' => $context->getData('publisherInstitution'), - 'onlineIssn' => $context->getData('onlineIssn'), - 'printIssn' => $context->getData('printIssn'), + 'publisherInstitution' => $publication->getData('publisherInstitution'), + 'onlineIssn' => $publication->getData('onlineIssn'), + 'printIssn' => $publication->getData('printIssn'), 'doi' => $publication->getDoi(), 'issueId' => $issueId, ]; diff --git a/filter/ArticleCrossrefXmlFilter.php b/filter/ArticleCrossrefXmlFilter.php index d099a0a..446a50a 100644 --- a/filter/ArticleCrossrefXmlFilter.php +++ b/filter/ArticleCrossrefXmlFilter.php @@ -113,7 +113,7 @@ public function createSubmissionJournalNode(DOMDocument $doc, Submission $pubObj $deployment = $this->getDeployment(); $journalNode = $doc->createElementNS($deployment->getNamespace(), 'journal'); - $journalNode->appendChild($this->createJournalMetadataNode($doc)); + $journalNode->appendChild($this->createSubmissionJournalMetadataNode($doc, $publication)); $issueNode = $this->createSubmissionJournalIssueNode($doc, $publication); if ($issueNode) { $journalNode->appendChild($issueNode); @@ -122,6 +122,34 @@ public function createSubmissionJournalNode(DOMDocument $doc, Submission $pubObj return $journalNode; } + /** + * Create and return the journal metadata node 'journal_metadata'. + */ + public function createSubmissionJournalMetadataNode(DOMDocument $doc, Publication $publication): ?DOMElement + { + /** @var CrossrefExportDeployment $deployment */ + $deployment = $this->getDeployment(); + $context = $deployment->getContext(); + $cache = $deployment->getCache(); + + $issueId = $publication->getData('issueId'); + + if (!$issueId) { + return null; + } + + if ($cache->isCached('issues', $issueId)) { + $issue = $cache->get('issues', $issueId); + } else { + $issue = Repo::issue()->get($issueId); + $issue = $issue->getJournalId() == $context->getId() ? $issue : null; + if ($issue) { + $cache->add($issue, null); + } + } + return parent::createJournalMetadataNode($doc, $issue); + } + /** * Create and return the journal issue node 'journal_issue'. */ diff --git a/filter/IssueCrossrefXmlFilter.php b/filter/IssueCrossrefXmlFilter.php index 4c81665..a129221 100644 --- a/filter/IssueCrossrefXmlFilter.php +++ b/filter/IssueCrossrefXmlFilter.php @@ -129,7 +129,7 @@ public function createJournalNode(DOMDocument $doc, Issue $pubObject): DOMElemen { $deployment = $this->getDeployment(); $journalNode = $doc->createElementNS($deployment->getNamespace(), 'journal'); - $journalNode->appendChild($this->createJournalMetadataNode($doc)); + $journalNode->appendChild($this->createJournalMetadataNode($doc, $pubObject)); $journalNode->appendChild($this->createJournalIssueNode($doc, $pubObject)); return $journalNode; } @@ -137,14 +137,14 @@ public function createJournalNode(DOMDocument $doc, Issue $pubObject): DOMElemen /** * Create and return the journal metadata node 'journal_metadata'. */ - public function createJournalMetadataNode(DOMDocument $doc): DOMElement + public function createJournalMetadataNode(DOMDocument $doc, Issue $issue): DOMElement { $deployment = $this->getDeployment(); $context = $deployment->getContext(); $journalMetadataNode = $doc->createElementNS($deployment->getNamespace(), 'journal_metadata'); // Full title - $journalTitle = $context->getName($context->getPrimaryLocale()); + $journalTitle = $issue->getData('contextName', $context->getPrimaryLocale()); // Fall back to the journal abbreviation if the full title is not set in the primary locale. if ($journalTitle == '') { $journalTitle = $context->getData('abbreviation', $context->getPrimaryLocale()); @@ -157,11 +157,11 @@ public function createJournalMetadataNode(DOMDocument $doc): DOMElement } $journalMetadataNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'abbrev_title', htmlspecialchars($journalAbbrev, ENT_COMPAT, 'UTF-8'))); // Both online and print ISSNs are permitted by Crossref — send whichever are available. - if ($ISSN = $context->getData('onlineIssn')) { + if ($ISSN = $issue->getData('onlineIssn')) { $journalMetadataNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'issn', $ISSN)); $node->setAttribute('media_type', 'electronic'); } - if ($ISSN = $context->getData('printIssn')) { + if ($ISSN = $issue->getData('printIssn')) { $journalMetadataNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'issn', $ISSN)); $node->setAttribute('media_type', 'print'); } From e5434992b68950824b0cd015003fc9038d268b57 Mon Sep 17 00:00:00 2001 From: Bozana Bokan Date: Wed, 17 Jun 2026 14:13:49 +0200 Subject: [PATCH 2/2] pkp/pkp-lib#7527 Use identity resolver in Crossref stale-metadata check and issue export --- CrossrefPlugin.php | 6 +- filter/ArticleCrossrefXmlFilter.php | 30 +-------- filter/IssueCrossrefXmlFilter.php | 9 +-- tests/JournalMetadataNodeTest.php | 96 +++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 36 deletions(-) create mode 100644 tests/JournalMetadataNodeTest.php diff --git a/CrossrefPlugin.php b/CrossrefPlugin.php index eb6ee43..b6aee5a 100644 --- a/CrossrefPlugin.php +++ b/CrossrefPlugin.php @@ -488,9 +488,9 @@ function ($attribute, $value, $fail) use ($context, $publication) { ]; $metadata = [ - 'publisherInstitution' => $publication->getData('publisherInstitution'), - 'onlineIssn' => $publication->getData('onlineIssn'), - 'printIssn' => $publication->getData('printIssn'), + 'publisherInstitution' => $publication->getPublisher($context), + 'onlineIssn' => $publication->getOnlineIssn($context), + 'printIssn' => $publication->getPrintIssn($context), 'doi' => $publication->getDoi(), 'issueId' => $issueId, ]; diff --git a/filter/ArticleCrossrefXmlFilter.php b/filter/ArticleCrossrefXmlFilter.php index 446a50a..0979b5e 100644 --- a/filter/ArticleCrossrefXmlFilter.php +++ b/filter/ArticleCrossrefXmlFilter.php @@ -113,7 +113,7 @@ public function createSubmissionJournalNode(DOMDocument $doc, Submission $pubObj $deployment = $this->getDeployment(); $journalNode = $doc->createElementNS($deployment->getNamespace(), 'journal'); - $journalNode->appendChild($this->createSubmissionJournalMetadataNode($doc, $publication)); + $journalNode->appendChild($this->createJournalMetadataNode($doc, $publication)); $issueNode = $this->createSubmissionJournalIssueNode($doc, $publication); if ($issueNode) { $journalNode->appendChild($issueNode); @@ -122,34 +122,6 @@ public function createSubmissionJournalNode(DOMDocument $doc, Submission $pubObj return $journalNode; } - /** - * Create and return the journal metadata node 'journal_metadata'. - */ - public function createSubmissionJournalMetadataNode(DOMDocument $doc, Publication $publication): ?DOMElement - { - /** @var CrossrefExportDeployment $deployment */ - $deployment = $this->getDeployment(); - $context = $deployment->getContext(); - $cache = $deployment->getCache(); - - $issueId = $publication->getData('issueId'); - - if (!$issueId) { - return null; - } - - if ($cache->isCached('issues', $issueId)) { - $issue = $cache->get('issues', $issueId); - } else { - $issue = Repo::issue()->get($issueId); - $issue = $issue->getJournalId() == $context->getId() ? $issue : null; - if ($issue) { - $cache->add($issue, null); - } - } - return parent::createJournalMetadataNode($doc, $issue); - } - /** * Create and return the journal issue node 'journal_issue'. */ diff --git a/filter/IssueCrossrefXmlFilter.php b/filter/IssueCrossrefXmlFilter.php index a129221..7154357 100644 --- a/filter/IssueCrossrefXmlFilter.php +++ b/filter/IssueCrossrefXmlFilter.php @@ -18,6 +18,7 @@ use APP\core\Request; use APP\issue\Issue; use APP\plugins\generic\crossref\CrossrefExportDeployment; +use APP\publication\Publication; use DOMDocument; use DOMElement; use PKP\core\Dispatcher; @@ -137,14 +138,14 @@ public function createJournalNode(DOMDocument $doc, Issue $pubObject): DOMElemen /** * Create and return the journal metadata node 'journal_metadata'. */ - public function createJournalMetadataNode(DOMDocument $doc, Issue $issue): DOMElement + public function createJournalMetadataNode(DOMDocument $doc, Issue|Publication $identitySource): DOMElement { $deployment = $this->getDeployment(); $context = $deployment->getContext(); $journalMetadataNode = $doc->createElementNS($deployment->getNamespace(), 'journal_metadata'); // Full title - $journalTitle = $issue->getData('contextName', $context->getPrimaryLocale()); + $journalTitle = $identitySource->getPrimaryContextName($context); // Fall back to the journal abbreviation if the full title is not set in the primary locale. if ($journalTitle == '') { $journalTitle = $context->getData('abbreviation', $context->getPrimaryLocale()); @@ -157,11 +158,11 @@ public function createJournalMetadataNode(DOMDocument $doc, Issue $issue): DOMEl } $journalMetadataNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'abbrev_title', htmlspecialchars($journalAbbrev, ENT_COMPAT, 'UTF-8'))); // Both online and print ISSNs are permitted by Crossref — send whichever are available. - if ($ISSN = $issue->getData('onlineIssn')) { + if ($ISSN = $identitySource->getOnlineIssn($context)) { $journalMetadataNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'issn', $ISSN)); $node->setAttribute('media_type', 'electronic'); } - if ($ISSN = $issue->getData('printIssn')) { + if ($ISSN = $identitySource->getPrintIssn($context)) { $journalMetadataNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'issn', $ISSN)); $node->setAttribute('media_type', 'print'); } diff --git a/tests/JournalMetadataNodeTest.php b/tests/JournalMetadataNodeTest.php new file mode 100644 index 0000000..88d0630 --- /dev/null +++ b/tests/JournalMetadataNodeTest.php @@ -0,0 +1,96 @@ +shouldReceive('getPrimaryLocale')->andReturn('en'); + Registry::set('site', $mockSite); + $this->mockRequest(); + + $this->publication = (new DAO(new PKPSchemaService()))->newDataObject(); + + $this->filter = $this->getMockBuilder(IssueCrossrefXmlFilter::class) + ->disableOriginalConstructor() + ->onlyMethods([]) + ->getMock(); + } + + private function setupDeployment(Journal $journal): void + { + $deployment = Mockery::mock(CrossrefExportDeployment::class); + $deployment->shouldReceive('getContext')->andReturn($journal); + $deployment->shouldReceive('getNamespace')->andReturn(CrossrefExportDeployment::CROSSREF_XMLNS); + $this->filter->setDeployment($deployment); + } + + public function testJournalMetadataUsesStampedIdentityAfterJournalChange(): void + { + $journal = new Journal(); + $journal->setName('Old Journal Name', 'en'); + $journal->setPrimaryLocale('en'); + $journal->setData('onlineIssn', 'old-online-issn'); + $journal->setData('printIssn', 'old-print-issn'); + $journal->setData('publisherInstitution', 'Old Publisher'); + $journal->setData('abbreviation', 'J.Old', 'en'); + + $this->publication->stampContextIdentity($journal); + + // Journal is later renamed and its ISSNs changed — the stamp must remain authoritative. + $journal->setName('New Journal Name', 'en'); + $journal->setData('onlineIssn', 'new-online-issn'); + $journal->setData('printIssn', 'new-print-issn'); + + $this->setupDeployment($journal); + $xml = $this->filter->createJournalMetadataNode(new DOMDocument(), $this->publication); + $xmlString = $xml->ownerDocument->saveXML($xml); + + $this->assertStringContainsString('Old Journal Name', $xmlString); + $this->assertStringContainsString('old-online-issn', $xmlString); + $this->assertStringContainsString('old-print-issn', $xmlString); + $this->assertStringNotContainsString('New Journal Name', $xmlString); + $this->assertStringNotContainsString('new-online-issn', $xmlString); + $this->assertStringNotContainsString('new-print-issn', $xmlString); + } +}