diff --git a/plugins/metadata/mods/filter/ModsSchemaSubmissionAdapter.inc.php b/plugins/metadata/mods/filter/ModsSchemaSubmissionAdapter.inc.php new file mode 100644 index 00000000000..e446f9ec946 --- /dev/null +++ b/plugins/metadata/mods/filter/ModsSchemaSubmissionAdapter.inc.php @@ -0,0 +1,291 @@ +getMetadataSchemaName() == 'plugins.metadata.mods.schema.ModsSchema'); + $modsSchema =& $modsDescription->getMetadataSchema(); + + // Title + $localizedTitles = $modsDescription->getStatementTranslations('titleInfo/title'); + if (is_array($localizedTitles)) { + foreach($localizedTitles as $locale => $title) { + $submission->setTitle($title, $locale); + } + } + + // Names: authors and sponsor + $foundSponsor = false; + $nameDescriptions =& $modsDescription->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.mods.schema.ModsNameSchema'); + + // 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. + 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. + import($authorClassName); + $author = new Author(); + + // Family Name + $author->setLastName($nameDescription->getStatement('namePart[@type="family"]')); + + // Given Names + $givenNames = $nameDescription->getStatement('namePart[@type="given"]'); + if (isset($givenNames[0])) $author->setFirstName($givenNames[0]); + if (isset($givenNames[1])) $author->setMiddleName($givenNames[1]); + + // Affiliation + $localizedAffiliations = $nameDescription->getStatementTranslations('affiliation'); + if (is_array($localizedAffiliations)) { + foreach($localizedAffiliations as $locale => $affiliations) { + if (is_array($affiliations) && isset($affiliations[0])) { + $author->setAffiliation($affiliations[0], $locale); + } + } + } + + // Add the author to the submission. + $submission->addAuthor($author); + unset($author); + } + break; + + // Sponsor + case 'corporate': + // Only the first sponsor goes into the submission. + if (!$foundSponsor && in_array('spn', $nameRoles)) { + $foundSponsor = true; + $submission->setSponsor($nameDescription->getStatement('namePart')); + } + break; + } + } + + unset($nameDescription); + } + } + + // Creation date + $dateSubmitted = $modsDescription->getStatement('originInfo/dateCreated[@encoding="w3cdtf"]'); + if ($dateSubmitted) $submission->setDateSubmitted($dateSubmitted); + + // Submission language + $submissionLanguages = $modsSchema->get2LetterFrom3LetterIsoLanguage($modsDescription->getStatement('language[@objectPart=""]/languageTerm[@type="code" @authority="iso639-2b"]')); + if (is_array($submissionLanguages) && isset($submissionLanguages[0])) { + $submission->setLanguage($submissionLanguages[0]); + } + + // Pages (extent) + $pages = $modsDescription->getStatement('physicalDescription/extent'); + if ($pages) $submission->setPages($pages); + + // Abstract + $localizedAbstracts = $modsDescription->getStatementTranslations('abstract'); + if (is_array($localizedAbstracts)) { + foreach($localizedAbstracts as $locale => $abstract) { + $submission->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? + + // Geographical coverage + $localizedCoverageGeos = $modsDescription->getStatementTranslations('subject/geographic'); + if (is_array($localizedCoverageGeos)) { + foreach($localizedCoverageGeos as $locale => $localizedCoverageGeo) { + $submission->setCoverageGeo($localizedCoverageGeo, $locale); + } + } + + // Chronological coverage + $localizedCoverageChrons = $modsDescription->getStatementTranslations('subject/temporal'); + if (is_array($localizedCoverageChrons)) { + foreach($localizedCoverageChrons as $locale => $localizedCoverageChron) { + $submission->setCoverageChron($localizedCoverageChron, $locale); + } + } + + // 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. + + return $submission; + } + + /** + * @see MetadataDataObjectAdapter::extractMetadataFromDataObject() + * @param $submission Submission + * @param $authorMarcrelatorRole string the marcrelator role to be used + * for submission authors. + */ + function &extractMetadataFromDataObject(&$submission, $authorMarcrelatorRole = 'aut') { + assert(is_a($submission, 'Submission')); + $modsDescription =& $this->instantiateMetadataDescription(); + $modsSchema =& $modsDescription->getMetadataSchema(); + + // Retrieve the primary locale. + $primaryLocale = Locale::getPrimaryLocale(); + $primaryLanguage = $modsSchema->get3LetterIsoFromLocale($primaryLocale); + + // Establish the association between the meta-data description + // and the submission. + $modsDescription->setAssocId($submission->getId()); + + // Title + $localizedTitles =& $submission->getTitle(null); // Localized + $this->addLocalizedStatements($modsDescription, 'titleInfo/title', $localizedTitles); + + // Authors + $authors =& $submission->getAuthors(); + foreach($authors as $author) { + // Create a new name description. + $authorDescription = new MetadataDescription('lib.pkp.plugins.metadata.mods.schema.ModsNameSchema', ASSOC_TYPE_AUTHOR); + + // Type + $authorType = 'personal'; + $authorDescription->addStatement('[@type]', $authorType); + + // Family Name + $authorDescription->addStatement('namePart[@type="family"]', $author->getLastName()); + + // Given Names + $authorDescription->addStatement('namePart[@type="given"]', $author->getFirstName()); + $middleName = $author->getMiddleName(); + if (!empty($middleName)) { + $authorDescription->addStatement('namePart[@type="given"]', $middleName); + } + + // Affiliation + $localizedAffiliation =& $author->getAffiliation(null); // Localized + $this->addLocalizedStatements($authorDescription, 'affiliation', $localizedAffiliation); + + // Role + $authorDescription->addStatement('role/roleTerm[@type="code" @authority="marcrelator"]', $authorMarcrelatorRole); + + // Add the author to the MODS schema. + $modsDescription->addStatement('name', $authorDescription); + unset($authorDescription); + } + + // Sponsor + $supportingAgency = $submission->getSponsor($primaryLanguage); // Try the cataloging language first. + if (!$supportingAgency) { + $supportingAgency = $submission->getLocalizedSponsor(); + } + if ($supportingAgency) { + $supportingAgencyDescription = new MetadataDescription('lib.pkp.plugins.metadata.mods.schema.ModsNameSchema', ASSOC_TYPE_AUTHOR); + $supportingAgencyDescription->addStatement('[@type]', 'corporate'); + $supportingAgencyDescription->addStatement('namePart', $supportingAgency); + $supportingAgencyDescription->addStatement('role/roleTerm[@type="code" @authority="marcrelator"]', 'spn'); + $modsDescription->addStatement('name', $supportingAgencyDescription); + } + + // Type of resource + $typeOfResource = 'text'; + $modsDescription->addStatement('typeOfResource', $typeOfResource); + + // Creation date + $modsDescription->addStatement('originInfo/dateCreated[@encoding="w3cdtf"]', $submission->getDateSubmitted()); + + // Submission language + $submissionLanguage = $modsSchema->get3LetterFrom2LetterIsoLanguage($submission->getLanguage()); + if (!$submissionLanguage) { + $submissionLanguage = $primaryLanguage; + } + $modsDescription->addStatement('language[@objectPart=""]/languageTerm[@type="code" @authority="iso639-2b"]', $submissionLanguage); + + // Pages (extent) + $modsDescription->addStatement('physicalDescription/extent', $submission->getPages()); + + // Abstract + $localizedAbstracts =& $submission->getAbstract(null); // Localized + $this->addLocalizedStatements($modsDescription, 'abstract', $localizedAbstracts); + + // Discipline + $localizedDisciplines = $submission->getDiscipline(null); // Localized + $this->addLocalizedStatements($modsDescription, 'subject/topic', $localizedDisciplines); + + // Subject class + $localizedSubjectClasses = $submission->getSubjectClass(null); // Localized + $this->addLocalizedStatements($modsDescription, 'subject/topic', $localizedSubjectClasses); + + // Subject + $localizedSubjects = $submission->getSubject(null); // Localized + $this->addLocalizedStatements($modsDescription, 'subject/topic', $localizedSubjects); + + // Geographical coverage + $localizedCoverageGeo = $submission->getCoverageGeo(null); // Localized + $this->addLocalizedStatements($modsDescription, 'subject/geographic', $localizedCoverageGeo); + + // Chronological coverage + $localizedCoverageChron = $submission->getCoverageChron(null); // Localized + $this->addLocalizedStatements($modsDescription, 'subject/temporal', $localizedCoverageChron); + + // Record creation date + $recordCreationDate = date('%Y-%m-%d'); + $modsDescription->addStatement('recordInfo/recordCreationDate[@encoding="w3cdtf"]', $recordCreationDate); + + // Record identifier + $modsDescription->addStatement('recordInfo/recordIdentifier[@source="pkp"]', $submission->getId()); + + // Cataloging language + $modsDescription->addStatement('recordInfo/languageOfCataloging/languageTerm[@authority="iso639-2b"]', $primaryLanguage); + + return $modsDescription; + } +} +?> diff --git a/tests/plugins/metadata/mods/filter/MockAuthor.inc.php b/tests/plugins/metadata/mods/filter/MockAuthor.inc.php new file mode 100644 index 00000000000..29937644468 --- /dev/null +++ b/tests/plugins/metadata/mods/filter/MockAuthor.inc.php @@ -0,0 +1,15 @@ + \ No newline at end of file diff --git a/tests/plugins/metadata/mods/filter/MockLocale.inc.php b/tests/plugins/metadata/mods/filter/MockLocale.inc.php new file mode 100644 index 00000000000..b0e5a20c62e --- /dev/null +++ b/tests/plugins/metadata/mods/filter/MockLocale.inc.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/tests/plugins/metadata/mods/filter/ModsSchemaSubmissionAdapterTest.inc.php b/tests/plugins/metadata/mods/filter/ModsSchemaSubmissionAdapterTest.inc.php new file mode 100755 index 00000000000..945aa50c350 --- /dev/null +++ b/tests/plugins/metadata/mods/filter/ModsSchemaSubmissionAdapterTest.inc.php @@ -0,0 +1,79 @@ +getAssocType()); + self::assertType('ModsSchema', $adapter->getMetadataSchema()); + $expectedTransformations = array( + array( + 'metadata::plugins.metadata.mods.schema.ModsSchema(CITATION)', + 'class::lib.pkp.classes.submission.Submission' + ), + array( + 'class::lib.pkp.classes.submission.Submission', + 'metadata::plugins.metadata.mods.schema.ModsSchema(CITATION)' + ) + ); + self::assertEquals($expectedTransformations, $adapter->getSupportedTransformations()); + + // Instantiate a test description. + $authorDescription = new MetadataDescription('lib.pkp.plugins.metadata.mods.schema.ModsNameSchema', ASSOC_TYPE_AUTHOR); + self::assertTrue($authorDescription->addStatement('[@type]', $nameType = 'personal')); + self::assertTrue($authorDescription->addStatement('namePart[@type="family"]', $familyName = 'some family name')); + self::assertTrue($authorDescription->addStatement('role/roleTerm[@type="code" @authority="marcrelator"]', $role = 'aut')); + $submissionDescription = new MetadataDescription('plugins.metadata.mods.schema.ModsSchema', ASSOC_TYPE_CITATION); + self::assertTrue($submissionDescription->addStatement('titleInfo/title', $articleTitle = 'new submission title')); + self::assertTrue($submissionDescription->addStatement('name', $authorDescription)); + self::assertTrue($submissionDescription->addStatement('typeOfResource', $typeOfResource = 'text')); + self::assertTrue($submissionDescription->addStatement('recordInfo/languageOfCataloging/languageTerm[@authority="iso639-2b"]', $languageOfCataloging = 'eng')); + + // Instantiate test submission. + $submission = new Submission(); + $submission->setTitle('previous submission title', 'en_US'); + $submission->setAbstract('previous abstract', 'en_US'); + + // Test metadata injection (no replace). + $resultSubmission =& $adapter->injectMetadataIntoDataObject($submissionDescription, $submission, false, 'lib.pkp.tests.plugins.metadata.mods.filter.Author'); + $expectedResult = array( + 'cleanTitle' => array('en_US' => 'new submission title'), + 'title' => array('en_US' => 'new submission title'), + 'abstract' => array('en_US' => 'previous abstract') + ); + self::assertEquals($expectedResult, $resultSubmission->getAllData()); + + // Test meta-data injection (replace). + $resultSubmission =& $adapter->injectMetadataIntoDataObject($submissionDescription, $submission, true, 'lib.pkp.tests.plugins.metadata.mods.filter.Author'); + $expectedResult = array( + 'cleanTitle' => array('en_US' => 'new submission title'), + 'title' => array('en_US' => 'new submission title') + ); + self::assertEquals($expectedResult, $resultSubmission->getAllData()); + + // Test meta-data extraction. + $extractedDescription =& $adapter->extractMetadataFromDataObject($submission); + self::assertEquals($submissionDescription, $extractedDescription); + } +} +?> \ No newline at end of file