/** * Try to translate an ISO language code to an OJS locale. * @param $language string 2- or 3-letter ISO language code * @return string|null An OJS locale or null if no matching * locale could be found. */ function translateLanguageToLocale($language) { $locale = null; if (strlen($language) == 2) { $language = AppLocale::get3LetterFrom2LetterIsoLanguage($language); } if (strlen($language) == 3) { $language = AppLocale::getLocaleFrom3LetterIso($language); } if (AppLocale::isLocaleValid($language)) { $locale = $language; } return $locale; }
/** * @see MetadataDataObjectAdapter::injectMetadataIntoDataObject() * @param $metadataDescription MetadataDescription * @param $targetDataObject Submission */ function &injectMetadataIntoDataObject(&$metadataDescription, &$targetDataObject) { assert(is_a($targetDataObject, 'Submission')); assert($metadataDescription->getMetadataSchemaName() == 'plugins.metadata.mods34.schema.Mods34Schema'); // Get the cataloging language. $catalogingLanguage = $metadataDescription->getStatement('recordInfo/languageOfCataloging/languageTerm[@authority="iso639-2b"]'); $catalogingLocale = AppLocale::getLocaleFrom3LetterIso($catalogingLanguage); assert(!is_null($catalogingLocale)); // Title $localizedTitles = $metadataDescription->getStatementTranslations('titleInfo/title'); if (is_array($localizedTitles)) { foreach ($localizedTitles as $locale => $title) { $targetDataObject->setTitle($title, $locale); } } // Names: authors and sponsor $foundSponsor = false; $nameDescriptions =& $metadataDescription->getStatement('name'); if (is_array($nameDescriptions)) { foreach ($nameDescriptions as $nameDescription) { /* @var $nameDescription MetadataDescription */ // Check that we find the expected name schema. assert($nameDescription->getMetadataSchemaName() == 'lib.pkp.plugins.metadata.mods34.schema.Mods34NameSchema'); // Retrieve the name type and role. $nameType = $nameDescription->getStatement('[@type]'); $nameRoles = $nameDescription->getStatement('role/roleTerm[@type="code" @authority="marcrelator"]'); // Transport the name into the submission depending // on name type and role. // FIXME: Move this to a dedicated adapter in the Author class. if (is_array($nameRoles)) { switch ($nameType) { // Authors case 'personal': // Only authors go into the submission. if (in_array('aut', $nameRoles)) { // Instantiate a new author object. $authorDao = DAORegistry::getDAO('AuthorDAO'); /* @var $authorDao AuthorDAO */ $author = $authorDao->newDataObject(); // Family Name $author->setLastName($nameDescription->getStatement('namePart[@type="family"]')); // Given Names $givenNames = $nameDescription->getStatement('namePart[@type="given"]'); if (!empty($givenNames)) { $givenNames = explode(' ', $givenNames, 2); if (isset($givenNames[0])) { $author->setFirstName($givenNames[0]); } if (isset($givenNames[1])) { $author->setMiddleName($givenNames[1]); } } // Affiliation // NB: Our MODS mapping currently doesn't support translation for names. // This can be added when required by data providers. We assume the cataloging // language for the record. $affiliation = $nameDescription->getStatement('affiliation'); if (!empty($affiliation)) { $author->setAffiliation($affiliation, $catalogingLocale); } // Terms of address (unmapped field) $termsOfAddress = $nameDescription->getStatement('namePart[@type="termsOfAddress"]'); if ($termsOfAddress) { $author->setData('nlm34:namePart[@type="termsOfAddress"]', $termsOfAddress); } // Date (unmapped field) $date = $nameDescription->getStatement('namePart[@type="date"]'); if ($date) { $author->setData('nlm34:namePart[@type="date"]', $date); } // Add the author to the submission. $authorDao->insertObject($author); unset($author); } break; // Sponsor // NB: Our MODS mapping currently doesn't support translation for names. // This can be added when required by data providers. We assume the cataloging // language for the record. // Sponsor // NB: Our MODS mapping currently doesn't support translation for names. // This can be added when required by data providers. We assume the cataloging // language for the record. case 'corporate': // Only the first sponsor goes into the submission. if (!$foundSponsor && in_array('spn', $nameRoles)) { $foundSponsor = true; $targetDataObject->setSponsor($nameDescription->getStatement('namePart'), $catalogingLocale); } break; } } unset($nameDescription); } } // Creation date $dateSubmitted = $metadataDescription->getStatement('originInfo/dateCreated[@encoding="w3cdtf"]'); if ($dateSubmitted) { $targetDataObject->setDateSubmitted($dateSubmitted); } // Submission language $submissionLanguage = $metadataDescription->getStatement('language/languageTerm[@type="code" @authority="iso639-2b"]'); $submissionLocale = AppLocale::get2LetterFrom3LetterIsoLanguage($submissionLanguage); if ($submissionLocale) { $targetDataObject->setLanguage($submissionLocale); } // Pages (extent) $pages = $metadataDescription->getStatement('physicalDescription/extent'); if ($pages) { $targetDataObject->setPages($pages); } // Abstract $localizedAbstracts = $metadataDescription->getStatementTranslations('abstract'); if (is_array($localizedAbstracts)) { foreach ($localizedAbstracts as $locale => $abstract) { $targetDataObject->setAbstract($abstract, $locale); } } // Discipline, subject class and subject // FIXME: We currently ignore discipline, subject class and subject because we cannot // distinguish them within a list of MODS topic elements. Can we use several subject // statements with different authorities instead? // FIXME: We do not include coverage information at the moment. // Record identifier // NB: We currently don't override the submission id with the record identifier in MODS // to make sure that MODS records can be transported between different installations. // Handle unmapped fields. $this->injectUnmappedDataObjectMetadataFields($metadataDescription, $targetDataObject); return $targetDataObject; }
/** * @covers PKPLocale */ public function testGetLocaleFrom3LetterIso() { // A locale that does not have to be disambiguated. self::assertEquals('en_US', AppLocale::getLocaleFrom3LetterIso('eng')); // The primary locale will be used if that helps // to disambiguate. AppLocale::setSupportedLocales(array('en_US' => 'English', 'pt_BR' => 'Portuguese (Brazil)', 'pt_PT' => 'Portuguese (Portugal)')); AppLocale::setPrimaryLocale('pt_BR'); self::assertEquals('pt_BR', AppLocale::getLocaleFrom3LetterIso('por')); AppLocale::setPrimaryLocale('pt_PT'); self::assertEquals('pt_PT', AppLocale::getLocaleFrom3LetterIso('por')); // If the primary locale doesn't help then use the first supported locale found. AppLocale::setPrimaryLocale('en_US'); self::assertEquals('pt_BR', AppLocale::getLocaleFrom3LetterIso('por')); AppLocale::setSupportedLocales(array('en_US' => 'English', 'pt_PT' => 'Portuguese (Portugal)', 'pt_BR' => 'Portuguese (Brazil)')); self::assertEquals('pt_PT', AppLocale::getLocaleFrom3LetterIso('por')); // If the locale isn't even in the supported localse then use the first locale found. AppLocale::setSupportedLocales(array('en_US' => 'English')); self::assertEquals('pt_PT', AppLocale::getLocaleFrom3LetterIso('por')); // Unknown language. self::assertNull(AppLocale::getLocaleFrom3LetterIso('xxx')); }
/** * Add the metadata XML of a single article to an * XML article list. * * @param $articleDoc DOMDocument * @param $article PublishedArticle * @param $journal Journal * @param $markToDelete boolean If true the returned XML * will only contain a deletion marker. */ function _addArticleXml(&$articleDoc, &$article, &$journal, $markToDelete = false) { assert(is_a($article, 'Article')); // Get the root node of the list. assert(is_a($articleDoc, 'DOMDocument')); $articleList =& $articleDoc->documentElement; // Create a new article node. $articleNode =& XMLCustomWriter::createElement($articleDoc, 'article'); // Add ID information. XMLCustomWriter::setAttribute($articleNode, 'id', $article->getId()); XMLCustomWriter::setAttribute($articleNode, 'sectionId', $article->getSectionId()); XMLCustomWriter::setAttribute($articleNode, 'journalId', $article->getJournalId()); XMLCustomWriter::setAttribute($articleNode, 'instId', $this->_instId); // Set the load action. $loadAction = $markToDelete ? 'delete' : 'replace'; XMLCustomWriter::setAttribute($articleNode, 'loadAction', $loadAction); XMLCustomWriter::appendChild($articleList, $articleNode); // The XML for an article marked to be deleted contains no metadata. if ($markToDelete) { return; } assert(is_a($article, 'PublishedArticle')); // Add authors. $authors = $article->getAuthors(); if (!empty($authors)) { $authorList =& XMLCustomWriter::createElement($articleDoc, 'authorList'); foreach ($authors as $author) { /* @var $author Author */ XMLCustomWriter::createChildWithText($articleDoc, $authorList, 'author', $author->getFullName(true)); } XMLCustomWriter::appendChild($articleNode, $authorList); } // We need the request to retrieve locales and build URLs. $request = PKPApplication::getRequest(); // Get all supported locales. $site = $request->getSite(); $supportedLocales = $site->getSupportedLocales() + array_keys($journal->getSupportedLocaleNames()); assert(!empty($supportedLocales)); // Add titles. $titleList =& XMLCustomWriter::createElement($articleDoc, 'titleList'); // Titles are used for sorting, we therefore need // them in all supported locales. assert(!empty($supportedLocales)); foreach ($supportedLocales as $locale) { $localizedTitle = $article->getLocalizedTitle($locale); if (!is_null($localizedTitle)) { // Add the localized title. $titleNode =& XMLCustomWriter::createChildWithText($articleDoc, $titleList, 'title', $localizedTitle); XMLCustomWriter::setAttribute($titleNode, 'locale', $locale); // If the title does not exist in the given locale // then use the localized title for sorting only. $title = $article->getTitle($locale); $sortOnly = empty($title) ? 'true' : 'false'; XMLCustomWriter::setAttribute($titleNode, 'sortOnly', $sortOnly); } } XMLCustomWriter::appendChild($articleNode, $titleList); // Add abstracts. $abstracts = $article->getAbstract(null); // return all locales if (!empty($abstracts)) { $abstractList =& XMLCustomWriter::createElement($articleDoc, 'abstractList'); foreach ($abstracts as $locale => $abstract) { $abstractNode =& XMLCustomWriter::createChildWithText($articleDoc, $abstractList, 'abstract', $abstract); XMLCustomWriter::setAttribute($abstractNode, 'locale', $locale); } XMLCustomWriter::appendChild($articleNode, $abstractList); } // Add discipline. $disciplines = $article->getDiscipline(null); // return all locales if (!empty($disciplines)) { $disciplineList =& XMLCustomWriter::createElement($articleDoc, 'disciplineList'); foreach ($disciplines as $locale => $discipline) { $disciplineNode =& XMLCustomWriter::createChildWithText($articleDoc, $disciplineList, 'discipline', $discipline); XMLCustomWriter::setAttribute($disciplineNode, 'locale', $locale); } XMLCustomWriter::appendChild($articleNode, $disciplineList); } // Add subjects and subject classes. $subjectClasses = $article->getSubjectClass(null); $subjects = $article->getSubject(null); if (!empty($subjectClasses) || !empty($subjects)) { $subjectList =& XMLCustomWriter::createElement($articleDoc, 'subjectList'); if (!is_array($subjectClasses)) { $subjectClasses = array(); } if (!is_array($subjects)) { $subjects = array(); } $locales = array_unique(array_merge(array_keys($subjectClasses), array_keys($subjects))); foreach ($locales as $locale) { $subject = ''; if (isset($subjectClasses[$locale])) { $subject .= $subjectClasses[$locale]; } if (isset($subjects[$locale])) { if (!empty($subject)) { $subject .= ' '; } $subject .= $subjects[$locale]; } $subjectNode =& XMLCustomWriter::createChildWithText($articleDoc, $subjectList, 'subject', $subject); XMLCustomWriter::setAttribute($subjectNode, 'locale', $locale); } XMLCustomWriter::appendChild($articleNode, $subjectList); } // Add type. $types = $article->getType(null); // return all locales if (!empty($types)) { $typeList =& XMLCustomWriter::createElement($articleDoc, 'typeList'); foreach ($types as $locale => $type) { $typeNode =& XMLCustomWriter::createChildWithText($articleDoc, $typeList, 'type', $type); XMLCustomWriter::setAttribute($typeNode, 'locale', $locale); } XMLCustomWriter::appendChild($articleNode, $typeList); } // Add coverage. $coverageGeo = $article->getCoverageGeo(null); $coverageChron = $article->getCoverageChron(null); $coverageSample = $article->getCoverageSample(null); if (!empty($coverageGeo) || !empty($coverageChron) || !empty($coverageSample)) { $coverageList =& XMLCustomWriter::createElement($articleDoc, 'coverageList'); if (!is_array($coverageGeo)) { $coverageGeo = array(); } if (!is_array($coverageChron)) { $coverageChron = array(); } if (!is_array($coverageSample)) { $coverageSample = array(); } $locales = array_unique(array_merge(array_keys($coverageGeo), array_keys($coverageChron), array_keys($coverageSample))); foreach ($locales as $locale) { $coverage = ''; if (isset($coverageGeo[$locale])) { $coverage .= $coverageGeo[$locale]; } if (isset($coverageChron[$locale])) { if (!empty($coverage)) { $coverage .= '; '; } $coverage .= $coverageChron[$locale]; } if (isset($coverageSample[$locale])) { if (!empty($coverage)) { $coverage .= '; '; } $coverage .= $coverageSample[$locale]; } $coverageNode =& XMLCustomWriter::createChildWithText($articleDoc, $coverageList, 'coverage', $coverage); XMLCustomWriter::setAttribute($coverageNode, 'locale', $locale); } XMLCustomWriter::appendChild($articleNode, $coverageList); } // Add journal titles. $journalTitleList =& XMLCustomWriter::createElement($articleDoc, 'journalTitleList'); // Journal titles are used for sorting, we therefore need // them in all supported locales. foreach ($supportedLocales as $locale) { $localizedTitle = $journal->getName($locale); $sortOnly = false; if (is_null($localizedTitle)) { // If the title does not exist in the given locale // then use the localized title for sorting only. $journalTitle = $journal->getLocalizedName(); $sortOnly = true; } else { $journalTitle = $localizedTitle; } $journalTitleNode =& XMLCustomWriter::createChildWithText($articleDoc, $journalTitleList, 'journalTitle', $journalTitle); XMLCustomWriter::setAttribute($journalTitleNode, 'locale', $locale); $sortOnly = $sortOnly ? 'true' : 'false'; XMLCustomWriter::setAttribute($journalTitleNode, 'sortOnly', $sortOnly); } XMLCustomWriter::appendChild($articleNode, $journalTitleList); // Add publication dates. $publicationDate = $article->getDatePublished(); if (!empty($publicationDate)) { // Transform and store article publication date. $publicationDate = $this->_convertDate($publicationDate); $dateNode =& XMLCustomWriter::createChildWithText($articleDoc, $articleNode, 'publicationDate', $publicationDate); } $issueId = $article->getIssueId(); if (is_numeric($issueId)) { $issueDao = DAORegistry::getDAO('IssueDAO'); /* @var $issueDao IssueDAO */ $issue = $issueDao->getById($issueId); if (is_a($issue, 'Issue')) { $issuePublicationDate = $issue->getDatePublished(); if (!empty($issuePublicationDate)) { // Transform and store issue publication date. $issuePublicationDate = $this->_convertDate($issuePublicationDate); $dateNode =& XMLCustomWriter::createChildWithText($articleDoc, $articleNode, 'issuePublicationDate', $issuePublicationDate); } } } // We need the router to build file URLs. $router = $request->getRouter(); /* @var $router PageRouter */ // Add galley files $articleGalleyDao = DAORegistry::getDAO('ArticleGalleyDAO'); $galleys = $articleGalleyDao->getBySubmissionId($article->getId()); $galleyList = null; while ($galley = $galleys->next()) { /* @var $galley ArticleGalley */ $locale = $galley->getLocale(); $galleyUrl = $router->url($request, $journal->getPath(), 'article', 'download', array(intval($article->getId()), intval($galley->getId()))); if (!empty($locale) && !empty($galleyUrl)) { if (is_null($galleyList)) { $galleyList =& XMLCustomWriter::createElement($articleDoc, 'galleyList'); } $galleyNode =& XMLCustomWriter::createElement($articleDoc, 'galley'); XMLCustomWriter::setAttribute($galleyNode, 'locale', $locale); XMLCustomWriter::setAttribute($galleyNode, 'fileName', $galleyUrl); XMLCustomWriter::appendChild($galleyList, $galleyNode); } } // Wrap the galley XML as CDATA. if (!is_null($galleyList)) { if (is_callable(array($articleDoc, 'saveXml'))) { $galleyXml = $articleDoc->saveXml($galleyList); } else { $galleyXml = $galleyList->toXml(); } $galleyOuterNode =& XMLCustomWriter::createElement($articleDoc, 'galley-xml'); if (is_callable(array($articleDoc, 'createCDATASection'))) { $cdataNode = $articleDoc->createCDATASection($galleyXml); } else { $cdataNode = new XMLNode(); $cdataNode->setValue('<![CDATA[' . $galleyXml . ']]>'); } XMLCustomWriter::appendChild($galleyOuterNode, $cdataNode); XMLCustomWriter::appendChild($articleNode, $galleyOuterNode); } // Add supplementary files $fileDao = DAORegistry::getDAO('SuppFileDAO'); $suppFiles =& $fileDao->getSuppFilesByArticle($article->getId()); $suppFileList = null; foreach ($suppFiles as $suppFile) { /* @var $suppFile SuppFile */ // Try to map the supp-file language to a PKP locale. $locale = null; $language = $suppFile->getLanguage(); if (strlen($language) == 2) { $language = AppLocale::get3LetterFrom2LetterIsoLanguage($language); } if (strlen($language) == 3) { $locale = AppLocale::getLocaleFrom3LetterIso($language); } if (!AppLocale::isLocaleValid($locale)) { $locale = 'unknown'; } $suppFileUrl = $router->url($request, $journal->getPath(), 'article', 'downloadSuppFile', array(intval($article->getId()), intval($suppFile->getId()))); if (!empty($locale) && !empty($suppFileUrl)) { if (is_null($suppFileList)) { $suppFileList =& XMLCustomWriter::createElement($articleDoc, 'suppFileList'); } $suppFileNode =& XMLCustomWriter::createElement($articleDoc, 'suppFile'); XMLCustomWriter::setAttribute($suppFileNode, 'locale', $locale); XMLCustomWriter::setAttribute($suppFileNode, 'fileName', $suppFileUrl); XMLCustomWriter::appendChild($suppFileList, $suppFileNode); // Add supp file meta-data. $suppFileMetadata = array('title' => $suppFile->getTitle(null), 'creator' => $suppFile->getCreator(null), 'subject' => $suppFile->getSubject(null), 'typeOther' => $suppFile->getTypeOther(null), 'description' => $suppFile->getDescription(null), 'source' => $suppFile->getSource(null)); foreach ($suppFileMetadata as $field => $data) { if (!empty($data)) { $suppFileMDListNode =& XMLCustomWriter::createElement($articleDoc, $field . 'List'); foreach ($data as $locale => $value) { $suppFileMDNode =& XMLCustomWriter::createChildWithText($articleDoc, $suppFileMDListNode, $field, $value); XMLCustomWriter::setAttribute($suppFileMDNode, 'locale', $locale); unset($suppFileMDNode); } XMLCustomWriter::appendChild($suppFileNode, $suppFileMDListNode); unset($suppFileMDListNode); } } } } // Wrap the suppFile XML as CDATA. if (!is_null($suppFileList)) { if (is_callable(array($articleDoc, 'saveXml'))) { $suppFileXml = $articleDoc->saveXml($suppFileList); } else { $suppFileXml = $suppFileList->toXml(); } $suppFileOuterNode =& XMLCustomWriter::createElement($articleDoc, 'suppFile-xml'); if (is_callable(array($articleDoc, 'createCDATASection'))) { $cdataNode = $articleDoc->createCDATASection($suppFileXml); } else { $cdataNode = new XMLNode(); $cdataNode->setValue('<![CDATA[' . $suppFileXml . ']]>'); } XMLCustomWriter::appendChild($suppFileOuterNode, $cdataNode); XMLCustomWriter::appendChild($articleNode, $suppFileOuterNode); } }
/** * @see DOIExportDom::getPrimaryObjectLocale() * @param $suppFile SuppFile */ function getPrimaryObjectLocale(&$article, &$galley, &$suppFile) { $primaryObjectLocale = null; if (is_a($suppFile, 'SuppFile')) { // Try to map the supp-file language to a PKP locale. $suppFileLanguage = $suppFile->getLanguage(); if (strlen($suppFileLanguage) == 2) { $suppFileLanguage = AppLocale::get3LetterFrom2LetterIsoLanguage($suppFileLanguage); } if (strlen($suppFileLanguage) == 3) { $primaryObjectLocale = AppLocale::getLocaleFrom3LetterIso($suppFileLanguage); } } // If mapping didn't work or we do not have a supp file then // retrieve the locale from the other objects. if (!AppLocale::isLocaleValid($primaryObjectLocale)) { $primaryObjectLocale = parent::getPrimaryObjectLocale($article, $galley); } return $primaryObjectLocale; }