Open Journal Systems  3.3.0
ArticleCrossrefXmlFilter.inc.php
1 <?php
2 
16 import('plugins.importexport.crossref.filter.IssueCrossrefXmlFilter');
17 
23  function __construct($filterGroup) {
24  $this->setDisplayName('Crossref XML article export');
25  parent::__construct($filterGroup);
26  }
27 
28  //
29  // Implement template methods from PersistableFilter
30  //
34  function getClassName() {
35  return 'plugins.importexport.crossref.filter.ArticleCrossrefXmlFilter';
36  }
37 
38 
39  //
40  // Submission conversion functions
41  //
45  function createJournalNode($doc, $pubObject) {
46  $deployment = $this->getDeployment();
47  $journalNode = parent::createJournalNode($doc, $pubObject);
48  assert(is_a($pubObject, 'Submission'));
49  $journalNode->appendChild($this->createJournalArticleNode($doc, $pubObject));
50  return $journalNode;
51  }
52 
59  function createJournalIssueNode($doc, $submission) {
60  $deployment = $this->getDeployment();
61  $context = $deployment->getContext();
62  $cache = $deployment->getCache();
63  assert(is_a($submission, 'Submission'));
64  $issueId = $submission->getCurrentPublication()->getData('issueId');
65  if ($cache->isCached('issues', $issueId)) {
66  $issue = $cache->get('issues', $issueId);
67  } else {
68  $issueDao = DAORegistry::getDAO('IssueDAO'); /* @var $issueDao IssueDAO */
69  $issue = $issueDao->getById($issueId, $context->getId());
70  if ($issue) $cache->add($issue, null);
71  }
72  $journalIssueNode = parent::createJournalIssueNode($doc, $issue);
73  return $journalIssueNode;
74  }
75 
82  function createJournalArticleNode($doc, $submission) {
83  $deployment = $this->getDeployment();
84  $context = $deployment->getContext();
85  $request = Application::get()->getRequest();
86 
87  $publication = $submission->getCurrentPublication();
88  $locale = $publication->getData('locale');
89 
90  // Issue shoulld be set by now
91  $issue = $deployment->getIssue();
92 
93  $journalArticleNode = $doc->createElementNS($deployment->getNamespace(), 'journal_article');
94  $journalArticleNode->setAttribute('publication_type', 'full_text');
95  $journalArticleNode->setAttribute('metadata_distribution_opts', 'any');
96 
97 
98  // title
99  $titlesNode = $doc->createElementNS($deployment->getNamespace(), 'titles');
100  $titlesNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'title', htmlspecialchars($publication->getData('title', $locale), ENT_COMPAT, 'UTF-8')));
101  if ($subtitle = $publication->getData('subtitle', $locale)) $titlesNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'subtitle', htmlspecialchars($subtitle, ENT_COMPAT, 'UTF-8')));
102  $journalArticleNode->appendChild($titlesNode);
103 
104  // contributors
105  $contributorsNode = $doc->createElementNS($deployment->getNamespace(), 'contributors');
106  $authors = $publication->getData('authors');
107  $isFirst = true;
108  foreach ($authors as $author) {
109  $personNameNode = $doc->createElementNS($deployment->getNamespace(), 'person_name');
110  $personNameNode->setAttribute('contributor_role', 'author');
111 
112  if ($isFirst) {
113  $personNameNode->setAttribute('sequence', 'first');
114  } else {
115  $personNameNode->setAttribute('sequence', 'additional');
116  }
117 
118  $familyNames = $author->getFamilyName(null);
119  $givenNames = $author->getGivenName(null);
120 
121  // Check if both givenName and familyName is set for the submission language.
122  if (isset($familyNames[$locale]) && isset($givenNames[$locale])) {
123  $personNameNode->setAttribute('language', PKPLocale::getIso1FromLocale($locale));
124  $personNameNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'given_name', htmlspecialchars(ucfirst($givenNames[$locale]), ENT_COMPAT, 'UTF-8')));
125  $personNameNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'surname', htmlspecialchars(ucfirst($familyNames[$locale]), ENT_COMPAT, 'UTF-8')));
126 
127  $hasAltName = false;
128  foreach($familyNames as $otherLocal => $familyName) {
129  if ($otherLocal != $locale && isset($familyName) && !empty($familyName)) {
130  if (!$hasAltName) {
131  $altNameNode = $doc->createElementNS($deployment->getNamespace(), 'alt-name');
132  $personNameNode->appendChild($altNameNode);
133 
134  $hasAltName = true;
135  }
136 
137  $nameNode = $doc->createElementNS($deployment->getNamespace(), 'name');
138  $nameNode->setAttribute('language', PKPLocale::getIso1FromLocale($otherLocal));
139 
140  $nameNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'surname', htmlspecialchars(ucfirst($familyName), ENT_COMPAT, 'UTF-8')));
141  if (isset($givenNames[$otherLocal]) && !empty($givenNames[$otherLocal])) {
142  $nameNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'given_name', htmlspecialchars(ucfirst($givenNames[$otherLocal]), ENT_COMPAT, 'UTF-8')));
143  }
144 
145  $altNameNode->appendChild($nameNode);
146  }
147  }
148 
149  } else {
150  $personNameNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'surname', htmlspecialchars(ucfirst($author->getFullName(false)), ENT_COMPAT, 'UTF-8')));
151  }
152 
153  if ($author->getData('orcid')) {
154  $personNameNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'ORCID', $author->getData('orcid')));
155  }
156 
157  $contributorsNode->appendChild($personNameNode);
158  $isFirst = false;
159  }
160  $journalArticleNode->appendChild($contributorsNode);
161 
162  // abstract
163  if ($abstract = $publication->getData('abstract', $locale)) {
164  $abstractNode = $doc->createElementNS($deployment->getJATSNamespace(), 'jats:abstract');
165  $abstractNode->appendChild($node = $doc->createElementNS($deployment->getJATSNamespace(), 'jats:p', htmlspecialchars(html_entity_decode(strip_tags($abstract), ENT_COMPAT, 'UTF-8'), ENT_COMPAT, 'UTF-8')));
166  $journalArticleNode->appendChild($abstractNode);
167  }
168 
169  // publication date
170  if ($datePublished = $publication->getData('datePublished')) {
171  $journalArticleNode->appendChild($this->createPublicationDateNode($doc, $datePublished));
172  }
173 
174  // pages
175  // CrossRef requires first_page and last_page of any contiguous range, then any other ranges go in other_pages
176  $pages = $publication->getPageArray();
177  if (!empty($pages)) {
178  $firstRange = array_shift($pages);
179  $firstPage = array_shift($firstRange);
180  if (count($firstRange)) {
181  // There is a first page and last page for the first range
182  $lastPage = array_shift($firstRange);
183  } else {
184  // There is not a range in the first segment
185  $lastPage = '';
186  }
187  // CrossRef accepts no punctuation in first_page or last_page
188  if ((!empty($firstPage) || $firstPage === "0") && !preg_match('/[^[:alnum:]]/', $firstPage) && !preg_match('/[^[:alnum:]]/', $lastPage)) {
189  $pagesNode = $doc->createElementNS($deployment->getNamespace(), 'pages');
190  $pagesNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'first_page', $firstPage));
191  if ($lastPage != '') {
192  $pagesNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'last_page', $lastPage));
193  }
194  $otherPages = '';
195  foreach ($pages as $range) {
196  $otherPages .= ($otherPages ? ',' : '').implode('-', $range);
197  }
198  if ($otherPages != '') {
199  $pagesNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'other_pages', $otherPages));
200  }
201  $journalArticleNode->appendChild($pagesNode);
202  }
203  }
204 
205  // license
206  if ($publication->getData('licenseUrl')) {
207  $licenseNode = $doc->createElementNS($deployment->getAINamespace(), 'ai:program');
208  $licenseNode->setAttribute('name', 'AccessIndicators');
209  $licenseNode->appendChild($node = $doc->createElementNS($deployment->getAINamespace(), 'ai:license_ref', htmlspecialchars($publication->getData('licenseUrl'), ENT_COMPAT, 'UTF-8')));
210  $journalArticleNode->appendChild($licenseNode);
211  }
212 
213  // DOI data
214  $doiDataNode = $this->createDOIDataNode($doc, $publication->getStoredPubId('doi'), $request->url($context->getPath(), 'article', 'view', $submission->getBestId(), null, null, true));
215  // append galleys files and collection nodes to the DOI data node
216  $galleys = $publication->getData('galleys');
217  // All full-texts, PDF full-texts and remote galleys for text-mining and as-crawled URL
218  $submissionGalleys = $pdfGalleys = $remoteGalleys = array();
219  // preferred PDF full-text for the as-crawled URL
220  $pdfGalleyInArticleLocale = null;
221  // get immediatelly also supplementary files for component list
222  $componentGalleys = array();
223  $genreDao = DAORegistry::getDAO('GenreDAO'); /* @var $genreDao GenreDAO */
224  foreach ($galleys as $galley) {
225  // filter supp files with DOI
226  if (!$galley->getRemoteURL()) {
227  $galleyFile = $galley->getFile();
228  if ($galleyFile) {
229  $genre = $genreDao->getById($galleyFile->getGenreId());
230  if ($genre->getSupplementary()) {
231  if ($galley->getStoredPubid('doi')) {
232  // construct the array key with galley best ID and locale needed for the component node
233  $componentGalleys[] = $galley;
234  }
235  } else {
236  $submissionGalleys[] = $galley;
237  if ($galley->isPdfGalley()) {
238  $pdfGalleys[] = $galley;
239  if (!$pdfGalleyInArticleLocale && $galley->getLocale() == $locale) {
240  $pdfGalleyInArticleLocale = $galley;
241  }
242  }
243  }
244  }
245  } else {
246  $remoteGalleys[] = $galley;
247  }
248  }
249  // as-crawled URLs
250  $asCrawledGalleys = array();
251  if ($pdfGalleyInArticleLocale) {
252  $asCrawledGalleys = array($pdfGalleyInArticleLocale);
253  } elseif (!empty($pdfGalleys)) {
254  $asCrawledGalleys = array($pdfGalleys[0]);
255  } else {
256  $asCrawledGalleys = $submissionGalleys;
257  }
258  // as-crawled URL - collection nodes
259  $this->appendAsCrawledCollectionNodes($doc, $doiDataNode, $submission, $asCrawledGalleys);
260  // text-mining - collection nodes
261  $submissionGalleys = array_merge($submissionGalleys, $remoteGalleys);
262  $this->appendTextMiningCollectionNodes($doc, $doiDataNode, $submission, $submissionGalleys);
263  $journalArticleNode->appendChild($doiDataNode);
264 
265  // component list (supplementary files)
266  if (!empty($componentGalleys)) {
267  $journalArticleNode->appendChild($this->createComponentListNode($doc, $submission, $componentGalleys));
268  }
269 
270  return $journalArticleNode;
271  }
272 
280  function appendAsCrawledCollectionNodes($doc, $doiDataNode, $submission, $galleys) {
281  $deployment = $this->getDeployment();
282  $context = $deployment->getContext();
283  $request = Application::get()->getRequest();
284 
285  if (empty($galleys)) {
286  $crawlerBasedCollectionNode = $doc->createElementNS($deployment->getNamespace(), 'collection');
287  $crawlerBasedCollectionNode->setAttribute('property', 'crawler-based');
288  $doiDataNode->appendChild($crawlerBasedCollectionNode);
289  }
290  foreach ($galleys as $galley) {
291  $resourceURL = $request->url($context->getPath(), 'article', 'download', array($submission->getBestId(), $galley->getBestGalleyId()), null, null, true);
292  // iParadigms crawler based collection element
293  $crawlerBasedCollectionNode = $doc->createElementNS($deployment->getNamespace(), 'collection');
294  $crawlerBasedCollectionNode->setAttribute('property', 'crawler-based');
295  $iParadigmsItemNode = $doc->createElementNS($deployment->getNamespace(), 'item');
296  $iParadigmsItemNode->setAttribute('crawler', 'iParadigms');
297  $iParadigmsItemNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'resource', $resourceURL));
298  $crawlerBasedCollectionNode->appendChild($iParadigmsItemNode);
299  $doiDataNode->appendChild($crawlerBasedCollectionNode);
300  }
301  }
302 
310  function appendTextMiningCollectionNodes($doc, $doiDataNode, $submission, $galleys) {
311  $deployment = $this->getDeployment();
312  $context = $deployment->getContext();
313  $request = Application::get()->getRequest();
314 
315  // start of the text-mining collection element
316  $textMiningCollectionNode = $doc->createElementNS($deployment->getNamespace(), 'collection');
317  $textMiningCollectionNode->setAttribute('property', 'text-mining');
318  foreach ($galleys as $galley) {
319  $resourceURL = $request->url($context->getPath(), 'article', 'download', array($submission->getBestId(), $galley->getBestGalleyId()), null, null, true);
320  // text-mining collection item
321  $textMiningItemNode = $doc->createElementNS($deployment->getNamespace(), 'item');
322  $resourceNode = $doc->createElementNS($deployment->getNamespace(), 'resource', $resourceURL);
323  if (!$galley->getRemoteURL()) $resourceNode->setAttribute('mime_type', $galley->getFileType());
324  $textMiningItemNode->appendChild($resourceNode);
325  $textMiningCollectionNode->appendChild($textMiningItemNode);
326  }
327  $doiDataNode->appendChild($textMiningCollectionNode);
328  }
329 
337  function createComponentListNode($doc, $submission, $componentGalleys) {
338  $deployment = $this->getDeployment();
339  $context = $deployment->getContext();
340  $request = Application::get()->getRequest();
341 
342  // Create the base node
343  $componentListNode =$doc->createElementNS($deployment->getNamespace(), 'component_list');
344  // Run through supp files and add component nodes.
345  foreach($componentGalleys as $componentGalley) {
346  $componentFile = $componentGalley->getFile();
347  $componentNode = $doc->createElementNS($deployment->getNamespace(), 'component');
348  $componentNode->setAttribute('parent_relation', 'isPartOf');
349  /* Titles */
350  $componentFileTitle = $componentFile->getName($componentGalley->getLocale());
351  if (!empty($componentFileTitle)) {
352  $titlesNode = $doc->createElementNS($deployment->getNamespace(), 'titles');
353  $titlesNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'title', htmlspecialchars($componentFileTitle, ENT_COMPAT, 'UTF-8')));
354  $componentNode->appendChild($titlesNode);
355  }
356  // DOI data node
357  $resourceURL = $request->url($context->getPath(), 'article', 'download', array($submission->getBestId(), $componentGalley->getBestGalleyId()), null, null, true);
358  $componentNode->appendChild($this->createDOIDataNode($doc, $componentGalley->getStoredPubId('doi'), $resourceURL));
359  $componentListNode->appendChild($componentNode);
360  }
361  return $componentListNode;
362  }
363 }
364 
365 
ArticleCrossrefXmlFilter\appendAsCrawledCollectionNodes
appendAsCrawledCollectionNodes($doc, $doiDataNode, $submission, $galleys)
Definition: ArticleCrossrefXmlFilter.inc.php:280
IssueCrossrefXmlFilter
Class that converts an Issue to a Crossref XML document.
Definition: IssueCrossrefXmlFilter.inc.php:18
ArticleCrossrefXmlFilter\appendTextMiningCollectionNodes
appendTextMiningCollectionNodes($doc, $doiDataNode, $submission, $galleys)
Definition: ArticleCrossrefXmlFilter.inc.php:310
IssueCrossrefXmlFilter\createPublicationDateNode
createPublicationDateNode($doc, $objectPublicationDate)
Definition: IssueCrossrefXmlFilter.inc.php:207
IssueCrossrefXmlFilter\createDOIDataNode
createDOIDataNode($doc, $doi, $url)
Definition: IssueCrossrefXmlFilter.inc.php:229
DAORegistry\getDAO
static & getDAO($name, $dbconn=null)
Definition: DAORegistry.inc.php:57
ArticleCrossrefXmlFilter\createJournalNode
createJournalNode($doc, $pubObject)
Definition: ArticleCrossrefXmlFilter.inc.php:45
ArticleCrossrefXmlFilter
Class that converts an Article to a Crossref XML document.
Definition: ArticleCrossrefXmlFilter.inc.php:18
NativeImportExportFilter\getDeployment
getDeployment()
Definition: NativeImportExportFilter.inc.php:49
PKPLocale\getIso1FromLocale
static getIso1FromLocale($locale)
Definition: PKPLocale.inc.php:762
ArticleCrossrefXmlFilter\createComponentListNode
createComponentListNode($doc, $submission, $componentGalleys)
Definition: ArticleCrossrefXmlFilter.inc.php:337
ArticleCrossrefXmlFilter\__construct
__construct($filterGroup)
Definition: ArticleCrossrefXmlFilter.inc.php:23
ArticleCrossrefXmlFilter\createJournalIssueNode
createJournalIssueNode($doc, $submission)
Definition: ArticleCrossrefXmlFilter.inc.php:59
PKPApplication\get
static get()
Definition: PKPApplication.inc.php:235
ArticleCrossrefXmlFilter\getClassName
getClassName()
Definition: ArticleCrossrefXmlFilter.inc.php:34
Filter\setDisplayName
setDisplayName($displayName)
Definition: Filter.inc.php:140
ArticleCrossrefXmlFilter\createJournalArticleNode
createJournalArticleNode($doc, $submission)
Definition: ArticleCrossrefXmlFilter.inc.php:82