/** * @covers PKPLocale */ public function testGet3LetterIsoFromLocale() { self::assertEquals('eng', AppLocale::get3LetterIsoFromLocale('en_US')); self::assertEquals('por', AppLocale::get3LetterIsoFromLocale('pt_BR')); self::assertEquals('por', AppLocale::get3LetterIsoFromLocale('pt_PT')); self::assertNull(AppLocale::get3LetterIsoFromLocale('xx_XX')); }
/** * @see OAIMetadataFormat#toXml */ function toXml(&$record, $format = null) { $article = $record->getData('article'); $journal = $record->getData('journal'); $templateMgr = TemplateManager::getManager(); $templateMgr->assign(array('journal' => $journal, 'article' => $article, 'issue' => $record->getData('issue'), 'section' => $record->getData('section'))); $subjects = array_merge_recursive($this->stripAssocArray((array) $article->getDiscipline(null)), $this->stripAssocArray((array) $article->getSubject(null)), $this->stripAssocArray((array) $article->getSubjectClass(null))); $templateMgr->assign(array('subject' => isset($subjects[$journal->getPrimaryLocale()]) ? $subjects[$journal->getPrimaryLocale()] : '', 'abstract' => String::html2text($article->getAbstract($article->getLocale())), 'language' => AppLocale::get3LetterIsoFromLocale($article->getLocale()))); return $templateMgr->fetch(dirname(__FILE__) . '/record.tpl'); }
/** * Create a hierarchical array that represents the MODS DOM * from the meta-data description. * * @param $doc XMLNode|DOMDocument the MODS document node. * @param $root XMLNode|DOMDocument the root node of the * MODS document. * @param $mods34Description MetadataDescription * @return array a hierarchical array of XMLNode|DOMDocument objects * representing the MODS document. */ function &_buildDocumentHierarchy(&$doc, &$root, &$mods34Description) { // Get the MODS schema. $mods34Schema =& $mods34Description->getMetadataSchema(); if (is_a($mods34Schema, 'Mods34Schema')) { // Identify the cataloging language. assert($mods34Description->hasStatement('recordInfo/languageOfCataloging/languageTerm[@authority="iso639-2b"]')); $catalogingLanguage = $mods34Description->getStatement('recordInfo/languageOfCataloging/languageTerm[@authority="iso639-2b"]'); } else { // This must be a MODS name schema. assert(is_a($mods34Schema, 'Mods34NameSchema')); $catalogingLanguage = 'undefined'; } // Initialize the document hierarchy with the root node. $documentHierarchy = array('@branch' => &$root); // Find the translations required for top-level elements. // We need this array later because we'll have to repeat non-translated // values for every translated top-level element. $properties = $mods34Description->getProperties(); $translations = array(); foreach ($properties as $propertyName => $property) { /* @var $property MetadataProperty */ if ($mods34Description->hasStatement($propertyName)) { $nodes = explode('/', $propertyName); $topLevelNode = array_shift($nodes); if (!isset($translations[$topLevelNode])) { $translations[$topLevelNode] = array(); } if ($property->getTranslated()) { foreach ($mods34Description->getStatementTranslations($propertyName) as $locale => $value) { $isoLanguage = AppLocale::get3LetterIsoFromLocale($locale); if (!in_array($isoLanguage, $translations[$topLevelNode])) { $translations[$topLevelNode][] = $isoLanguage; } } } else { if (!in_array($catalogingLanguage, $translations[$topLevelNode])) { $translations[$topLevelNode][] = $catalogingLanguage; } } } } // Build the document hierarchy. foreach ($properties as $propertyName => $property) { /* @var $property MetadataProperty */ if ($mods34Description->hasStatement($propertyName)) { // Get relevant property attributes. $translated = $property->getTranslated(); $cardinality = $property->getCardinality(); // Get the XML element hierarchy. $nodes = explode('/', $propertyName); $hierarchyDepth = count($nodes) - 1; // Normalize property values to an array of translated strings. if ($translated) { // Only the main MODS schema can contain translated values. assert(is_a($mods34Schema, 'Mods34Schema')); // Retrieve the translated values of the statement. $localizedValues =& $mods34Description->getStatementTranslations($propertyName); // Translate the PKP locale into ISO639-2b 3-letter codes. $translatedValues = array(); foreach ($localizedValues as $locale => $translatedValue) { $isoLanguage = AppLocale::get3LetterIsoFromLocale($locale); assert(!is_null($isoLanguage)); $translatedValues[$isoLanguage] = $translatedValue; } } else { // Untranslated statements will be repeated for all languages // present in the top-level element. $untranslatedValue =& $mods34Description->getStatement($propertyName); $translatedValues = array(); assert(isset($translations[$nodes[0]])); foreach ($translations[$nodes[0]] as $isoLanguage) { $translatedValues[$isoLanguage] = $untranslatedValue; } } // Normalize all values to arrays so that we can // handle them uniformly. $translatedValueArrays = array(); foreach ($translatedValues as $isoLanguage => $translatedValue) { if ($cardinality == METADATA_PROPERTY_CARDINALITY_ONE) { assert(is_scalar($translatedValue)); $translatedValueArrays[$isoLanguage] = array(&$translatedValue); } else { assert(is_array($translatedValue)); $translatedValueArrays[$isoLanguage] =& $translatedValue; } unset($translatedValue); } // Add the translated values one by one to the element hierarchy. foreach ($translatedValueArrays as $isoLanguage => $translatedValueArray) { foreach ($translatedValueArray as $translatedValue) { // Add a language attribute to the top-level element if // it differs from the cataloging language. $translatedNodes = $nodes; if ($isoLanguage != $catalogingLanguage) { assert(strpos($translatedNodes[0], '[') === false); $translatedNodes[0] .= '[@lang="' . $isoLanguage . '"]'; } // Create the node hierarchy for the statement. $currentNodeList =& $documentHierarchy; foreach ($translatedNodes as $nodeDepth => $nodeName) { // Are we at a leaf node? if ($nodeDepth == $hierarchyDepth) { // Is this a top-level attribute? if (substr($nodeName, 0, 1) == '[') { assert($nodeDepth == 0); assert($translated == false); assert($cardinality == METADATA_PROPERTY_CARDINALITY_ONE); assert(!is_object($translatedValue)); $attributeName = trim($nodeName, '[@"]'); XMLCustomWriter::setAttribute($root, $attributeName, (string) $translatedValue); continue; } // This is a sub-element. if (isset($currentNodeList[$nodeName])) { // Only properties with cardinality "many" can // have more than one leaf node. assert($cardinality == METADATA_PROPERTY_CARDINALITY_MANY); // Check that the leaf list is actually there. assert(isset($currentNodeList[$nodeName]['@leaves'])); // We should never find any branch in a leaves node. assert(!isset($currentNodeList[$nodeName]['@branch'])); } else { // Create the leaf list in the hierarchy. $currentNodeList[$nodeName]['@leaves'] = array(); } if (is_a($translatedValue, 'MetadataDescription')) { // Recursively process composite properties. $leafNode =& $this->_processCompositeProperty($doc, $propertyName, $translatedValue); } else { // Cast scalar values to string types for XML binding. $translatedValue = (string) $translatedValue; // Create the leaf element. $leafNode =& $this->_createNode($doc, $nodeName, $translatedValue); } // Add the leaf element to the leaves list. $currentNodeList[$nodeName]['@leaves'][] =& $leafNode; unset($leafNode); } else { // This is a branch node. // Has the branch already been created? If not: create it. if (isset($currentNodeList[$nodeName])) { // Check that the branch node is actually there. assert(isset($currentNodeList[$nodeName]['@branch'])); // We should never find any leaves in a branch node. assert(!isset($currentNodeList[$nodeName]['@leaves'])); } else { // Create the branch node. $branchNode =& $this->_createNode($doc, $nodeName); // Add the branch node list and add the new node as it's root element. $currentNodeList[$nodeName] = array('@branch' => &$branchNode); unset($branchNode); } } // Set the node list pointer to the sub-element $currentNodeList =& $currentNodeList[$nodeName]; } } } } } return $documentHierarchy; }
/** * Create a description text element. * * @param $locale string * @param $description string * * @return XMLNode|DOMImplementation */ function &_otherTextElement($locale, $description) { $otherTextElement =& XMLCustomWriter::createElement($this->getDoc(), 'OtherText'); // Text Type XMLCustomWriter::createChildWithText($this->getDoc(), $otherTextElement, 'TextTypeCode', O4DOI_TEXT_TYPE_MAIN_DESCRIPTION); // Text Language $language = AppLocale::get3LetterIsoFromLocale($locale); assert(!empty($language)); // Text element and attributes $attributes = array('textformat' => O4DOI_TEXTFORMAT_ASCII, 'language' => $language); $textElement =& $this->createElementWithText('Text', $description, $attributes); XMLCustomWriter::appendChild($otherTextElement, $textElement); return $otherTextElement; }
/** * @see MetadataDataObjectAdapter::extractMetadataFromDataObject() * @param $submission Submission * @return MetadataDescription */ function extractMetadataFromDataObject(&$submission) { assert(is_a($submission, 'Submission')); $mods34Description = $this->instantiateMetadataDescription(); // Retrieve the primary locale. $catalogingLocale = AppLocale::getPrimaryLocale(); $catalogingLanguage = AppLocale::get3LetterIsoFromLocale($catalogingLocale); // Establish the association between the meta-data description // and the submission. $mods34Description->setAssocId($submission->getId()); // Title $localizedTitles = $submission->getTitle(null); // Localized $this->addLocalizedStatements($mods34Description, 'titleInfo/title', $localizedTitles); // Authors // FIXME: Move this to a dedicated adapter in the Author class. $authors = $submission->getAuthors(); foreach ($authors as $author) { /* @var $author Author */ // Create a new name description. $authorDescription = new MetadataDescription('lib.pkp.plugins.metadata.mods34.schema.Mods34NameSchema', ASSOC_TYPE_AUTHOR); // Type $authorType = 'personal'; $authorDescription->addStatement('[@type]', $authorType); // Family Name $authorDescription->addStatement('namePart[@type="family"]', $author->getLastName()); // Given Names $firstName = (string) $author->getFirstName(); $middleName = (string) $author->getMiddleName(); $givenNames = trim($firstName . ' ' . $middleName); if (!empty($givenNames)) { $authorDescription->addStatement('namePart[@type="given"]', $givenNames); } // Affiliation // NB: Our MODS mapping currently doesn't support translation for names. // This can be added when required by data consumers. We therefore only use // translations in the cataloging language. $affiliation = $author->getAffiliation($catalogingLocale); if ($affiliation) { $authorDescription->addStatement('affiliation', $affiliation); } // Terms of address (unmapped field) $termsOfAddress = $author->getData('nlm34:namePart[@type="termsOfAddress"]'); if ($termsOfAddress) { $authorDescription->addStatement('namePart[@type="termsOfAddress"]', $termsOfAddress); } // Date (unmapped field) $date = $author->getData('nlm34:namePart[@type="date"]'); if ($date) { $authorDescription->addStatement('namePart[@type="date"]', $date); } // Role $authorDescription->addStatement('role/roleTerm[@type="code" @authority="marcrelator"]', 'aut'); // Add the author to the MODS schema. $mods34Description->addStatement('name', $authorDescription); unset($authorDescription); } // Sponsor // NB: Our MODS mapping currently doesn't support translation for names. // This can be added when required by data consumers. We therefore only use // translations in the cataloging language. $supportingAgency = $submission->getSponsor($catalogingLocale); if ($supportingAgency) { $supportingAgencyDescription = new MetadataDescription('lib.pkp.plugins.metadata.mods34.schema.Mods34NameSchema', ASSOC_TYPE_AUTHOR); $sponsorNameType = 'corporate'; $supportingAgencyDescription->addStatement('[@type]', $sponsorNameType); $supportingAgencyDescription->addStatement('namePart', $supportingAgency); $sponsorRole = 'spn'; $supportingAgencyDescription->addStatement('role/roleTerm[@type="code" @authority="marcrelator"]', $sponsorRole); $mods34Description->addStatement('name', $supportingAgencyDescription); } // Type of resource $typeOfResource = 'text'; $mods34Description->addStatement('typeOfResource', $typeOfResource); // Creation & copyright date $submissionDate = $submission->getDateSubmitted(); if (strlen($submissionDate) >= 4) { $mods34Description->addStatement('originInfo/dateCreated[@encoding="w3cdtf"]', $submissionDate); $mods34Description->addStatement('originInfo/copyrightDate[@encoding="w3cdtf"]', substr($submissionDate, 0, 4)); } // Submission language $language = $submission->getLanguage(); if ($language) { $submissionLanguage = AppLocale::get3LetterFrom2LetterIsoLanguage($submission->getLanguage()); } else { $submissionLanguage = null; } if (!$submissionLanguage) { // Assume the cataloging language by default. $submissionLanguage = $catalogingLanguage; } $mods34Description->addStatement('language/languageTerm[@type="code" @authority="iso639-2b"]', $submissionLanguage); // Pages (extent) $mods34Description->addStatement('physicalDescription/extent', $submission->getPages()); // Abstract $localizedAbstracts =& $submission->getAbstract(null); // Localized $this->addLocalizedStatements($mods34Description, 'abstract', $localizedAbstracts); // Discipline $localizedDisciplines = $submission->getDiscipline(null); // Localized $this->addLocalizedStatements($mods34Description, 'subject/topic', $localizedDisciplines); // Subject $localizedSubjects = $submission->getSubject(null); // Localized $this->addLocalizedStatements($mods34Description, 'subject/topic', $localizedSubjects); // FIXME: Coverage not included // Record creation date $recordCreationDate = date('Y-m-d'); $mods34Description->addStatement('recordInfo/recordCreationDate[@encoding="w3cdtf"]', $recordCreationDate); // Record identifier $mods34Description->addStatement('recordInfo/recordIdentifier[@source="pkp"]', $submission->getId()); // Cataloging language $mods34Description->addStatement('recordInfo/languageOfCataloging/languageTerm[@authority="iso639-2b"]', $catalogingLanguage); // Handle unmapped fields. $this->extractUnmappedDataObjectMetadataFields($submission, $mods34Description); return $mods34Description; }
/** * @see DOIExportDom::generate() */ function &generate(&$object) { $falseVar = false; // Declare variables that will contain publication objects. $journal =& $this->getJournal(); $issue = null; /* @var $issue Issue */ $article = null; /* @var $article PublishedArticle */ $galley = null; /* @var $galley ArticleGalley */ $suppFile = null; /* @var $suppFile SuppFile */ $articlesByIssue = null; $galleysByArticle = null; $suppFilesByArticle = null; // Retrieve required publication objects (depends on the object to be exported). $pubObjects =& $this->retrievePublicationObjects($object); extract($pubObjects); // Identify an object implementing an ArticleFile (if any). $articleFile = empty($suppFile) ? $galley : $suppFile; // Identify the object locale. $objectLocalePrecedence = $this->getObjectLocalePrecedence($article, $galley, $suppFile); // The publisher is required. $publisher = is_a($object, 'SuppFile') ? $object->getSuppFilePublisher() : null; if (empty($publisher)) { $publisher = $this->getPublisher($objectLocalePrecedence); } // The publication date is required. $publicationDate = is_a($article, 'PublishedArticle') ? $article->getDatePublished() : null; if (empty($publicationDate)) { $publicationDate = $issue->getDatePublished(); } assert(!empty($publicationDate)); // Create the XML document and its root element. $doc =& $this->getDoc(); $rootElement =& $this->rootElement(); XMLCustomWriter::appendChild($doc, $rootElement); // DOI (mandatory) if (($identifierElement =& $this->_identifierElement($object)) === false) { return false; } XMLCustomWriter::appendChild($rootElement, $identifierElement); // Creators (mandatory) XMLCustomWriter::appendChild($rootElement, $this->_creatorsElement($object, $objectLocalePrecedence, $publisher)); // Title (mandatory) XMLCustomWriter::appendChild($rootElement, $this->_titlesElement($object, $objectLocalePrecedence)); // Publisher (mandatory) XMLCustomWriter::createChildWithText($this->getDoc(), $rootElement, 'publisher', $publisher); // Publication Year (mandatory) XMLCustomWriter::createChildWithText($this->getDoc(), $rootElement, 'publicationYear', date('Y', strtotime($publicationDate))); // Subjects if (!empty($suppFile)) { $this->_appendNonMandatoryChild($rootElement, $this->_subjectsElement($suppFile, $objectLocalePrecedence)); } elseif (!empty($article)) { $this->_appendNonMandatoryChild($rootElement, $this->_subjectsElement($article, $objectLocalePrecedence)); } // Dates XMLCustomWriter::appendChild($rootElement, $this->_datesElement($issue, $article, $articleFile, $suppFile, $publicationDate)); // Language XMLCustomWriter::createChildWithText($this->getDoc(), $rootElement, 'language', AppLocale::get3LetterIsoFromLocale($objectLocalePrecedence[0])); // Resource Type if (!is_a($object, 'SuppFile')) { $resourceTypeElement =& $this->_resourceTypeElement($object); XMLCustomWriter::appendChild($rootElement, $resourceTypeElement); } // Alternate Identifiers $this->_appendNonMandatoryChild($rootElement, $this->_alternateIdentifiersElement($object, $issue, $article, $articleFile)); // Related Identifiers $this->_appendNonMandatoryChild($rootElement, $this->_relatedIdentifiersElement($object, $articlesByIssue, $galleysByArticle, $suppFilesByArticle, $issue, $article)); // Sizes $sizesElement =& $this->_sizesElement($object, $article); if ($sizesElement) { XMLCustomWriter::appendChild($rootElement, $sizesElement); } // Formats if (!empty($articleFile)) { XMLCustomWriter::appendChild($rootElement, $this->_formatsElement($articleFile)); } // Rights $rights = $this->getPrimaryTranslation($journal->getSetting('copyrightNotice', null), $objectLocalePrecedence); if (!empty($rights)) { XMLCustomWriter::createChildWithText($this->getDoc(), $rootElement, 'rights', $rights); } // Descriptions $descriptionsElement =& $this->_descriptionsElement($issue, $article, $suppFile, $objectLocalePrecedence, $articlesByIssue); if ($descriptionsElement) { XMLCustomWriter::appendChild($rootElement, $descriptionsElement); } return $doc; }
/** * Create a description text node. * @param $doc DOMDocument * @param $locale string * @param $description string * @return DOMElement */ function createOtherTextNode($doc, $locale, $description) { $deployment = $this->getDeployment(); $otherTextNode = $doc->createElementNS($deployment->getNamespace(), 'OtherText'); // Text Type $otherTextNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'TextTypeCode', O4DOI_TEXT_TYPE_MAIN_DESCRIPTION)); // Text $language = AppLocale::get3LetterIsoFromLocale($locale); assert(!empty($language)); $otherTextNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'Text', htmlspecialchars(PKPString::html2text($description), ENT_COMPAT, 'UTF-8'))); $node->setAttribute('textformat', O4DOI_TEXTFORMAT_ASCII); $node->setAttribute('language', $language); return $otherTextNode; }
/** * Create a content item node. * @param $doc DOMDocument * @param $issue Issue * @param $article PublishedArticle * @param $galley ArticleGalley * @param $objectLocalePrecedence array * @return DOMElement */ function createContentItemNode($doc, $issue, $article, $galley, $objectLocalePrecedence) { $deployment = $this->getDeployment(); $context = $deployment->getContext(); $plugin = $deployment->getPlugin(); $contentItemNode = $doc->createElementNS($deployment->getNamespace(), 'ContentItem'); // Sequence number $seq = $article->getSequence(); assert(!empty($seq)); $contentItemNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'SequenceNumber', $seq)); // Number of pages $pages = $article->getPages(); if (is_numeric($pages)) { $pages = (int) $pages; } else { // If the field is not numeric then try to parse it (eg. "pp. 3-8"). if (preg_match("/([0-9]+)\\s*-\\s*([0-9]+)/i", $pages, $matches)) { if (is_numeric($matches[1]) && is_numeric($matches[2])) { $firstPage = (int) $matches[1]; $lastPage = (int) $matches[2]; $pages = $lastPage - $firstPage + 1; } } } if (is_integer($pages)) { $textItemNode = $doc->createElementNS($deployment->getNamespace(), 'TextItem'); $textItemNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'NumberOfPages', $pages)); $contentItemNode->appendChild($textItemNode); } // Extent (for article-as-manifestation only) if ($galley && !$galley->getRemoteURL()) { $galleyFile = $galley->getFile(); $contentItemNode->appendChild($this->createExtentNode($doc, $galleyFile)); } // Article Title (mandatory) $titles = $this->getTranslationsByPrecedence($article->getTitle(null), $objectLocalePrecedence); assert(!empty($titles)); foreach ($titles as $locale => $title) { $contentItemNode->appendChild($this->createTitleNode($doc, $locale, $title, O4DOI_TITLE_TYPE_FULL)); } // Contributors $authors = $article->getAuthors(); assert(!empty($authors)); foreach ($authors as $author) { $contentItemNode->appendChild($this->createContributorNode($doc, $author, $objectLocalePrecedence)); } // Language $languageCode = AppLocale::get3LetterIsoFromLocale($objectLocalePrecedence[0]); assert(!empty($languageCode)); $languageNode = $doc->createElementNS($deployment->getNamespace(), 'Language'); $languageNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'LanguageRole', O4DOI_LANGUAGE_ROLE_LANGUAGE_OF_TEXT)); $languageNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'LanguageCode', $languageCode)); $contentItemNode->appendChild($languageNode); // Article keywords // SubjectClass will be left out here, because we don't know the scheme/classification name $submissionKeywordDao = DAORegistry::getDAO('SubmissionKeywordDAO'); $allKeywords = $submissionKeywordDao->getKeywords($article->getId(), $context->getSupportedSubmissionLocales()); $keywords = $this->getPrimaryTranslation($allKeywords, $objectLocalePrecedence); if (!empty($keywords)) { $keywordsString = implode(';', $keywords); $contentItemNode->appendChild($this->createSubjectNode($doc, O4DOI_SUBJECT_SCHEME_PUBLISHER, $keywordsString)); } // Object Description 'OtherText' $descriptions = $this->getTranslationsByPrecedence($article->getAbstract(null), $objectLocalePrecedence); foreach ($descriptions as $locale => $description) { $contentItemNode->appendChild($this->createOtherTextNode($doc, $locale, $description)); } // Article Publication Date $datePublished = $article->getDatePublished(); if (!empty($datePublished)) { $contentItemNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'PublicationDate', date('Ymd', strtotime($datePublished)))); } // Relations // Issue if ($plugin->getSetting($context->getId(), 'exportIssuesAs') == O4DOI_ISSUE_AS_WORK) { // related work: // - is part of issue-as-work $issueWorkOrProduct = 'Work'; } else { // related product: // - is part of issue-as-manifestation $issueWorkOrProduct = 'Product'; } $issueProprietaryId = $context->getId() . '-' . $issue->getId(); $relatedIssueIds = array(O4DOI_ID_TYPE_PROPRIETARY => $issueProprietaryId); $issueDoi = $issue->getStoredPubId('doi'); if (!empty($issueDoi)) { $relatedIssueIds[O4DOI_ID_TYPE_DOI] = $issueDoi; } $relatedIssueNode = $this->createRelatedNode($doc, $issueWorkOrProduct, O4DOI_RELATION_IS_PART_OF, $relatedIssueIds); // Galleys $galleyDao = DAORegistry::getDAO('ArticleGalleyDAO'); /* @var $galleyDao ArticleGalleyDAO */ $galleysByArticle = $galleyDao->getBySubmissionId($article->getId())->toArray(); if (!$galley) { // if exporting object is an article $contentItemNode->appendChild($relatedIssueNode); // related products: // - is manifested in articles-as-manifestation foreach ($galleysByArticle as $relatedGalley) { $galleyProprietaryId = $context->getId() . '-' . $issue->getId() . '-' . $article->getId() . '-g' . $relatedGalley->getId(); $relatedGalleyIds = array(O4DOI_ID_TYPE_PROPRIETARY => $galleyProprietaryId); $galleyDoi = $relatedGalley->getStoredPubId('doi'); if (!empty($galleyDoi)) { $relatedGalleyIds[O4DOI_ID_TYPE_DOI] = $galleyDoi; } $contentItemNode->appendChild($this->createRelatedNode($doc, 'Product', O4DOI_RELATION_IS_MANIFESTED_IN, $relatedGalleyIds)); unset($relatedGalley, $relatedGalleyIds, $galleyProprietaryId, $galleyDoi); } } else { // Include issue-as-work before article-as-work. if ($issueWorkOrProduct == 'Work') { $contentItemNode->appendChild($relatedIssueNode); } // related work: // - is a manifestation of article-as-work $articleProprietaryId = $context->getId() . '-' . $article->getIssueId() . '-' . $article->getId(); $relatedArticleIds = array(O4DOI_ID_TYPE_PROPRIETARY => $articleProprietaryId); $doi = $article->getStoredPubId('doi'); if (!empty($doi)) { $relatedArticleIds[O4DOI_ID_TYPE_DOI] = $doi; } $contentItemNode->appendChild($this->createRelatedNode($doc, 'Work', O4DOI_RELATION_IS_A_MANIFESTATION_OF, $relatedArticleIds)); unset($relatedArticleIds); // Include issue-as-manifestation after article-as-work. if ($issueWorkOrProduct == 'Product') { $contentItemNode->appendChild($relatedIssueNode); } // related products: foreach ($galleysByArticle as $relatedGalley) { $galleyProprietaryId = $context->getId() . '-' . $issue->getId() . '-' . $article->getId() . '-g' . $relatedGalley->getId(); $relatedGalleyIds = array(O4DOI_ID_TYPE_PROPRIETARY => $galleyProprietaryId); $galleyDoi = $relatedGalley->getStoredPubId('doi'); if (!empty($galleyDoi)) { $relatedGalleyIds[O4DOI_ID_TYPE_DOI] = $galleyDoi; } // - is a different form of all other articles-as-manifestation // with the same article id and language but different form if ($galley->getLocale() == $relatedGalley->getLocale() && $galley->getLabel() != $relatedGalley->getLabel()) { $contentItemNode->appendChild($this->createRelatedNode($doc, 'Product', O4DOI_RELATION_IS_A_DIFFERENT_FORM_OF, $relatedGalleyIds)); } // - is a different language version of all other articles-as-manifestation // with the same article id and form/label but different language if ($galley->getLabel() == $relatedGalley->getLabel() && $galley->getLocale() != $relatedGalley->getLocale()) { $contentItemNode->appendChild($this->createRelatedNode($doc, 'Product', O4DOI_RELATION_IS_A_LANGUAGE_VERSION_OF, $relatedGalleyIds)); } unset($relatedGalley, $relatedGalleyIds, $galleyProprietaryId, $galleyDoi); } } return $contentItemNode; }
/** * @see Filter::process() * @param $pubObjects array Array of PublishedArticles * @return DOMDocument */ function &process(&$pubObjects) { // Create the XML document $doc = new DOMDocument('1.0', 'utf-8'); $doc->preserveWhiteSpace = false; $doc->formatOutput = true; $deployment = $this->getDeployment(); $context = $deployment->getContext(); $plugin = $deployment->getPlugin(); $cache = $plugin->getCache(); // Create the root node $rootNode = $this->createRootNode($doc); $doc->appendChild($rootNode); foreach ($pubObjects as $pubObject) { $issueId = $pubObject->getIssueId(); if ($cache->isCached('issues', $issueId)) { $issue = $cache->get('issues', $issueId); } else { $issueDao = DAORegistry::getDAO('IssueDAO'); /* @var $issueDao IssueDAO */ $issue = $issueDao->getById($issueId, $context->getId()); if ($issue) { $cache->add($issue, null); } } // Record $recordNode = $doc->createElement('record'); $rootNode->appendChild($recordNode); // Language $language = AppLocale::get3LetterIsoFromLocale($pubObject->getLocale()); if (!empty($language)) { $recordNode->appendChild($node = $doc->createElement('language', $language)); } // Publisher name (i.e. institution name) $publisher = $context->getSetting('publisherInstitution'); if (!empty($publisher)) { $recordNode->appendChild($node = $doc->createElement('publisher', htmlspecialchars($publisher, ENT_COMPAT, 'UTF-8'))); } // Journal's title (M) $journalTitle = $context->getName($context->getPrimaryLocale()); $recordNode->appendChild($node = $doc->createElement('journalTitle', htmlspecialchars($journalTitle, ENT_COMPAT, 'UTF-8'))); // Identification Numbers $issn = $context->getSetting('printIssn'); if (!empty($issn)) { $recordNode->appendChild($node = $doc->createElement('issn', $issn)); } $eissn = $context->getSetting('onlineIssn'); if (!empty($eissn)) { $recordNode->appendChild($node = $doc->createElement('eissn', $eissn)); } // Article's publication date, volume, issue if ($pubObject->getDatePublished()) { $recordNode->appendChild($node = $doc->createElement('publicationDate', $this->formatDate($pubObject->getDatePublished()))); } else { $recordNode->appendChild($node = $doc->createElement('publicationDate', $this->formatDate($issue->getDatePublished()))); } $volume = $issue->getVolume(); if (!empty($volume) && $issue->getShowVolume()) { $recordNode->appendChild($node = $doc->createElement('volume', htmlspecialchars($volume, ENT_COMPAT, 'UTF-8'))); } $issueNumber = $issue->getNumber(); if (!empty($issueNumber) && $issue->getShowNumber()) { $recordNode->appendChild($node = $doc->createElement('issue', htmlspecialchars($issueNumber, ENT_COMPAT, 'UTF-8'))); } /** --- FirstPage / LastPage (from PubMed plugin)--- * there is some ambiguity for online journals as to what * "page numbers" are; for example, some journals (eg. JMIR) * use the "e-location ID" as the "page numbers" in PubMed */ $pages = $pubObject->getPages(); if (preg_match("/([0-9]+)\\s*-\\s*([0-9]+)/i", $pages, $matches)) { // simple pagination (eg. "pp. 3-8") $recordNode->appendChild($node = $doc->createElement('startPage', htmlspecialchars($matches[1], ENT_COMPAT, 'UTF-8'))); $recordNode->appendChild($node = $doc->createElement('endPage', htmlspecialchars($matches[2], ENT_COMPAT, 'UTF-8'))); } elseif (preg_match("/(e[0-9]+)/i", $pages, $matches)) { // elocation-id (eg. "e12") $recordNode->appendChild($node = $doc->createElement('startPage', htmlspecialchars($matches[1], ENT_COMPAT, 'UTF-8'))); $recordNode->appendChild($node = $doc->createElement('endPage', htmlspecialchars($matches[1], ENT_COMPAT, 'UTF-8'))); } // DOI $doi = $pubObject->getStoredPubId('doi'); if (!empty($doi)) { $recordNode->appendChild($node = $doc->createElement('doi', htmlspecialchars($doi, ENT_COMPAT, 'UTF-8'))); } // publisherRecordId $recordNode->appendChild($node = $doc->createElement('publisherRecordId', htmlspecialchars($pubObject->getId(), ENT_COMPAT, 'UTF-8'))); // documentType $type = $pubObject->getType($pubObject->getLocale()); if (!empty($type)) { $recordNode->appendChild($node = $doc->createElement('documentType', htmlspecialchars($type, ENT_COMPAT, 'UTF-8'))); } // Article title foreach ((array) $pubObject->getTitle(null) as $locale => $title) { if (!empty($title)) { $recordNode->appendChild($node = $doc->createElement('title', htmlspecialchars($title, ENT_COMPAT, 'UTF-8'))); $node->setAttribute('language', AppLocale::get3LetterIsoFromLocale($locale)); } } // Authors and affiliations $authorsNode = $doc->createElement('authors'); $recordNode->appendChild($authorsNode); $affilList = $this->createAffiliationsList($pubObject->getAuthors(), $pubObject); foreach ($pubObject->getAuthors() as $author) { $authorsNode->appendChild($this->createAuthorNode($doc, $pubObject, $author, $affilList)); } if (!empty($affilList[0])) { $affilsNode = $doc->createElement('affiliationsList'); $recordNode->appendChild($affilsNode); for ($i = 0; $i < count($affilList); $i++) { $affilsNode->appendChild($node = $doc->createElement('affiliationName', htmlspecialchars($affilList[$i], ENT_COMPAT, 'UTF-8'))); $node->setAttribute('affiliationId', $i); } } // Abstract foreach ((array) $pubObject->getAbstract(null) as $locale => $abstract) { if (!empty($abstract)) { $recordNode->appendChild($node = $doc->createElement('abstract', htmlspecialchars(PKPString::html2text($abstract), ENT_COMPAT, 'UTF-8'))); $node->setAttribute('language', AppLocale::get3LetterIsoFromLocale($locale)); } } // FullText URL $recordNode->appendChild($node = $doc->createElement('fullTextUrl', htmlspecialchars(Request::url(null, 'article', 'view', $pubObject->getId()), ENT_COMPAT, 'UTF-8'))); $node->setAttribute('format', 'html'); // Keywords $keywordsNode = $doc->createElement('keywords'); $recordNode->appendChild($keywordsNode); $subjects = array_map('trim', explode(';', $pubObject->getSubject($pubObject->getLocale()))); foreach ($subjects as $keyword) { if (!empty($keyword)) { $keywordsNode->appendChild($node = $doc->createElement('keyword', htmlspecialchars($keyword, ENT_COMPAT, 'UTF-8'))); } } } return $doc; }
/** * Create a title node. * @param $doc DOMDocument * @param $locale string e.g. 'en_US' * @param $localizedTitle string * @param $titleType string One of the O4DOI_TITLE_TYPE_* constants. * @return DOMElement */ function createTitleNode($doc, $locale, $localizedTitle, $titleType) { $deployment = $this->getDeployment(); $titleNode = $doc->createElementNS($deployment->getNamespace(), 'Title'); // Text format $titleNode->setAttribute('textformat', O4DOI_TEXTFORMAT_ASCII); // Language $language = AppLocale::get3LetterIsoFromLocale($locale); assert(!empty($language)); $titleNode->setAttribute('language', $language); // Title type (mandatory) $titleNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'TitleType', $titleType)); // Title text (mandatory) $titleNode->appendChild($node = $doc->createElementNS($deployment->getNamespace(), 'TitleText', PKPString::html2text($localizedTitle))); return $titleNode; }