17 define(
'DATACITE_TITLETYPE_TRANSLATED',
'TranslatedTitle');
18 define(
'DATACITE_TITLETYPE_ALTERNATIVE',
'AlternativeTitle');
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');
29 define(
'DATACITE_IDTYPE_PROPRIETARY',
'publisherId');
30 define(
'DATACITE_IDTYPE_EISSN',
'EISSN');
31 define(
'DATACITE_IDTYPE_ISSN',
'ISSN');
32 define(
'DATACITE_IDTYPE_DOI',
'DOI');
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');
42 define(
'DATACITE_DESCTYPE_ABSTRACT',
'Abstract');
43 define(
'DATACITE_DESCTYPE_SERIESINFO',
'SeriesInformation');
44 define(
'DATACITE_DESCTYPE_TOC',
'TableOfContents');
45 define(
'DATACITE_DESCTYPE_OTHER',
'Other');
47 import(
'lib.pkp.plugins.importexport.native.filter.NativeExportFilter');
57 parent::__construct($filterGroup);
67 return 'plugins.importexport.datacite.filter.DataciteXmlFilter';
80 $doc =
new DOMDocument(
'1.0',
'utf-8');
81 $doc->preserveWhiteSpace =
false;
82 $doc->formatOutput =
true;
84 $context = $deployment->getContext();
85 $plugin = $deployment->getPlugin();
86 $cache = $plugin->getCache();
89 $issue = $article = $galley = $galleyFile =
null;
90 if (is_a($pubObject,
'Issue')) {
92 if (!$cache->isCached(
'issues', $issue->getId())) {
93 $cache->add($issue,
null);
95 } elseif (is_a($pubObject,
'Submission')) {
96 $article = $pubObject;
97 if (!$cache->isCached(
'articles', $article->getId())) {
98 $cache->add($article,
null);
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'));
107 $article =
Services::get(
'submission')->get($publication->getData(
'submissionId'));
108 if ($article) $cache->add($article,
null);
112 $issueId = $article->getCurrentPublication()->getData(
'issueId');
113 if ($cache->isCached(
'issues', $issueId)) {
114 $issue = $cache->get(
'issues', $issueId);
117 $issue = $issueDao->getById($issueId, $context->getId());
118 if ($issue) $cache->add($issue,
null);
123 $publication = $article ? $article->getCurrentPublication() :
null;
130 assert(!empty($publisher));
133 $publicationDate = $publication->getData(
'datePublished');
135 if (empty($publicationDate)) {
136 $publicationDate = $issue->getDatePublished();
138 assert(!empty($publicationDate));
142 $doc->appendChild($rootNode);
144 $doi = $pubObject->getStoredPubId(
'doi');
145 if ($plugin->isTestMode($context)) {
148 $rootNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(),
'identifier', htmlspecialchars($doi, ENT_COMPAT,
'UTF-8')));
149 $node->setAttribute(
'identifierType', DATACITE_IDTYPE_DOI);
151 $rootNode->appendChild($this->
createCreatorsNode($doc, $issue, $publication, $galley, $galleyFile, $publisher, $objectLocalePrecedence));
153 $rootNode->appendChild($this->
createTitlesNode($doc, $issue, $publication, $galley, $galleyFile, $objectLocalePrecedence));
155 $rootNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(),
'publisher', htmlspecialchars($publisher, ENT_COMPAT,
'UTF-8')));
157 $rootNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(),
'publicationYear', date(
'Y', strtotime($publicationDate))));
160 if (!empty($galleyFile) && is_a($galleyFile,
'SupplementaryFile')) {
162 } elseif (!empty($article) && !empty($publication)) {
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);
171 $rootNode->appendChild($this->
createDatesNode($doc, $issue, $article, $publication, $galley, $galleyFile, $publicationDate));
173 $rootNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(),
'language',
AppLocale::getIso1FromLocale($objectLocalePrecedence[0])));
176 if ($resourceTypeNode) $rootNode->appendChild($resourceTypeNode);
181 if ($relatedIdentifiersNode) $rootNode->appendChild($relatedIdentifiersNode);
183 $sizesNode = $this->
createSizesNode($doc, $issue, $article, $publication, $galley, $galleyFile);
184 if ($sizesNode) $rootNode->appendChild($sizesNode);
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);
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);
203 $descriptionsNode = $this->
createDescriptionsNode($doc, $issue, $article, $publication, $galley, $galleyFile, $objectLocalePrecedence);
204 if ($descriptionsNode) $rootNode->appendChild($descriptionsNode);
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());
236 function createCreatorsNode($doc, $issue, $publication, $galley, $galleyFile, $publisher, $objectLocalePrecedence) {
240 case (isset($galleyFile) && is_a($galleyFile,
'SupplementaryFile')):
243 if (!empty($creator)) {
244 $creators[] = $creator;
249 case isset($publication):
251 $authors = $publication->getData(
'authors');
252 assert(!empty($authors));
253 foreach ($authors as $author) {
254 $creators[] = $author->getFullName(
false,
true);
258 $creators[] = $publisher;
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);
268 return $creatorsNode;
281 function createTitlesNode($doc, $issue, $publication, $galley, $galleyFile, $objectLocalePrecedence) {
284 $alternativeTitle =
null;
286 case (isset($galleyFile) && is_a($galleyFile,
'SupplementaryFile')):
287 $titles = $galleyFile->getName(
null);
289 case isset($publication):
290 $titles = $publication->getData(
'title');
300 assert(count($titles)>=1);
301 $titlesNode = $doc->createElementNS($deployment->getNamespace(),
'titles');
303 $primaryTitle = array_shift($titles);
304 $titlesNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(),
'title', htmlspecialchars(
PKPString::html2text($primaryTitle), ENT_COMPAT,
'UTF-8')));
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);
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);
329 function createDatesNode($doc, $issue, $article, $publication, $galley, $galleyFile, $publicationDate) {
333 case isset($galleyFile):
334 if (is_a($galleyFile,
'SupplementaryFile')) {
336 $createdDate = $galleyFile->getDateCreated();
337 if (!empty($createdDate)) {
338 $dates[DATACITE_DATE_CREATED] = $createdDate;
342 $acceptedDate = $galleyFile->getDateUploaded();
343 if (!empty($acceptedDate)) {
344 $dates[DATACITE_DATE_ACCEPTED] = $acceptedDate;
347 $lastModified = $galleyFile->getDateModified();
348 if (!empty($lastModified)) {
349 $dates[DATACITE_DATE_UPDATED] = $lastModified;
352 case isset($article):
354 $submittedDate = $article->getData(
'dateSubmitted');
355 if (!empty($submittedDate)) {
356 $dates[DATACITE_DATE_SUBMITTED] = $submittedDate;
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'];
367 $lastModified = $publication->getData(
'lastModified');
368 if (!empty($lastModified)) {
369 $dates[DATACITE_DATE_UPDATED] = $lastModified;
374 $lastModified = $issue->getLastModified();
375 if (!empty($lastModified)) {
376 $dates[DATACITE_DATE_UPDATED] = $issue->getLastModified();
380 $datesNode = $doc->createElementNS($deployment->getNamespace(),
'dates');
382 $dates[DATACITE_DATE_ISSUED] = $publicationDate;
384 $availableDate = $issue->getOpenAccessDate();
385 if (!empty($availableDate)) {
386 $dates[DATACITE_DATE_AVAILABLE] = $availableDate;
389 foreach($dates as $dateType => $date) {
391 $date = date(
'Y-m-d', strtotime($date));
392 $datesNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(),
'date', $date));
393 $node->setAttribute(
'dateType', $dateType);
409 $resourceTypeNode =
null;
412 if (!$galley->getRemoteURL()) {
414 $genre = $genreDao->getById($galleyFile->getGenreId());
415 if ($genre->getCategory() == GENRE_CATEGORY_DOCUMENT && !$genre->getSupplementary() && !$genre->getDependent()) {
416 $resourceType =
'Article';
419 $resourceType =
'Article';
422 case isset($article):
423 $resourceType =
'Article';
426 $resourceType =
'Journal Issue';
431 if (!empty($resourceType)) {
433 $resourceTypeNode = $doc->createElementNS($deployment->getNamespace(),
'resourceType', $resourceType);
434 $resourceTypeNode->setAttribute(
'resourceTypeGeneral',
'Text');
437 $resourceTypeNode = $doc->createElementNS($deployment->getNamespace(),
'resourceType');
438 $resourceTypeNode->setAttribute(
'resourceTypeGeneral',
'Dataset');
440 return $resourceTypeNode;
453 $context = $deployment->getContext();
454 $alternateIdentifiersNode = $doc->createElementNS($deployment->getNamespace(),
'alternateIdentifiers');
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);
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);
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);
475 return $alternateIdentifiersNode;
489 $relatedIdentifiersNode = $doc->createElementNS($deployment->getNamespace(),
'relatedIdentifiers');
493 assert(isset($article));
494 $doi = $article->getStoredPubId(
'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);
501 case isset($article):
503 assert(isset($issue));
504 $doi = $issue->getStoredPubId(
'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);
512 $galleysByArticle = $publication->getData(
'galleys');
513 foreach ($galleysByArticle as $relatedGalley) {
514 $doi = $relatedGalley->getStoredPubId(
'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);
520 unset($relatedGalley, $doi);
525 $submissionsIterator =
Services::get(
'submission')->getMany([
526 'contextId' => $issue->getJournalId(),
527 'issueIds' => $issue->getId(),
529 foreach ($submissionsIterator as $relatedArticle) {
530 $doi = $relatedArticle->getStoredPubId(
'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);
536 unset($relatedArticle, $doi);
540 if ($relatedIdentifiersNode->hasChildNodes())
return $relatedIdentifiersNode;
555 function createSizesNode($doc, $issue, $article, $publication, $galley, $galleyFile) {
560 $pages = $publication->getData(
'pages');
561 $files = array($galleyFile);
563 case isset($article):
564 $pages = $publication->getData(
'pages');
569 $files = $issueGalleyDao->getByIssueId($issue->getId());
575 if (!empty($pages)) {
577 $sizes[] = $pages .
' ' . __(
'editor.issues.pages');
579 foreach($files as $file) {
581 $sizes[] = $file->getNiceFileSize();
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')));
609 $descriptions = array();
612 if (is_a($galleyFile,
'SupplementaryFile')) {
613 $suppFileDesc = $this->
getPrimaryTranslation($galleyFile->getDescription(
null), $objectLocalePrecedence);
614 if (!empty($suppFileDesc)) $descriptions[DATACITE_DESCTYPE_OTHER] = $suppFileDesc;
617 case isset($article):
618 $articleAbstract = $this->
getPrimaryTranslation($publication->getData(
'abstract'), $objectLocalePrecedence);
619 if (!empty($articleAbstract)) $descriptions[DATACITE_DESCTYPE_ABSTRACT] = $articleAbstract;
623 if (!empty($issueDesc)) $descriptions[DATACITE_DESCTYPE_OTHER] = $issueDesc;
624 $descriptions[DATACITE_DESCTYPE_TOC] = $this->
getIssueToc($issue, $objectLocalePrecedence);
629 if (isset($article)) {
631 $descriptions[DATACITE_DESCTYPE_SERIESINFO] = $this->
getIssueInformation($issue, $objectLocalePrecedence);
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);
641 return $descriptionsNode;
660 $locales[] = $galley->getLocale();
662 if (is_a($article,
'Submission')) {
663 if (!is_null($publication->getData(
'locale'))) {
664 $locales[] = $publication->getData(
'locale');
668 $locales[] = $context->getPrimaryLocale();
670 $formLocales = array_keys($context->getSupportedFormLocaleNames());
674 foreach($formLocales as $formLocale) {
675 if (!in_array($formLocale, $locales)) $locales[] = $formLocale;
677 assert(!empty($locales));
689 if (strlen($language) == 2) {
692 if (strlen($language) == 3) {
713 if (!is_array($localizedData) || empty($localizedData))
return null;
715 foreach($localePrecedence as $locale) {
716 if (isset($localizedData[$locale]) && !empty($localizedData[$locale])) {
717 return $localizedData[$locale];
722 ksort($localizedData);
723 foreach($localizedData as $locale => $value) {
724 if (!empty($value))
return $value;
739 $reorderedLocalizedData = array();
742 if (!is_array($localizedData) || empty($localizedData))
return $reorderedLocalizedData;
745 foreach($localePrecedence as $locale) {
746 if (isset($localizedData[$locale]) && !empty($localizedData[$locale])) {
747 $reorderedLocalizedData[$locale] = $localizedData[$locale];
749 unset($localizedData[$locale]);
754 ksort($localizedData);
755 $reorderedLocalizedData = array_merge($reorderedLocalizedData, $localizedData);
757 return $reorderedLocalizedData;
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";
780 if (!empty($issueInfo)) {
783 $issueInfo .= $issueIdentification;
795 $submissionsIterator =
Services::get(
'submission')->getMany([
796 'contextId' => $issue->getJournalId(),
797 'issueIds' => $issue->getId(),
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;
807 $toc .= $currentEntry .
"<br />";
808 unset($submissionInIssue);