23 import(
'lib.pkp.classes.submission.SubmissionFile');
25 $candidateFiles = array();
28 foreach ($galleys as $galley) {
29 $galleyFiles = $submissionFileDao->getLatestRevisionsByAssocId(ASSOC_TYPE_GALLEY, $galley->getId(), $galley->getSubmissionId(), SUBMISSION_FILE_PROOF);
30 foreach ($galleyFiles as $galleyFile) {
36 if (empty($candidateFiles)) {
37 $layoutFiles = $submissionFileDao->getLatestRevisions($article->getId(), SUBMISSION_FILE_PRODUCTION_READY);
38 foreach ($layoutFiles as $layoutFile) {
44 HookRegistry::call(
'OAIMetadataFormat_JATS::findJats', array(&$this, &$candidateFiles, &$doc));
47 if (!$doc && empty($candidateFiles)) {
50 if (count($candidateFiles) > 1) error_log(
'WARNING: More than one JATS XML candidate documents were located for submission ' . $article->getId() .
'.');
54 $candidateFile = array_shift($candidateFiles);
55 $doc =
new DOMDocument;
56 $doc->loadXML(file_get_contents($candidateFile->getFilePath()));
65 public function toXml($record, $format =
null) {
67 $journal = $record->getData(
'journal');
68 $article = $record->getData(
'article');
69 $galleys = $record->getData(
'galleys');
70 $section = $record->getData(
'section');
71 $issue = $record->getData(
'issue');
74 import(
'classes.issue.IssueAction');
77 if ($subscriptionRequired && !$subscriptionRequired) {
78 $oaiDao->oai->error(
'cannotDisseminateFormat',
'Cannot disseminate format (JATS XML not available)');
81 $doc = $this->
_findJats($article, $galleys);
83 $oaiDao->oai->error(
'cannotDisseminateFormat',
'Cannot disseminate format (JATS XML not available)');
88 return $doc->saveXml($doc->getElementsByTagName(
'article')->item(0));
98 $permittedElementOrders = array(
99 'article-meta' => array(
'article-id',
'article-categories',
'title-group',
'contrib-group',
'aff',
'aff-alternatives',
'x',
'author-notes',
'pub-date',
'volume',
'volume-id',
'volume-series',
'issue',
'issue-id',
'issue-title',
'issue-sponsor',
'issue-part',
'isbn',
'supplement',
'fpage',
'lpage',
'page-range',
'elocation-id',
'email',
'ext-link',
'uri',
'product',
'supplementary-material',
'history',
'permissions',
'self-uri',
'related-article',
'related-object',
'abstract',
'trans-abstract',
'kwd-group',
'funding-group',
'conference',
'counts',
'custom-meta-group'),
100 'journal-meta' => array(
'journal-id',
'journal-title-group',
'contrib-group',
'aff',
'aff-alternatives',
'issn',
'issn-l',
'isbn',
'publisher',
'notes',
'self-uri',
'custom-meta-group'),
102 assert(isset($permittedElementOrders[$parentNode->nodeName]));
103 $order = $permittedElementOrders[$parentNode->nodeName];
104 $position = array_search($childNode->nodeName, $order);
105 assert($position !==
false);
107 $followingElements = array_slice($order, $position);
108 $followingElement =
null;
109 foreach ($parentNode->childNodes as $node) {
110 if (in_array($node->nodeName, $followingElements)) {
111 $followingElement = $node;
116 return $parentNode->insertBefore($childNode, $followingElement);
128 $xpath =
new DOMXPath($doc);
129 $articleMetaNode = $xpath->query(
'//article/front/article-meta')->item(0);
130 $journalMetaNode = $xpath->query(
'//article/front/journal-meta')->item(0);
131 if (!$journalMetaNode) {
132 $frontNode = $xpath->query(
'//article/front')->item(0);
133 $journalMetaNode = $this->
_addChildInOrder($frontNode, $doc->createElement(
'journal-meta'));
137 $xpath->query(
'//article')->item(0)->setAttribute(
'xml:lang', substr($article->getLocale(),0,2));
140 if ($datePublished = $article->getDatePublished()) {
141 $datePublished = strtotime($datePublished);
142 $match = $xpath->query(
"//article/front/article-meta/pub-date[@date-type='pub' and publication-format='epub']");
143 if ($match->length) {
145 $dateNode = $match->item(0);
146 while ($dateNode->hasChildNodes()) $dateNode->removeChild($dateNode->firstChild);
149 $dateNode = $this->
_addChildInOrder($articleMetaNode, $doc->createElement(
'pub-date'));
150 $dateNode->setAttribute(
'date-type',
'pub');
151 $dateNode->setAttribute(
'publication-format',
'epub');
154 $dateNode->setAttribute(
'iso-8601-date', strftime(
'%Y-%m-%d', $datePublished));
155 $dateNode->appendChild($doc->createElement(
'day'))->nodeValue = strftime(
'%d', $datePublished);
156 $dateNode->appendChild($doc->createElement(
'month'))->nodeValue = strftime(
'%m', $datePublished);
157 $dateNode->appendChild($doc->createElement(
'year'))->nodeValue = strftime(
'%Y', $datePublished);
161 if ($issue && $issue->getShowYear()) $issueYear = $issue->getYear();
162 if (!$issueYear && $datePublished) $issueYear = strftime(
'%Y', $datePublished);
164 $match = $xpath->query(
"//article/front/article-meta/pub-date[@date-type='issue' and publication-format='epub']");
165 if ($match->length) {
167 $dateNode = $match->item(0);
168 while ($dateNode->hasChildNodes()) $dateNode->removeChild($dateNode->firstChild);
171 $dateNode = $this->
_addChildInOrder($articleMetaNode, $doc->createElement(
'pub-date'));
172 $dateNode->setAttribute(
'date-type',
'issue');
173 $dateNode->setAttribute(
'publication-format',
'epub');
175 $dateNode->setAttribute(
'iso-8601-date', strftime(
'%Y-%m-%d', $datePublished));
176 $dateNode->appendChild($doc->createElement(
'day'))->nodeValue = strftime(
'%d', $datePublished);
177 $dateNode->appendChild($doc->createElement(
'month'))->nodeValue = strftime(
'%m', $datePublished);
178 $dateNode->appendChild($doc->createElement(
'year'))->nodeValue = strftime(
'%Y', $datePublished);
182 $titleGroupNode = $xpath->query(
'//article/front/article-meta/title-group')->item(0);
183 foreach ($titleGroupNode->getElementsByTagName(
'article-title') as $titleNode) $titleGroupNode->removeChild($titleNode);
184 foreach ($article->getTitle(
null) as $locale => $title) {
185 $titleNode = $titleGroupNode->appendChild($doc->createElement(
'article-title'));
186 $titleNode->setAttribute(
'xml:lang', substr($locale,0,2));
187 $titleNode->nodeValue = $title;
193 $config = HTMLPurifier_Config::createDefault();
194 $config->set(
'HTML.Allowed',
'p');
195 $config->set(
'Cache.SerializerPath',
'cache');
196 $purifier =
new HTMLPurifier($config);
198 foreach ($articleMetaNode->getElementsByTagName(
'abstract') as $abstractNode) $articleMetaNode->removeChild($abstractNode);
199 foreach ((array) $article->getAbstract(
null) as $locale => $abstract) {
200 $abstractNode = $this->
_addChildInOrder($articleMetaNode, $doc->createElement(
'abstract'));
201 $abstractNode->setAttribute(
'xml:lang', substr($locale,0,2));
202 $abstractNode->nodeValue = $purifier->purify($abstract);
206 $match = $xpath->query(
"//article/front/journal-meta/journal-id[@journal-id-type='publisher-id']");
207 if ($match->length) $match->item(0)->nodeValue = $journal->getPath();
209 $journalIdNode = $this->
_addChildInOrder($journalMetaNode, $doc->createElement(
'journal-id'));
210 $journalIdNode->setAttribute(
'journal-id-type',
'publisher-id');
211 $journalIdNode->nodeValue = $journal->getPath();
215 if ($doi = trim($article->getStoredPubId(
'doi'))) {
216 $match = $xpath->query(
"//article/front/article-meta/article-id[@pub-id-type='doi']");
217 if ($match->length) $match->item(0)->nodeValue = $doi;
219 $articleIdNode = $this->
_addChildInOrder($articleMetaNode, $doc->createElement(
'article-id'));
220 $articleIdNode->setAttribute(
'pub-id-type',
'doi');
221 $articleIdNode->nodeValue = $doi;
226 $match = $xpath->query(
'//article/front/article-meta/permissions');
227 $copyrightHolder = $article->getLocalizedCopyrightHolder($article->getLocale());
228 $copyrightYear = $article->getCopyrightYear();
229 $licenseUrl = $article->getLicenseURL();
230 if (!$match->length && ($copyrightHolder || $copyrightYear || $licenseUrl)) {
231 $permissionsNode = $this->
_addChildInOrder($articleMetaNode, $doc->createElement(
'permissions'));
232 if ($copyrightYear) $permissionsNode->appendChild($doc->createElement(
'copyright-year'))->nodeValue = $copyrightYear;
233 if ($copyrightHolder) $permissionsNode->appendChild($doc->createElement(
'copyright-holder'))->nodeValue = $copyrightHolder;
235 $licenseNode = $permissionsNode->appendChild($doc->createElement(
'license'));
236 $licenseNode->setAttribute(
'xlink:href', $licenseUrl);
241 $match = $xpath->query(
"//article/front/article-meta/article-categories");
242 if ($match->length) $articleCategoriesNode = $match->item(0);
244 $articleCategoriesNode = $this->
_addChildInOrder($articleMetaNode, $doc->createElement(
'article-categories'));
246 $match = $xpath->query(
'//article/front/article-meta/subj-group[@subj-group-type="heading"]');
247 if ($match->length) $subjGroupNode = $match->item(0);
249 $subjGroupNode = $articleCategoriesNode->appendChild($doc->createElement(
'subj-group'));
250 $subjGroupNode->setAttribute(
'subj-group-type',
'heading');
252 $subjectNode = $subjGroupNode->appendChild($doc->createElement(
'subject'));
253 $subjectNode->nodeValue = $section->getTitle($journal->getPrimaryLocale());
257 $articleIds = array_map(
function($publishedArticle) {
258 return $publishedArticle->getId();
259 }, $publishedArticleDao->getPublishedArticles($issue->getId()));
260 foreach (array(
'volume',
'number') as $nodeName) {
261 $match = $xpath->query(
"//article/front/article-meta/$nodeName");
262 if ($match->length) $match->item(0)->setAttribute(
'seq', array_search($article->getId(), $articleIds));
266 $match = $xpath->query(
"//article/front/article-meta/issue-id");
267 if ($match->length) $match->item(0)->nodeValue = $issue->getId();
269 $issueIdNode = $this->
_addChildInOrder($articleMetaNode, $doc->createElement(
'issue-id'));
270 $issueIdNode->nodeValue = $issue->getId();
274 if ($articleType = trim($section->getLocalizedIdentifyType())) {
275 $articleNode = $xpath->query(
"//article")->item(0);
276 $articleNode->setAttribute(
'article-type', $articleType);
281 $userGroups = $userGroupDao->getByContextId($journal->getId());
282 $journalMetaNode = $xpath->query(
'//article/front/journal-meta')->item(0);
283 $contribGroupNode = $this->
_addChildInOrder($journalMetaNode, $doc->createElement(
'contrib-group'));
284 $keyContribTypeMapping = array(
285 'default.groups.name.manager' =>
'jmanager',
286 'default.groups.name.editor' =>
'editor',
287 'default.groups.name.sectionEditor' =>
'secteditor',
289 while ($userGroup = $userGroups->next()) {
290 if (!isset($keyContribTypeMapping[$userGroup->getData(
'nameLocaleKey')]))
continue;
292 $users = $userGroupDao->getUsersById($userGroup->getId());
293 while ($user = $users->next()) {
294 $contribNode = $contribGroupNode->appendChild($doc->createElement(
'contrib'));
295 $contribNode->setAttribute(
'contrib-type', $keyContribTypeMapping[$userGroup->getData(
'nameLocaleKey')]);
296 $nameNode = $contribNode->appendChild($doc->createElement(
'name'));
297 $surnameNode = $nameNode->appendChild($doc->createElement(
'surname'));
298 $surnameNode->nodeValue = method_exists($user,
'getLastName')?$user->getLastName():$user->getLocalizedFamilyName();
299 $givenNamesNode = $nameNode->appendChild($doc->createElement(
'given-names'));
300 $givenNamesNode->nodeValue = method_exists($user,
'getFirstName')?$user->getFirstName():$user->getLocalizedGivenName();
301 if (method_exists($user,
'getMiddleName') && $s = $user->getMiddleName()) $givenNamesNode->nodeValue .=
" $s";
314 if (!in_array($submissionFile->getFileType(), array(
'application/xml',
'text/xml')))
return false;
316 static $genres = array();
318 $genreId = $submissionFile->getGenreId();
319 if (!isset($genres[$genreId])) $genres[$genreId] = $genreDao->getById($genreId);
320 assert($genres[$genreId]);
321 $genre = $genres[$genreId];
324 if ($genre->getCategory() != GENRE_CATEGORY_DOCUMENT)
return false;
325 if ($genre->getDependent())
return false;
326 if ($genre->getSupplementary())
return false;