Open Journal Systems  3.3.0
DataciteXmlFilter.inc.php
1 <?php
2 
16 // Title types
17 define('DATACITE_TITLETYPE_TRANSLATED', 'TranslatedTitle');
18 define('DATACITE_TITLETYPE_ALTERNATIVE', 'AlternativeTitle');
19 
20 // Date types
21 define('DATACITE_DATE_AVAILABLE', 'Available');
22 define('DATACITE_DATE_ISSUED', 'Issued');
23 define('DATACITE_DATE_SUBMITTED', 'Submitted');
24 define('DATACITE_DATE_ACCEPTED', 'Accepted');
25 define('DATACITE_DATE_CREATED', 'Created');
26 define('DATACITE_DATE_UPDATED', 'Updated');
27 
28 // Identifier types
29 define('DATACITE_IDTYPE_PROPRIETARY', 'publisherId');
30 define('DATACITE_IDTYPE_EISSN', 'EISSN');
31 define('DATACITE_IDTYPE_ISSN', 'ISSN');
32 define('DATACITE_IDTYPE_DOI', 'DOI');
33 
34 // Relation types
35 define('DATACITE_RELTYPE_ISVARIANTFORMOF', 'IsVariantFormOf');
36 define('DATACITE_RELTYPE_HASPART', 'HasPart');
37 define('DATACITE_RELTYPE_ISPARTOF', 'IsPartOf');
38 define('DATACITE_RELTYPE_ISPREVIOUSVERSIONOF', 'IsPreviousVersionOf');
39 define('DATACITE_RELTYPE_ISNEWVERSIONOF', 'IsNewVersionOf');
40 
41 // Description types
42 define('DATACITE_DESCTYPE_ABSTRACT', 'Abstract');
43 define('DATACITE_DESCTYPE_SERIESINFO', 'SeriesInformation');
44 define('DATACITE_DESCTYPE_TOC', 'TableOfContents');
45 define('DATACITE_DESCTYPE_OTHER', 'Other');
46 
47 import('lib.pkp.plugins.importexport.native.filter.NativeExportFilter');
48 
49 
55  function __construct($filterGroup) {
56  $this->setDisplayName('DataCite XML export');
57  parent::__construct($filterGroup);
58  }
59 
60  //
61  // Implement template methods from PersistableFilter
62  //
66  function getClassName() {
67  return 'plugins.importexport.datacite.filter.DataciteXmlFilter';
68  }
69 
70  //
71  // Implement template methods from Filter
72  //
78  function &process(&$pubObject) {
79  // Create the XML document
80  $doc = new DOMDocument('1.0', 'utf-8');
81  $doc->preserveWhiteSpace = false;
82  $doc->formatOutput = true;
83  $deployment = $this->getDeployment();
84  $context = $deployment->getContext();
85  $plugin = $deployment->getPlugin();
86  $cache = $plugin->getCache();
87 
88  // Get all objects
89  $issue = $article = $galley = $galleyFile = null;
90  if (is_a($pubObject, 'Issue')) {
91  $issue = $pubObject;
92  if (!$cache->isCached('issues', $issue->getId())) {
93  $cache->add($issue, null);
94  }
95  } elseif (is_a($pubObject, 'Submission')) {
96  $article = $pubObject;
97  if (!$cache->isCached('articles', $article->getId())) {
98  $cache->add($article, null);
99  }
100  } elseif (is_a($pubObject, 'ArticleGalley')) {
101  $galley = $pubObject;
102  $galleyFile = $galley->getFile();
103  $publication = Services::get('publication')->get($galley->getData('publicationId'));
104  if ($cache->isCached('articles', $publication->getData('submissionId'))) {
105  $article = $cache->get('articles', $publication->getData('submissionId'));
106  } else {
107  $article = Services::get('submission')->get($publication->getData('submissionId'));
108  if ($article) $cache->add($article, null);
109  }
110  }
111  if (!$issue) {
112  $issueId = $article->getCurrentPublication()->getData('issueId');
113  if ($cache->isCached('issues', $issueId)) {
114  $issue = $cache->get('issues', $issueId);
115  } else {
116  $issueDao = DAORegistry::getDAO('IssueDAO'); /* @var $issueDao IssueDAO */
117  $issue = $issueDao->getById($issueId, $context->getId());
118  if ($issue) $cache->add($issue, null);
119  }
120  }
121 
122  // Get the most recently published version
123  $publication = $article ? $article->getCurrentPublication() : null;
124 
125  // Identify the object locale.
126  $objectLocalePrecedence = $this->getObjectLocalePrecedence($context, $article, $publication, $galley);
127  // The publisher is required.
128  // Use the journal title as DataCite recommends for now.
129  $publisher = $this->getPrimaryTranslation($context->getData('name'), $objectLocalePrecedence);
130  assert(!empty($publisher));
131  // The publication date is required.
132  if ($publication) {
133  $publicationDate = $publication->getData('datePublished');
134  }
135  if (empty($publicationDate)) {
136  $publicationDate = $issue->getDatePublished();
137  }
138  assert(!empty($publicationDate));
139 
140  // Create the root node
141  $rootNode = $this->createRootNode($doc);
142  $doc->appendChild($rootNode);
143  // DOI (mandatory)
144  $doi = $pubObject->getStoredPubId('doi');
145  if ($plugin->isTestMode($context)) {
146  $doi = PKPString::regexp_replace('#^[^/]+/#', DATACITE_API_TESTPREFIX . '/', $doi);
147  }
148  $rootNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'identifier', htmlspecialchars($doi, ENT_COMPAT, 'UTF-8')));
149  $node->setAttribute('identifierType', DATACITE_IDTYPE_DOI);
150  // Creators (mandatory)
151  $rootNode->appendChild($this->createCreatorsNode($doc, $issue, $publication, $galley, $galleyFile, $publisher, $objectLocalePrecedence));
152  // Title (mandatory)
153  $rootNode->appendChild($this->createTitlesNode($doc, $issue, $publication, $galley, $galleyFile, $objectLocalePrecedence));
154  // Publisher (mandatory)
155  $rootNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'publisher', htmlspecialchars($publisher, ENT_COMPAT, 'UTF-8')));
156  // Publication Year (mandatory)
157  $rootNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'publicationYear', date('Y', strtotime($publicationDate))));
158  // Subjects
159  $subject = null;
160  if (!empty($galleyFile) && is_a($galleyFile, 'SupplementaryFile')) {
161  $subject = $this->getPrimaryTranslation($galleyFile->getSubject(null), $objectLocalePrecedence);
162  } elseif (!empty($article) && !empty($publication)) {
163  $subject = $this->getPrimaryTranslation($publication->getData('subjects'), $objectLocalePrecedence);
164  }
165  if (!empty($subject)) {
166  $subjectsNode = $doc->createElementNS($deployment->getNamespace(), 'subjects');
167  $subjectsNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'subject', htmlspecialchars($subject, ENT_COMPAT, 'UTF-8')));
168  $rootNode->appendChild($subjectsNode);
169  }
170  // Dates
171  $rootNode->appendChild($this->createDatesNode($doc, $issue, $article, $publication, $galley, $galleyFile, $publicationDate));
172  // Language
173  $rootNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'language', AppLocale::getIso1FromLocale($objectLocalePrecedence[0])));
174  // Resource Type
175  $resourceTypeNode = $this->createResourceTypeNode($doc, $issue, $article, $galley, $galleyFile);
176  if ($resourceTypeNode) $rootNode->appendChild($resourceTypeNode);
177  // Alternate Identifiers
178  $rootNode->appendChild($this->createAlternateIdentifiersNode($doc, $issue, $article, $galley));
179  // Related Identifiers
180  $relatedIdentifiersNode = $this->createRelatedIdentifiersNode($doc, $issue, $article, $publication, $galley);
181  if ($relatedIdentifiersNode) $rootNode->appendChild($relatedIdentifiersNode);
182  // Sizes
183  $sizesNode = $this->createSizesNode($doc, $issue, $article, $publication, $galley, $galleyFile);
184  if ($sizesNode) $rootNode->appendChild($sizesNode);
185  // Formats
186  if (!empty($galleyFile)) {
187  $format = $galleyFile->getFileType();
188  if (!empty($format)) {
189  $formatsNode = $doc->createElementNS($deployment->getNamespace(), 'formats');
190  $formatsNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'format', htmlspecialchars($format, ENT_COMPAT, 'UTF-8')));
191  $rootNode->appendChild($formatsNode);
192  }
193  }
194  // Rights
195  $rightsURL = $publication ? $publication->getData('licenseUrl') : $context->getData('licenseUrl');
196  if(!empty($rightsURL)) {
197  $rightsNode = $doc->createElementNS($deployment->getNamespace(), 'rightsList');
198  $rightsNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'rights', htmlspecialchars(strip_tags(Application::getCCLicenseBadge($rightsURL)), ENT_COMPAT, 'UTF-8')));
199  $node->setAttribute('rightsURI', $rightsURL);
200  $rootNode->appendChild($rightsNode);
201  }
202  // Descriptions
203  $descriptionsNode = $this->createDescriptionsNode($doc, $issue, $article, $publication, $galley, $galleyFile, $objectLocalePrecedence);
204  if ($descriptionsNode) $rootNode->appendChild($descriptionsNode);
205 
206  return $doc;
207  }
208 
209  //
210  // Conversion functions
211  //
217  function createRootNode($doc) {
218  $deployment = $this->getDeployment();
219  $rootNode = $doc->createElementNS($deployment->getNamespace(), $deployment->getRootElementName());
220  $rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xsi', $deployment->getXmlSchemaInstance());
221  $rootNode->setAttribute('xsi:schemaLocation', $deployment->getNamespace() . ' ' . $deployment->getSchemaFilename());
222  return $rootNode;
223  }
224 
236  function createCreatorsNode($doc, $issue, $publication, $galley, $galleyFile, $publisher, $objectLocalePrecedence) {
237  $deployment = $this->getDeployment();
238  $creators = array();
239  switch (true) {
240  case (isset($galleyFile) && is_a($galleyFile, 'SupplementaryFile')):
241  // Check whether we have a supp file creator set...
242  $creator = $this->getPrimaryTranslation($galleyFile->getCreator(null), $objectLocalePrecedence);
243  if (!empty($creator)) {
244  $creators[] = $creator;
245  break;
246  }
247  // ...if not then go on by retrieving the publication
248  // authors.
249  case isset($publication):
250  // Retrieve the publication authors.
251  $authors = $publication->getData('authors');
252  assert(!empty($authors));
253  foreach ($authors as $author) { /* @var $author Author */
254  $creators[] = $author->getFullName(false, true);
255  }
256  break;
257  case isset($issue):
258  $creators[] = $publisher;
259  break;
260  }
261  assert(count($creators) >= 1);
262  $creatorsNode = $doc->createElementNS($deployment->getNamespace(), 'creators');
263  foreach ($creators as $creator) {
264  $creatorNode = $doc->createElementNS($deployment->getNamespace(), 'creator');
265  $creatorNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'creatorName', htmlspecialchars($creator, ENT_COMPAT, 'UTF-8')));
266  $creatorsNode->appendChild($creatorNode);
267  }
268  return $creatorsNode;
269  }
270 
281  function createTitlesNode($doc, $issue, $publication, $galley, $galleyFile, $objectLocalePrecedence) {
282  $deployment = $this->getDeployment();
283  // Get an array of localized titles.
284  $alternativeTitle = null;
285  switch (true) {
286  case (isset($galleyFile) && is_a($galleyFile, 'SupplementaryFile')):
287  $titles = $galleyFile->getName(null);
288  break;
289  case isset($publication):
290  $titles = $publication->getData('title');
291  break;
292  case isset($issue):
293  $titles = $this->getIssueInformation($issue);
294  $alternativeTitle = $this->getPrimaryTranslation($issue->getTitle(null), $objectLocalePrecedence);
295  break;
296  }
297  // Order titles by locale precedence.
298  $titles = $this->getTranslationsByPrecedence($titles, $objectLocalePrecedence);
299  // We expect at least one title.
300  assert(count($titles)>=1);
301  $titlesNode = $doc->createElementNS($deployment->getNamespace(), 'titles');
302  // Start with the primary object locale.
303  $primaryTitle = array_shift($titles);
304  $titlesNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'title', htmlspecialchars(PKPString::html2text($primaryTitle), ENT_COMPAT, 'UTF-8')));
305  // Then let the translated titles follow.
306  foreach($titles as $locale => $title) {
307  $titlesNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'title', htmlspecialchars(PKPString::html2text($title), ENT_COMPAT, 'UTF-8')));
308  $node->setAttribute('titleType', DATACITE_TITLETYPE_TRANSLATED);
309  }
310  // And finally the alternative title.
311  if (!empty($alternativeTitle)) {
312  $titlesNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'title', htmlspecialchars(PKPString::html2text($alternativeTitle), ENT_COMPAT, 'UTF-8')));
313  $node->setAttribute('titleType', DATACITE_TITLETYPE_ALTERNATIVE);
314  }
315  return $titlesNode;
316  }
317 
329  function createDatesNode($doc, $issue, $article, $publication, $galley, $galleyFile, $publicationDate) {
330  $deployment = $this->getDeployment();
331  $dates = array();
332  switch (true) {
333  case isset($galleyFile):
334  if (is_a($galleyFile, 'SupplementaryFile')) {
335  // Created date (for supp files only): supp file date created.
336  $createdDate = $galleyFile->getDateCreated();
337  if (!empty($createdDate)) {
338  $dates[DATACITE_DATE_CREATED] = $createdDate;
339  }
340  }
341  // Accepted date (for galleys files): file uploaded.
342  $acceptedDate = $galleyFile->getDateUploaded();
343  if (!empty($acceptedDate)) {
344  $dates[DATACITE_DATE_ACCEPTED] = $acceptedDate;
345  }
346  // Last modified date (for galley files): file modified date.
347  $lastModified = $galleyFile->getDateModified();
348  if (!empty($lastModified)) {
349  $dates[DATACITE_DATE_UPDATED] = $lastModified;
350  }
351  break;
352  case isset($article):
353  // Submitted date (for articles): article date submitted.
354  $submittedDate = $article->getData('dateSubmitted');
355  if (!empty($submittedDate)) {
356  $dates[DATACITE_DATE_SUBMITTED] = $submittedDate;
357  }
358  // Accepted date: the last editor accept decision date
359  $editDecisionDao = DAORegistry::getDAO('EditDecisionDAO'); /* @var $editDecisionDao EditDecisionDAO */
360  $editDecisions = $editDecisionDao->getEditorDecisions($article->getId());
361  foreach (array_reverse($editDecisions) as $editDecision) {
362  if ($editDecision['decision'] == SUBMISSION_EDITOR_DECISION_ACCEPT) {
363  $dates[DATACITE_DATE_ACCEPTED] = $editDecision['dateDecided'];
364  }
365  }
366  // Last modified date (for articles): last modified date.
367  $lastModified = $publication->getData('lastModified');
368  if (!empty($lastModified)) {
369  $dates[DATACITE_DATE_UPDATED] = $lastModified;
370  }
371  break;
372  case isset($issue):
373  // Last modified date (for issues): last modified date.
374  $lastModified = $issue->getLastModified();
375  if (!empty($lastModified)) {
376  $dates[DATACITE_DATE_UPDATED] = $issue->getLastModified();
377  }
378  break;
379  }
380  $datesNode = $doc->createElementNS($deployment->getNamespace(), 'dates');
381  // Issued date: publication date.
382  $dates[DATACITE_DATE_ISSUED] = $publicationDate;
383  // Available date: issue open access date.
384  $availableDate = $issue->getOpenAccessDate();
385  if (!empty($availableDate)) {
386  $dates[DATACITE_DATE_AVAILABLE] = $availableDate;
387  }
388  // Create the date elements for all dates.
389  foreach($dates as $dateType => $date) {
390  // Format the date.
391  $date = date('Y-m-d', strtotime($date));
392  $datesNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'date', $date));
393  $node->setAttribute('dateType', $dateType);
394  }
395  return $datesNode;
396  }
397 
407  function createResourceTypeNode($doc, $issue, $article, $galley, $galleyFile) {
408  $deployment = $this->getDeployment();
409  $resourceTypeNode = null;
410  switch (true) {
411  case isset($galley):
412  if (!$galley->getRemoteURL()) {
413  $genreDao = DAORegistry::getDAO('GenreDAO'); /* @var $genreDao GenreDAO */
414  $genre = $genreDao->getById($galleyFile->getGenreId());
415  if ($genre->getCategory() == GENRE_CATEGORY_DOCUMENT && !$genre->getSupplementary() && !$genre->getDependent()) {
416  $resourceType = 'Article';
417  }
418  } else {
419  $resourceType = 'Article';
420  }
421  break;
422  case isset($article):
423  $resourceType = 'Article';
424  break;
425  case isset($issue):
426  $resourceType = 'Journal Issue';
427  break;
428  default:
429  assert(false);
430  }
431  if (!empty($resourceType)) {
432  // Create the resourceType element.
433  $resourceTypeNode = $doc->createElementNS($deployment->getNamespace(), 'resourceType', $resourceType);
434  $resourceTypeNode->setAttribute('resourceTypeGeneral', 'Text');
435  } else {
436  // It is a supplementary file
437  $resourceTypeNode = $doc->createElementNS($deployment->getNamespace(), 'resourceType');
438  $resourceTypeNode->setAttribute('resourceTypeGeneral', 'Dataset');
439  }
440  return $resourceTypeNode;
441  }
442 
451  function createAlternateIdentifiersNode($doc, $issue, $article, $galley) {
452  $deployment = $this->getDeployment();
453  $context = $deployment->getContext();
454  $alternateIdentifiersNode = $doc->createElementNS($deployment->getNamespace(), 'alternateIdentifiers');
455  // Proprietary ID
456  $proprietaryId = $context->getId();
457  if ($issue) $proprietaryId .= '-' . $issue->getId();
458  if ($article) $proprietaryId .= '-' . $article->getId();
459  if ($galley) $proprietaryId .= '-g' . $galley->getId();
460  $alternateIdentifiersNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'alternateIdentifier', $proprietaryId));
461  $node->setAttribute('alternateIdentifierType', DATACITE_IDTYPE_PROPRIETARY);
462  // ISSN - for issues only.
463  if (!isset($article) && !isset($galley)) {
464  $onlineIssn = $context->getData('onlineIssn');
465  if (!empty($onlineIssn)) {
466  $alternateIdentifiersNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'alternateIdentifier', $onlineIssn));
467  $node->setAttribute('alternateIdentifierType', DATACITE_IDTYPE_EISSN);
468  }
469  $printIssn = $context->getData('printIssn');
470  if (!empty($printIssn)) {
471  $alternateIdentifiersNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'alternateIdentifier', $printIssn));
472  $node->setAttribute('alternateIdentifierType', DATACITE_IDTYPE_ISSN);
473  }
474  }
475  return $alternateIdentifiersNode;
476  }
477 
487  function createRelatedIdentifiersNode($doc, $issue, $article, $publication, $galley) {
488  $deployment = $this->getDeployment();
489  $relatedIdentifiersNode = $doc->createElementNS($deployment->getNamespace(), 'relatedIdentifiers');
490  switch (true) {
491  case isset($galley):
492  // Part of: article.
493  assert(isset($article));
494  $doi = $article->getStoredPubId('doi');
495  if (!empty($doi)) {
496  $relatedIdentifiersNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'relatedIdentifier', htmlspecialchars($doi, ENT_COMPAT, 'UTF-8')));
497  $node->setAttribute('relatedIdentifierType', DATACITE_IDTYPE_DOI);
498  $node->setAttribute('relationType', DATACITE_RELTYPE_ISPARTOF);
499  }
500  break;
501  case isset($article):
502  // Part of: issue.
503  assert(isset($issue));
504  $doi = $issue->getStoredPubId('doi');
505  if (!empty($doi)) {
506  $relatedIdentifiersNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'relatedIdentifier', htmlspecialchars($doi, ENT_COMPAT, 'UTF-8')));
507  $node->setAttribute('relatedIdentifierType', DATACITE_IDTYPE_DOI);
508  $node->setAttribute('relationType', DATACITE_RELTYPE_ISPARTOF);
509  }
510  unset($doi);
511  // Parts: galleys.
512  $galleysByArticle = $publication->getData('galleys');
513  foreach ($galleysByArticle as $relatedGalley) {
514  $doi = $relatedGalley->getStoredPubId('doi');
515  if (!empty($doi)) {
516  $relatedIdentifiersNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'relatedIdentifier', htmlspecialchars($doi, ENT_COMPAT, 'UTF-8')));
517  $node->setAttribute('relatedIdentifierType', DATACITE_IDTYPE_DOI);
518  $node->setAttribute('relationType', DATACITE_RELTYPE_HASPART);
519  }
520  unset($relatedGalley, $doi);
521  }
522  break;
523  case isset($issue):
524  // Parts: articles in this issue.
525  $submissionsIterator = Services::get('submission')->getMany([
526  'contextId' => $issue->getJournalId(),
527  'issueIds' => $issue->getId(),
528  ]);
529  foreach ($submissionsIterator as $relatedArticle) {
530  $doi = $relatedArticle->getStoredPubId('doi');
531  if (!empty($doi)) {
532  $relatedIdentifiersNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'relatedIdentifier', htmlspecialchars($doi, ENT_COMPAT, 'UTF-8')));
533  $node->setAttribute('relatedIdentifierType', DATACITE_IDTYPE_DOI);
534  $node->setAttribute('relationType', DATACITE_RELTYPE_HASPART);
535  }
536  unset($relatedArticle, $doi);
537  }
538  break;
539  }
540  if ($relatedIdentifiersNode->hasChildNodes()) return $relatedIdentifiersNode;
541  else return null;
542  }
543 
555  function createSizesNode($doc, $issue, $article, $publication, $galley, $galleyFile) {
556  $deployment = $this->getDeployment();
557  switch (true) {
558  case isset($galley):
559  // The galley represents the article.
560  $pages = $publication->getData('pages');
561  $files = array($galleyFile);
562  break;
563  case isset($article):
564  $pages = $publication->getData('pages');
565  $files = array();
566  break;
567  case isset($issue):
568  $issueGalleyDao = DAORegistry::getDAO('IssueGalleyDAO'); /* @var $issueGalleyDao IssueGalleyDAO */
569  $files = $issueGalleyDao->getByIssueId($issue->getId());
570  break;
571  default:
572  assert(false);
573  }
574  $sizes = array();
575  if (!empty($pages)) {
576  AppLocale::requireComponents(array(LOCALE_COMPONENT_APP_EDITOR));
577  $sizes[] = $pages . ' ' . __('editor.issues.pages');
578  }
579  foreach($files as $file) { /* @var $file PKPFile */
580  if ($file) {
581  $sizes[] = $file->getNiceFileSize();
582  }
583  unset($file);
584  }
585  $sizesNode = null;
586  if (!empty($sizes)) {
587  $sizesNode = $doc->createElementNS($deployment->getNamespace(), 'sizes');
588  foreach($sizes as $size) {
589  $sizesNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'size', htmlspecialchars($size, ENT_COMPAT, 'UTF-8')));
590  }
591  }
592  return $sizesNode;
593  }
594 
607  function createDescriptionsNode($doc, $issue, $article, $publication, $galley, $galleyFile, $objectLocalePrecedence) {
608  $deployment = $this->getDeployment();
609  $descriptions = array();
610  switch (true) {
611  case isset($galley):
612  if (is_a($galleyFile, 'SupplementaryFile')) {
613  $suppFileDesc = $this->getPrimaryTranslation($galleyFile->getDescription(null), $objectLocalePrecedence);
614  if (!empty($suppFileDesc)) $descriptions[DATACITE_DESCTYPE_OTHER] = $suppFileDesc;
615  }
616  break;
617  case isset($article):
618  $articleAbstract = $this->getPrimaryTranslation($publication->getData('abstract'), $objectLocalePrecedence);
619  if (!empty($articleAbstract)) $descriptions[DATACITE_DESCTYPE_ABSTRACT] = $articleAbstract;
620  break;
621  case isset($issue):
622  $issueDesc = $this->getPrimaryTranslation($issue->getDescription(null), $objectLocalePrecedence);
623  if (!empty($issueDesc)) $descriptions[DATACITE_DESCTYPE_OTHER] = $issueDesc;
624  $descriptions[DATACITE_DESCTYPE_TOC] = $this->getIssueToc($issue, $objectLocalePrecedence);
625  break;
626  default:
627  assert(false);
628  }
629  if (isset($article)) {
630  // Articles and galleys.
631  $descriptions[DATACITE_DESCTYPE_SERIESINFO] = $this->getIssueInformation($issue, $objectLocalePrecedence);
632  }
633  $descriptionsNode = null;
634  if (!empty($descriptions)) {
635  $descriptionsNode = $doc->createElementNS($deployment->getNamespace(), 'descriptions');
636  foreach($descriptions as $descType => $description) {
637  $descriptionsNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'description', htmlspecialchars(PKPString::html2text($description), ENT_COMPAT, 'UTF-8')));
638  $node->setAttribute('descriptionType', $descType);
639  }
640  }
641  return $descriptionsNode;
642  }
643 
644 
645  //
646  // Helper functions
647  //
657  function getObjectLocalePrecedence($context, $article, $publication, $galley) {
658  $locales = array();
659  if (is_a($galley, 'ArticleGalley') && AppLocale::isLocaleValid($galley->getLocale())) {
660  $locales[] = $galley->getLocale();
661  }
662  if (is_a($article, 'Submission')) {
663  if (!is_null($publication->getData('locale'))) {
664  $locales[] = $publication->getData('locale');
665  }
666  }
667  // Use the journal locale as fallback.
668  $locales[] = $context->getPrimaryLocale();
669  // Use form locales as fallback.
670  $formLocales = array_keys($context->getSupportedFormLocaleNames());
671  // Sort form locales alphabetically so that
672  // we get a well-defined order.
673  sort($formLocales);
674  foreach($formLocales as $formLocale) {
675  if (!in_array($formLocale, $locales)) $locales[] = $formLocale;
676  }
677  assert(!empty($locales));
678  return $locales;
679  }
680 
687  function translateLanguageToLocale($language) {
688  $locale = null;
689  if (strlen($language) == 2) {
690  $language = AppLocale::get3LetterFrom2LetterIsoLanguage($language);
691  }
692  if (strlen($language) == 3) {
693  $language = AppLocale::getLocaleFrom3LetterIso($language);
694  }
695  if (AppLocale::isLocaleValid($language)) {
696  $locale = $language;
697  }
698  return $locale;
699  }
700 
711  function getPrimaryTranslation($localizedData, $localePrecedence) {
712  // Check whether we have localized data at all.
713  if (!is_array($localizedData) || empty($localizedData)) return null;
714  // Try all locales from the precedence list first.
715  foreach($localePrecedence as $locale) {
716  if (isset($localizedData[$locale]) && !empty($localizedData[$locale])) {
717  return $localizedData[$locale];
718  }
719  }
720  // As a fallback: use any translation by alphabetical
721  // order of locales.
722  ksort($localizedData);
723  foreach($localizedData as $locale => $value) {
724  if (!empty($value)) return $value;
725  }
726  // If we found nothing (how that?) return null.
727  return null;
728  }
729 
738  function getTranslationsByPrecedence($localizedData, $localePrecedence) {
739  $reorderedLocalizedData = array();
740 
741  // Check whether we have localized data at all.
742  if (!is_array($localizedData) || empty($localizedData)) return $reorderedLocalizedData;
743 
744  // Order by explicit locale precedence first.
745  foreach($localePrecedence as $locale) {
746  if (isset($localizedData[$locale]) && !empty($localizedData[$locale])) {
747  $reorderedLocalizedData[$locale] = $localizedData[$locale];
748  }
749  unset($localizedData[$locale]);
750  }
751 
752  // Order any remaining values alphabetically by locale
753  // and amend the re-ordered array.
754  ksort($localizedData);
755  $reorderedLocalizedData = array_merge($reorderedLocalizedData, $localizedData);
756 
757  return $reorderedLocalizedData;
758  }
759 
768  function getIssueInformation($issue, $objectLocalePrecedence = null) {
769  $deployment = $this->getDeployment();
770  $context = $deployment->getContext();
771  $issueIdentification = $issue->getIssueIdentification();
772  assert(!empty($issueIdentification));
773  if (is_null($objectLocalePrecedence)) {
774  $issueInfo = array();
775  foreach ($context->getName(null) as $locale => $contextName) {
776  $issueInfo[$locale] = "$contextName, $issueIdentification";
777  }
778  } else {
779  $issueInfo = $this->getPrimaryTranslation($context->getName(null), $objectLocalePrecedence);
780  if (!empty($issueInfo)) {
781  $issueInfo .= ', ';
782  }
783  $issueInfo .= $issueIdentification;
784  }
785  return $issueInfo;
786  }
787 
794  function getIssueToc($issue, $objectLocalePrecedence) {
795  $submissionsIterator = Services::get('submission')->getMany([
796  'contextId' => $issue->getJournalId(),
797  'issueIds' => $issue->getId(),
798  ]);
799  $toc = '';
800  foreach ($submissionsIterator as $submissionInIssue) {
801  $currentEntry = $this->getPrimaryTranslation($submissionInIssue->getTitle(null), $objectLocalePrecedence);
802  assert(!empty($currentEntry));
803  $pages = $submissionInIssue->getPages();
804  if (!empty($pages)) {
805  $currentEntry .= '...' . $pages;
806  }
807  $toc .= $currentEntry . "<br />";
808  unset($submissionInIssue);
809  }
810  return $toc;
811  }
812 }
813 
814 
DataciteXmlFilter\getIssueInformation
getIssueInformation($issue, $objectLocalePrecedence=null)
Definition: DataciteXmlFilter.inc.php:768
AppLocale\requireComponents
static requireComponents()
Definition: env1/MockAppLocale.inc.php:56
PKPString\regexp_replace
static regexp_replace($pattern, $replacement, $subject, $limit=-1)
Definition: PKPString.inc.php:279
DataciteXmlFilter\createSizesNode
createSizesNode($doc, $issue, $article, $publication, $galley, $galleyFile)
Definition: DataciteXmlFilter.inc.php:555
DataciteXmlFilter\translateLanguageToLocale
translateLanguageToLocale($language)
Definition: DataciteXmlFilter.inc.php:687
DAORegistry\getDAO
static & getDAO($name, $dbconn=null)
Definition: DAORegistry.inc.php:57
DataciteXmlFilter\createTitlesNode
createTitlesNode($doc, $issue, $publication, $galley, $galleyFile, $objectLocalePrecedence)
Definition: DataciteXmlFilter.inc.php:281
PKPApplication\getCCLicenseBadge
getCCLicenseBadge($ccLicenseURL, $locale=null)
Definition: PKPApplication.inc.php:704
DataciteXmlFilter\getPrimaryTranslation
getPrimaryTranslation($localizedData, $localePrecedence)
Definition: DataciteXmlFilter.inc.php:711
DataciteXmlFilter\getIssueToc
getIssueToc($issue, $objectLocalePrecedence)
Definition: DataciteXmlFilter.inc.php:794
NativeImportExportFilter\getDeployment
getDeployment()
Definition: NativeImportExportFilter.inc.php:49
DataciteXmlFilter\process
& process(&$pubObject)
Definition: DataciteXmlFilter.inc.php:78
NativeExportFilter
Base class that converts a DataObject to a Native XML document.
Definition: NativeExportFilter.inc.php:18
PKPLocale\getLocaleFrom3LetterIso
static getLocaleFrom3LetterIso($iso3Letter)
Definition: PKPLocale.inc.php:671
PKPLocale\get3LetterFrom2LetterIsoLanguage
static get3LetterFrom2LetterIsoLanguage($iso2Letter)
Definition: PKPLocale.inc.php:614
PKPString\html2text
static html2text($html)
Definition: PKPString.inc.php:395
PKPLocale\getIso1FromLocale
static getIso1FromLocale($locale)
Definition: PKPLocale.inc.php:762
DataciteXmlFilter\getTranslationsByPrecedence
getTranslationsByPrecedence($localizedData, $localePrecedence)
Definition: DataciteXmlFilter.inc.php:738
DataciteXmlFilter\createCreatorsNode
createCreatorsNode($doc, $issue, $publication, $galley, $galleyFile, $publisher, $objectLocalePrecedence)
Definition: DataciteXmlFilter.inc.php:236
DataciteXmlFilter\createDatesNode
createDatesNode($doc, $issue, $article, $publication, $galley, $galleyFile, $publicationDate)
Definition: DataciteXmlFilter.inc.php:329
DataciteXmlFilter\getClassName
getClassName()
Definition: DataciteXmlFilter.inc.php:66
DataciteXmlFilter
Class that converts an Issue to a DataCite XML document.
Definition: DataciteXmlFilter.inc.php:50
DataciteXmlFilter\getObjectLocalePrecedence
getObjectLocalePrecedence($context, $article, $publication, $galley)
Definition: DataciteXmlFilter.inc.php:657
DataciteXmlFilter\createDescriptionsNode
createDescriptionsNode($doc, $issue, $article, $publication, $galley, $galleyFile, $objectLocalePrecedence)
Definition: DataciteXmlFilter.inc.php:607
DataciteXmlFilter\createRootNode
createRootNode($doc)
Definition: DataciteXmlFilter.inc.php:217
DataciteXmlFilter\createRelatedIdentifiersNode
createRelatedIdentifiersNode($doc, $issue, $article, $publication, $galley)
Definition: DataciteXmlFilter.inc.php:487
Filter\setDisplayName
setDisplayName($displayName)
Definition: Filter.inc.php:140
PKPLocale\isLocaleValid
static isLocaleValid($locale)
Definition: PKPLocale.inc.php:505
DataciteXmlFilter\createResourceTypeNode
createResourceTypeNode($doc, $issue, $article, $galley, $galleyFile)
Definition: DataciteXmlFilter.inc.php:407
DataciteXmlFilter\createAlternateIdentifiersNode
createAlternateIdentifiersNode($doc, $issue, $article, $galley)
Definition: DataciteXmlFilter.inc.php:451
PKPServices\get
static get($service)
Definition: PKPServices.inc.php:49
DataciteXmlFilter\__construct
__construct($filterGroup)
Definition: DataciteXmlFilter.inc.php:55