/** * Map OpenURL properties to NLM 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; // Instantiate the target description. $outputSchema = new NlmCitationSchema(); $output = new MetadataDescription($outputSchema, $input->getAssocType()); // Parse au statements into name descriptions import('metadata.nlm.PersonStringNlmNameSchemaFilter'); $personStringFilter = new PersonStringNlmNameSchemaFilter(ASSOC_TYPE_AUTHOR); $authors =& $input->getStatement('au'); if (is_array($authors) && count($authors)) { // TODO: We might improve results here by constructing the // first author from aufirst, aulast fields. foreach ($authors as $author) { $authorDescription =& $personStringFilter->execute($author); $success = $output->addStatement('person-group[@person-group-type="author"]', $authorDescription); assert($success); unset($authorDescription); } } // Publication type if ($input->hasStatement('genre')) { $genre = $input->getStatement('genre'); $genreMap = $this->_getOpenUrlGenreTranslationMapping(); $publicationType = isset($genreMap[$genre]) ? $genreMap[$genre] : $genre; $success = $output->addStatement('[@publication-type]', $publicationType); assert($success); } // Get NLM => OpenURL property mapping. $propertyMap =& $this->nlmOpenUrlMapping($publicationType, $input->getMetadataSchema()); // Transfer mapped properties with default locale foreach ($propertyMap as $nlmProperty => $openUrlProperty) { if ($input->hasStatement($openUrlProperty)) { $success = $output->addStatement($nlmProperty, $input->getStatement($openUrlProperty)); assert($success); } } return $output; }
/** * Post processes an NLM meta-data array * @param $preliminaryNlmArray array * @return array */ function &postProcessMetadataArray(&$preliminaryNlmArray) { // Clean array $preliminaryNlmArray =& arrayClean($preliminaryNlmArray); // Trim punctuation $preliminaryNlmArray =& $this->_recursivelyTrimPunctuation($preliminaryNlmArray); // Parse (=filter) author/editor strings into NLM name descriptions foreach (array('author' => ASSOC_TYPE_AUTHOR, 'editor' => ASSOC_TYPE_EDITOR) as $personType => $personAssocType) { if (isset($preliminaryNlmArray[$personType])) { // Get the author/editor strings from the result $personStrings = $preliminaryNlmArray[$personType]; unset($preliminaryNlmArray[$personType]); // Parse the author/editor strings into NLM name descriptions $personStringFilter = new PersonStringNlmNameSchemaFilter($personAssocType); // Interpret a scalar as a textual authors list if (is_scalar($personStrings)) { $personStringFilter->setFilterMode(PERSON_STRING_FILTER_MULTIPLE); $persons =& $personStringFilter->execute($personStrings); } else { $persons =& array_map(array($personStringFilter, 'execute'), $personStrings); } $preliminaryNlmArray['person-group[@person-group-type="' . $personType . '"]'] = $persons; unset($persons); } } // Join comments if (isset($preliminaryNlmArray['comment']) && is_array($preliminaryNlmArray['comment'])) { // Implode comments from the result into a single string // as required by the NLM citation schema. $preliminaryNlmArray['comment'] = implode("\n", $preliminaryNlmArray['comment']); } // Normalize date strings foreach (array('date', 'conf-date', 'access-date') as $dateProperty) { if (isset($preliminaryNlmArray[$dateProperty])) { $dateFilter = new DateStringNormalizerFilter(); $preliminaryNlmArray[$dateProperty] = $dateFilter->execute($preliminaryNlmArray[$dateProperty]); } } // Cast strings to integers where necessary foreach (array('fpage', 'lpage', 'size') as $integerProperty) { if (isset($preliminaryNlmArray[$integerProperty]) && is_numeric($preliminaryNlmArray[$integerProperty])) { $preliminaryNlmArray[$integerProperty] = (int) $preliminaryNlmArray[$integerProperty]; } } // Rename elements that are stored in attributes in NLM citation $elementToAttributeMap = array('access-date' => 'date-in-citation[@content-type="access-date"]', 'issn-ppub' => 'issn[@pub-type="ppub"]', 'issn-epub' => 'issn[@pub-type="epub"]', 'pub-id-doi' => 'pub-id[@pub-id-type="doi"]', 'pub-id-publisher-id' => 'pub-id[@pub-id-type="publisher-id"]', 'pub-id-coden' => 'pub-id[@pub-id-type="coden"]', 'pub-id-sici' => 'pub-id[@pub-id-type="sici"]', 'pub-id-pmid' => 'pub-id[@pub-id-type="pmid"]', 'publication-type' => '[@publication-type]'); foreach ($elementToAttributeMap as $elementName => $nlmPropertyName) { if (isset($preliminaryNlmArray[$elementName])) { $preliminaryNlmArray[$nlmPropertyName] = $preliminaryNlmArray[$elementName]; unset($preliminaryNlmArray[$elementName]); } } return $preliminaryNlmArray; }
/** * Custom implementation of Form::validate() that validates * meta-data form data and injects it into the internal citation * object. * * NB: The configuration of the internal citation object * would normally be done in readInputData(). Validation and * injection can easily be done in one step. It therefore avoids * code duplication and improves performance to do both here. */ function validate() { // Make sure that this method is not called twice which // would corrupt internal state. assert(empty($this->_metadataDescriptions)); parent::validate(); // Validate form data and inject it into // the associated citation object. $citation =& $this->getCitation(); $citation->setRawCitation($this->getData('rawCitation')); if ($this->getData('citationApproved') == 'citationApproved') { // Editor's shortcut to the approved state, e.g. for manually edited citations. $citation->setCitationState(CITATION_APPROVED); } elseif (in_array($this->getData('citationState'), Citation::_getSupportedCitationStates())) { // Reset citation state if necessary if ($this->getData('citationState') == CITATION_APPROVED) { $this->setData('citationState', CITATION_LOOKED_UP); } $citation->setCitationState($this->getData('citationState')); } // Extract data from citation form fields and inject it into the citation import('lib.pkp.classes.metadata.MetadataDescription'); $metadataAdapters = $citation->getSupportedMetadataAdapters(); foreach ($metadataAdapters as $metadataAdapter) { // Instantiate a meta-data description for the given schema $metadataDescription = new MetadataDescription($metadataAdapter->getMetadataSchemaName(), ASSOC_TYPE_CITATION); // Set the meta-data statements $metadataSchema =& $metadataAdapter->getMetadataSchema(); foreach ($metadataSchema->getProperties() as $propertyName => $property) { $fieldName = $metadataSchema->getNamespacedPropertyId($propertyName); $fieldValue = trim($this->getData($fieldName)); if (empty($fieldValue)) { // Delete empty statements so that previously set // statements (if any) will be deleted. $metadataDescription->removeStatement($propertyName); if ($property->getMandatory()) { // A mandatory field is missing - add a validation error. $this->addError($fieldName, __($property->getValidationMessage())); $this->addErrorField($fieldName); } } else { // Try to convert the field value to (a) strongly // typed object(s) if applicable. Start with the most // specific allowed type so that we always get the // most strongly typed result possible. $allowedTypes = $property->getAllowedTypes(); switch (true) { case isset($allowedTypes[METADATA_PROPERTY_TYPE_VOCABULARY]) && is_numeric($fieldValue): case isset($allowedTypes[METADATA_PROPERTY_TYPE_INTEGER]) && is_numeric($fieldValue): $typedFieldValues = array((int) $fieldValue); break; case isset($allowedTypes[METADATA_PROPERTY_TYPE_DATE]): import('lib.pkp.classes.metadata.DateStringNormalizerFilter'); $dateStringFilter = new DateStringNormalizerFilter(); assert($dateStringFilter->supportsAsInput($fieldValue)); $typedFieldValues = array($dateStringFilter->execute($fieldValue)); break; case isset($allowedTypes[METADATA_PROPERTY_TYPE_COMPOSITE]): // We currently only support name composites $allowedAssocIds = $allowedTypes[METADATA_PROPERTY_TYPE_COMPOSITE]; if (in_array(ASSOC_TYPE_AUTHOR, $allowedAssocIds)) { $assocType = ASSOC_TYPE_AUTHOR; } elseif (in_array(ASSOC_TYPE_EDITOR, $allowedAssocIds)) { $assocType = ASSOC_TYPE_EDITOR; } else { assert(false); } // Try to transform the field to a name composite. import('lib.pkp.classes.metadata.nlm.PersonStringNlmNameSchemaFilter'); $personStringFilter = new PersonStringNlmNameSchemaFilter($assocType, PERSON_STRING_FILTER_MULTIPLE); assert($personStringFilter->supportsAsInput($fieldValue)); $typedFieldValues =& $personStringFilter->execute($fieldValue); break; default: $typedFieldValues = array($fieldValue); } // Inject data into the meta-data description and thereby // implicitly validate the field value. foreach ($typedFieldValues as $typedFieldValue) { if (!$metadataDescription->addStatement($propertyName, $typedFieldValue)) { // Add form field error $this->addError($fieldName, __($property->getValidationMessage())); $this->addErrorField($fieldName); } unset($typedFieldValue); } unset($typedFieldValues); } } // Inject the meta-data into the citation. $citation->injectMetadata($metadataDescription, true); // Save the meta-data description for later usage. $this->_metadataDescriptions[] =& $metadataDescription; unset($metadataDescription); } return $this->isValid(); }
/** * Save citation */ function execute() { $citation =& $this->getCitation(); $citation->setEditedCitation($this->getData('editedCitation')); if (in_array($this->getData('citationState'), Citation::_getSupportedCitationStates())) { $citation->setCitationState($this->getData('citationState')); } // Extract data from citation form fields and inject it into the citation $metadataAdapters = $citation->getSupportedMetadataAdapters(); foreach ($metadataAdapters as $metadataAdapter) { // Instantiate a meta-data description for the given schema $metadataSchema =& $metadataAdapter->getMetadataSchema(); import('metadata.MetadataDescription'); $metadataDescription = new MetadataDescription($metadataSchema, ASSOC_TYPE_CITATION); // Set the meta-data statements $metadataSchemaNamespace = $metadataSchema->getNamespace(); foreach ($metadataSchema->getProperties() as $propertyName => $property) { $fieldName = $metadataSchema->getNamespacedPropertyId($propertyName); $fieldValue = trim($this->getData($fieldName)); if (empty($fieldValue)) { $metadataDescription->removeStatement($propertyName); } else { $foundValidType = false; foreach ($property->getTypes() as $type) { // Some property types need to be converted first switch ($type) { // We currently only support name composites case array(METADATA_PROPERTY_TYPE_COMPOSITE => ASSOC_TYPE_AUTHOR): case array(METADATA_PROPERTY_TYPE_COMPOSITE => ASSOC_TYPE_EDITOR): import('metadata.nlm.PersonStringNlmNameSchemaFilter'); $personStringFilter = new PersonStringNlmNameSchemaFilter($type[METADATA_PROPERTY_TYPE_COMPOSITE], PERSON_STRING_FILTER_MULTIPLE); assert($personStringFilter->supportsAsInput($fieldValue)); $fieldValue =& $personStringFilter->execute($fieldValue); $foundValidType = true; break; case METADATA_PROPERTY_TYPE_INTEGER: $fieldValue = array((int) $fieldValue); $foundValidType = true; break; case METADATA_PROPERTY_TYPE_DATE: import('metadata.DateStringNormalizerFilter'); $dateStringFilter = new DateStringNormalizerFilter(); assert($dateStringFilter->supportsAsInput($fieldValue)); $fieldValue = array($dateStringFilter->execute($fieldValue)); $foundValidType = true; break; default: if ($property->isValid($fieldValue)) { $fieldValue = array($fieldValue); $foundValidType = true; break; } } // Break the outer loop once we found a valid // interpretation for our form field. if ($foundValidType) { break; } } foreach ($fieldValue as $fieldValueStatement) { $metadataDescription->addStatement($propertyName, $fieldValueStatement); unset($fieldValueStatement); } } } // Inject the meta-data into the citation $citation->injectMetadata($metadataDescription, true); } // Persist citation $citationDAO =& DAORegistry::getDAO('CitationDAO'); if (is_numeric($citation->getId())) { $citationDAO->updateCitation($citation); } else { $citationDAO->insertCitation($citation); } return true; }