/** * @covers Nlm30NameSchemaPersonStringFilter * @covers Nlm30PersonStringFilter * @depends testExecuteWithSinglePersonDescription */ public function testExecuteWithMultiplePersonDescriptions($personDescription1) { $personDescription2 = new MetadataDescription('lib.pkp.plugins.metadata.nlm30.schema.Nlm30NameSchema', ASSOC_TYPE_AUTHOR); $personDescription2->addStatement('given-names', $givenNames1 = 'Bernardo'); $personDescription2->addStatement('given-names', $givenNames2 = 'Antonio'); $personDescription2->addStatement('surname', $surname = 'Elis'); $personDescriptions = array($personDescription1, $personDescription2, PERSON_STRING_FILTER_ETAL); $nlm30NameSchemaPersonStringFilter = new Nlm30NameSchemaPersonStringFilter(PERSON_STRING_FILTER_MULTIPLE); self::assertEquals('Assis Jr, (Machado) de; Elis, A. (Bernardo); et al', $nlm30NameSchemaPersonStringFilter->execute($personDescriptions)); // Test template and delimiter $nlm30NameSchemaPersonStringFilter->setDelimiter(':'); $nlm30NameSchemaPersonStringFilter->setTemplate('%firstname%%initials%%prefix% %surname%%suffix%'); self::assertEquals('Machado de Assis Jr:Bernardo A. Elis:et al', $nlm30NameSchemaPersonStringFilter->execute($personDescriptions)); }
/** * Take a structured meta-data statement and transform it into a * plain text value that can be displayed to the end-user. * * @param $property MetadataProperty * @param $value mixed * @return string */ function _getStringValueFromMetadataStatement(&$property, &$value) { if ($property->getCardinality() == METADATA_PROPERTY_CARDINALITY_MANY && !empty($value)) { $allowedTypes = $property->getAllowedTypes(); if (isset($allowedTypes[METADATA_PROPERTY_TYPE_COMPOSITE])) { // We currently only can transform composite // name arrays to strings. $allowedAssocTypes = $allowedTypes[METADATA_PROPERTY_TYPE_COMPOSITE]; assert(in_array(ASSOC_TYPE_AUTHOR, $allowedAssocTypes) || in_array(ASSOC_TYPE_EDITOR, $allowedAssocTypes)); import('lib.pkp.plugins.metadata.nlm30.filter.Nlm30NameSchemaPersonStringFilter'); $personStringFilter = new Nlm30NameSchemaPersonStringFilter(PERSON_STRING_FILTER_MULTIPLE); assert($personStringFilter->supportsAsInput($value)); $stringValue = $personStringFilter->execute($value); } else { // We currently can't transform properties of // cardinality "many" to strings. assert(is_array($value) && count($value) <= 1); $stringValue = $value[0]; } } else { $stringValue = (string) $value; } return $stringValue; }
/** * Construct an array of search strings from a citation * description and an array of search templates. * The templates may contain the placeholders * %aulast%: the first author's surname * %au%: the first author full name * %title%: the article-title (if it exists), * otherwise the source * %date%: the publication year * %isbn%: ISBN * @param $searchTemplates an array of templates * @param $citationDescription MetadataDescription * @return array */ function constructSearchStrings(&$searchTemplates, &$citationDescription) { // Convert first authors' name description to a string import('lib.pkp.plugins.metadata.nlm30.filter.Nlm30NameSchemaPersonStringFilter'); $personStringFilter = new Nlm30NameSchemaPersonStringFilter(); // Retrieve the authors $firstAuthorSurname = $firstAuthor = ''; $authors = $citationDescription->getStatement('person-group[@person-group-type="author"]'); if (is_array($authors) && count($authors)) { $firstAuthorSurname = (string) $authors[0]->getStatement('surname'); $firstAuthor = $personStringFilter->execute($authors[0]); } // Retrieve the editors $firstEditorSurname = $firstEditor = ''; $editors = $citationDescription->getStatement('person-group[@person-group-type="editor"]'); if (is_array($editors) && count($editors)) { $firstEditorSurname = (string) $editors[0]->getStatement('surname'); $firstEditor = $personStringFilter->execute($editors[0]); } // Retrieve (default language) title $title = (string) ($citationDescription->hasStatement('article-title') ? $citationDescription->getStatement('article-title') : $citationDescription->getStatement('source')); // Extract the year from the publication date $year = (string) $citationDescription->getStatement('date'); $year = String::strlen($year) > 4 ? String::substr($year, 0, 4) : $year; // Retrieve ISBN $isbn = (string) $citationDescription->getStatement('isbn'); // Replace the placeholders in the templates $searchStrings = array(); foreach ($searchTemplates as $searchTemplate) { // Try editors and authors separately $searchStrings[] = str_replace(array('%aulast%', '%au%', '%title%', '%date%', '%isbn%'), array($firstAuthorSurname, $firstAuthor, $title, $year, $isbn), $searchTemplate); $searchStrings[] = str_replace(array('%aulast%', '%au%', '%title%', '%date%', '%isbn%'), array($firstEditorSurname, $firstEditor, $title, $year, $isbn), $searchTemplate); } // Remove empty or duplicate searches $searchStrings = array_map(array('String', 'trimPunctuation'), $searchStrings); $searchStrings = array_unique($searchStrings); $searchStrings = arrayClean($searchStrings); return $searchStrings; }
/** * Map NLM properties to OpenURL properties. * NB: OpenURL has no i18n so we use the default * locale when mapping. * @see Filter::process() * @param $input MetadataDescription * @return MetadataDescription */ function &process(&$input) { $nullVar = null; // Identify the genre of the target record and // instantiate the target description. $publicationType = $input->getStatement('[@publication-type]'); switch ($publicationType) { case NLM30_PUBLICATION_TYPE_JOURNAL: case NLM30_PUBLICATION_TYPE_CONFPROC: $outputSchemaName = 'lib.pkp.plugins.metadata.openurl10.schema.Openurl10JournalSchema'; break; case NLM30_PUBLICATION_TYPE_BOOK: $outputSchemaName = 'lib.pkp.plugins.metadata.openurl10.schema.Openurl10BookSchema'; break; case NLM30_PUBLICATION_TYPE_THESIS: $outputSchemaName = 'lib.pkp.plugins.metadata.openurl10.schema.Openurl10DissertationSchema'; break; default: // Unsupported type return $nullVar; } // Create the target description $output = new MetadataDescription($outputSchemaName, $input->getAssocType()); // Transform authors import('lib.pkp.plugins.metadata.nlm30.filter.Nlm30NameSchemaPersonStringFilter'); $personStringFilter = new Nlm30NameSchemaPersonStringFilter(); $authors =& $input->getStatement('person-group[@person-group-type="author"]'); if (is_array($authors) && count($authors)) { $aulast = $authors[0]->hasStatement('prefix') ? $authors[0]->getStatement('prefix') . ' ' : ''; $aulast .= $authors[0]->getStatement('surname'); if (!empty($aulast)) { $success = $output->addStatement('aulast', $aulast); assert($success); } $givenNames = $authors[0]->getStatement('given-names'); if (is_array($givenNames) && count($givenNames)) { $aufirst = implode(' ', $givenNames); if (!empty($aufirst)) { $success = $output->addStatement('aufirst', $aufirst); assert($success); } $initials = array(); foreach ($givenNames as $givenName) { $initials[] = substr($givenName, 0, 1); } $auinit1 = array_shift($initials); if (!empty($auinit1)) { $success = $output->addStatement('auinit1', $auinit1); assert($success); } $auinitm = implode('', $initials); if (!empty($auinitm)) { $success = $output->addStatement('auinitm', $auinitm); assert($success); } $auinit = $auinit1 . $auinitm; if (!empty($auinit)) { $success = $output->addStatement('auinit', $auinit); assert($success); } } $ausuffix = $authors[0]->getStatement('suffix'); if (!empty($ausuffix)) { $success = $output->addStatement('ausuffix', $ausuffix); assert($success); } foreach ($authors as $author) { if ($author == PERSON_STRING_FILTER_ETAL) { $au = $author; } else { $au = $personStringFilter->execute($author); } $success = $output->addStatement('au', $au); assert($success); unset($au); } } // Genre: Guesswork if (is_a($output->getMetadataSchema(), 'Openurl10JournalBookBaseSchema')) { switch ($publicationType) { case NLM30_PUBLICATION_TYPE_JOURNAL: $genre = $input->hasProperty('article-title') ? OPENURL10_GENRE_ARTICLE : OPENURL10_GENRE_JOURNAL; break; case NLM30_PUBLICATION_TYPE_CONFPROC: $genre = $input->hasProperty('article-title') ? OPENURL10_GENRE_PROCEEDING : OPENURL10_GENRE_CONFERENCE; break; case NLM30_PUBLICATION_TYPE_BOOK: $genre = $input->hasProperty('article-title') ? OPENURL10_GENRE_BOOKITEM : OPENURL10_GENRE_BOOK; break; } assert(!empty($genre)); $success = $output->addStatement('genre', $genre); assert($success); } // Map remaining properties (NLM => OpenURL) $propertyMap =& $this->nlmOpenurl10Mapping($publicationType, $output->getMetadataSchema()); // Transfer mapped properties with default locale foreach ($propertyMap as $nlm30Property => $openurl10Property) { if ($input->hasStatement($nlm30Property)) { $success = $output->addStatement($openurl10Property, $input->getStatement($nlm30Property)); assert($success); } } return $output; }
/** * @see Filter::process() * @param $citationDescription MetadataDescription * @return MetadataDescription */ function &process(&$citationDescription) { $pmid = $citationDescription->getStatement('pub-id[@pub-id-type="pmid"]'); // If the citation does not have a PMID, try to get one from eSearch // otherwise skip directly to eFetch. if (empty($pmid)) { // Initialize search result arrays. $pmidArrayFromAuthorsSearch = $pmidArrayFromTitleSearch = $pmidArrayFromStrictSearch = array(); // 1) Try a "loose" search based on the author list. // (This works surprisingly well for pubmed.) $authors =& $citationDescription->getStatement('person-group[@person-group-type="author"]'); if (is_array($authors)) { import('lib.pkp.plugins.metadata.nlm30.filter.Nlm30NameSchemaPersonStringFilter'); $personNameFilter = new Nlm30NameSchemaPersonStringFilter(PERSON_STRING_FILTER_MULTIPLE, '%firstname%%initials%%prefix% %surname%%suffix%', ', '); $authorsString = (string) $personNameFilter->execute($authors); if (!empty($authorsString)) { $pmidArrayFromAuthorsSearch =& $this->_search($authorsString); } } // 2) Try a "loose" search based on the article title $articleTitle = (string) $citationDescription->getStatement('article-title'); if (!empty($articleTitle)) { $pmidArrayFromTitleSearch =& $this->_search($articleTitle); } // 3) Try a "strict" search based on as much information as possible $searchProperties = array('article-title' => '', 'person-group[@person-group-type="author"]' => '[Auth]', 'source' => '[Jour]', 'date' => '[DP]', 'volume' => '[VI]', 'issue' => '[IP]', 'fpage' => '[PG]'); $searchTerms = ''; $statements = $citationDescription->getStatements(); foreach ($searchProperties as $nlm30Property => $pubmedProperty) { if (isset($statements[$nlm30Property])) { if (!empty($searchTerms)) { $searchTerms .= ' AND '; } // Special treatment for authors if ($nlm30Property == 'person-group[@person-group-type="author"]') { assert(isset($statements['person-group[@person-group-type="author"]'][0])); $firstAuthor =& $statements['person-group[@person-group-type="author"]'][0]; // Add surname $searchTerms .= (string) $firstAuthor->getStatement('surname'); // Add initial of the first given name $givenNames = $firstAuthor->getStatement('given-names'); if (is_array($givenNames)) { $searchTerms .= ' ' . String::substr($givenNames[0], 0, 1); } } else { $searchTerms .= $citationDescription->getStatement($nlm30Property); } $searchTerms .= $pubmedProperty; } } $pmidArrayFromStrictSearch =& $this->_search($searchTerms); // TODO: add another search like strict, but without article title // e.g. ...term=Baumgart+Dc[Auth]+AND+Lancet[Jour]+AND+2005[DP]+AND+366[VI]+AND+9492[IP]+AND+1210[PG] // Compare the arrays to try to narrow it down to one PMID switch (true) { // strict search has a single result case count($pmidArrayFromStrictSearch) == 1: $pmid = $pmidArrayFromStrictSearch[0]; break; // 3-way union // 3-way union case count($intersect = array_intersect($pmidArrayFromTitleSearch, $pmidArrayFromAuthorsSearch, $pmidArrayFromStrictSearch)) == 1: $pmid = current($intersect); break; // 2-way union: title / strict // 2-way union: title / strict case count($pmid_2way1 = array_intersect($pmidArrayFromTitleSearch, $pmidArrayFromStrictSearch)) == 1: $pmid = current($pmid_2way1); break; // 2-way union: authors / strict // 2-way union: authors / strict case count($pmid_2way2 = array_intersect($pmidArrayFromAuthorsSearch, $pmidArrayFromStrictSearch)) == 1: $pmid = current($pmid_2way2); break; // 2-way union: authors / title // 2-way union: authors / title case count($pmid_2way3 = array_intersect($pmidArrayFromAuthorsSearch, $pmidArrayFromTitleSearch)) == 1: $pmid = current($pmid_2way3); break; // we only have one result for title // we only have one result for title case count($pmidArrayFromTitleSearch) == 1: $pmid = $pmidArrayFromTitleSearch[0]; break; // we only have one result for authors // we only have one result for authors case count($pmidArrayFromAuthorsSearch) == 1: $pmid = $pmidArrayFromAuthorsSearch[0]; break; // we were unable to find a PMID // we were unable to find a PMID default: $pmid = ''; } } // If we have a PMID, get a metadata array for it if (!empty($pmid)) { $citationDescription =& $this->_lookup($pmid); return $citationDescription; } // Nothing found $nullVar = null; return $nullVar; }