[ Mini Kiebo ]
Server: Windows NT DESKTOP-5B8S0D4 6.2 build 9200 (Windows 8 Professional Edition) i586
Path:
D:
/
Backup
/
05122024
/
htdocs
/
jurnal-kesmas
/
lib
/
pkp
/
classes
/
metadata
/
[
Home
]
File: MetadataDataObjectAdapter.php
<?php /** * @file classes/metadata/MetadataDataObjectAdapter.php * * Copyright (c) 2014-2021 Simon Fraser University * Copyright (c) 2000-2021 John Willinsky * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING. * * @class MetadataDataObjectAdapter * * @ingroup metadata * * @see DataObject * @see MetadataSchema * @see MetadataDescription * * @brief Class that injects/extracts a meta-data description * into/from an application entity object (DataObject). * * These adapters have to be persistable as they'll be provided * by plug-ins via the filter registry. */ namespace PKP\metadata; use PKP\core\DataObject; use PKP\filter\ClassTypeDescription; use PKP\filter\FilterGroup; use PKP\filter\PersistableFilter; class MetadataDataObjectAdapter extends PersistableFilter { public const METADATA_DOA_INJECTION_MODE = 1; public const METADATA_DOA_EXTRACTION_MODE = 2; /** @var int */ public $_mode; /** @var MetadataSchema */ public $_metadataSchema; /** @var string */ public $_dataObjectClass; /** @var array */ public $_metadataFieldNames; /** @var string */ public $_metadataSchemaName; /** @var int */ public $_assocType; /** @var string */ public $_dataObjectName; /** @var DataObject */ public $_targetDataObject; /** * Constructor * * @param FilterGroup $filterGroup * @param null|mixed $mode */ public function __construct($filterGroup, $mode = null) { // Initialize the adapter. parent::__construct($filterGroup); // Extract information from the input/output types. // Find out whether this filter is injecting or // extracting meta-data. $metadataTypeDescription = null; /** @var MetadataTypeDescription $metadataTypeDescription */ $dataObjectTypeDescription = null; /** @var ClassTypeDescription $dataObjectTypeDescription */ $inputType = & $this->getInputType(); $outputType = & $this->getOutputType(); if (is_null($mode)) { if ($inputType instanceof \PKP\metadata\MetadataTypeDescription) { $mode = self::METADATA_DOA_INJECTION_MODE; } else { $mode = self::METADATA_DOA_EXTRACTION_MODE; } } $this->_mode = $mode; if ($mode == self::METADATA_DOA_INJECTION_MODE) { // We are in meta-data injection mode (or both input and output are meta-data descriptions). $metadataTypeDescription = & $inputType; /** @var MetadataTypeDescription $metadataTypeDescription */ assert($outputType instanceof ClassTypeDescription); $dataObjectTypeDescription = & $outputType; /** @var ClassTypeDescription $dataObjectTypeDescription */ } else { // We are in meta-data extraction mode. assert($outputType instanceof \PKP\metadata\MetadataTypeDescription); $metadataTypeDescription = & $outputType; assert($inputType instanceof ClassTypeDescription); $dataObjectTypeDescription = & $inputType; } // Extract information from the input/output types. $this->_metadataSchemaName = $metadataTypeDescription->getMetadataSchemaClass(); $this->_assocType = $metadataTypeDescription->getAssocType(); $this->_dataObjectName = $dataObjectTypeDescription->getTypeName(); // Set the display name. if ($mode == self::METADATA_DOA_INJECTION_MODE) { $this->setDisplayName('Inject metadata into a(n) ' . $this->getDataObjectClass()); } else { $this->setDisplayName('Extract metadata from a(n) ' . $this->getDataObjectClass()); } } // // Getters and setters // /** * One of the METADATA_DOA_*_MODE constants. * * @return int */ public function getMode() { return $this->_mode; } /** * Get the fully qualified class name of * the supported meta-data schema. * * @return string */ public function getMetadataSchemaName() { return $this->_metadataSchemaName; } /** * Get the supported meta-data schema (lazy load) * * @return MetadataSchema */ public function &getMetadataSchema() { // Lazy-load the meta-data schema if this has // not been done before. if (is_null($this->_metadataSchema)) { $metadataSchemaName = $this->getMetadataSchemaName(); assert(!is_null($metadataSchemaName)); if (preg_match('/^[a-zA-Z0-9_.]+$/', $metadataSchemaName)) { // DEPRECATED as of 3.4.0: Schema class names should be fully qualified pkp/pkp-lib#8186 $this->_metadataSchema = & instantiate($metadataSchemaName, (string) \PKP\metadata\MetadataSchema::class); } elseif (class_exists($metadataSchemaName)) { $this->_metadataSchema = new $metadataSchemaName(); } if (!$this->_metadataSchema instanceof \PKP\metadata\MetadataSchema) { throw new \Exception('Metadata schema is unexpected class!'); } assert(is_object($this->_metadataSchema)); } return $this->_metadataSchema; } /** * Convenience method that returns the * meta-data name space. * * @return string */ public function getMetadataNamespace() { $metadataSchema = & $this->getMetadataSchema(); return $metadataSchema->getNamespace(); } /** * Get the supported application entity (class) name * * @return string */ public function getDataObjectName() { return $this->_dataObjectName; } /** * Return the data object class name * (without the package prefix) * * @return string */ public function getDataObjectClass() { if (is_null($this->_dataObjectClass)) { $dataObjectName = $this->getDataObjectName(); assert(!is_null($dataObjectName)); $dataObjectNameParts = explode('.', $dataObjectName); $this->_dataObjectClass = array_pop($dataObjectNameParts); } return $this->_dataObjectClass; } /** * Get the association type corresponding to the data * object type. * * @return int */ public function getAssocType() { return $this->_assocType; } /** * Set the target data object for meta-data injection. * * @param DataObject $targetDataObject */ public function setTargetDataObject(&$targetDataObject) { $this->_targetDataObject = & $targetDataObject; } /** * Get the target data object for meta-data injection. */ public function &getTargetDataObject() { return $this->_targetDataObject; } // // Abstract template methods // /** * Inject a MetadataDescription into the target DataObject * * @param MetadataDescription $metadataDescription * @param DataObject $targetDataObject * * @return DataObject */ public function &injectMetadataIntoDataObject(&$metadataDescription, &$targetDataObject) { // Must be implemented by sub-classes assert(false); } /** * Extract a MetadataDescription from a source DataObject. * * @param DataObject $sourceDataObject * * @return MetadataDescription */ public function extractMetadataFromDataObject(&$sourceDataObject) { // Must be implemented by sub-classes assert(false); } /** * Return the additional field names introduced by the * meta-data schema that need to be persisted in the * ..._settings table corresponding to the DataObject * which is supported by this adapter. * NB: The field names must be prefixed with the meta-data * schema namespace identifier. * * @param bool $translated if true, return localized field * names, otherwise return additional field names. * * @return array an array of field names to be persisted. */ public function getDataObjectMetadataFieldNames($translated = true) { // By default return all field names return $this->getMetadataFieldNames($translated); } // // Implement template methods from Filter // /** * Convert a MetadataDescription to an application * object or vice versa. * * @see Filter::process() * * @param mixed $input either a MetadataDescription or an application object * * @return mixed either a MetadataDescription or an application object */ public function &process(&$input) { // Do we inject or extract metadata? switch ($this->getMode()) { case self::METADATA_DOA_INJECTION_MODE: $targetDataObject = & $this->getTargetDataObject(); // Instantiate a new data object if none was given. if (is_null($targetDataObject)) { $targetDataObject = & $this->instantiateDataObject(); assert(is_a($targetDataObject, $this->getDataObjectName())); } // Inject meta-data into the data object. $output = & $this->injectMetadataIntoDataObject($input, $targetDataObject); break; case self::METADATA_DOA_EXTRACTION_MODE: $output = $this->extractMetadataFromDataObject($input); break; default: // Input should be validated by now. assert(false); } return $output; } // // Protected helper methods // /** * Instantiate a new data object of the * correct type. * * NB: This can be overridden by sub-classes for more complex * data objects. The standard implementation assumes there are * no constructor args to be set or configurations to be made. * * @return DataObject */ public function &instantiateDataObject() { $dataObjectName = $this->getDataObjectName(); assert(!is_null($dataObjectName)); $dataObject = & instantiate($dataObjectName, $this->getDataObjectClass()); return $dataObject; } /** * Instantiate a meta-data description that conforms to the * settings of this adapter. * * @return MetadataDescription */ public function &instantiateMetadataDescription() { $metadataDescription = new MetadataDescription($this->getMetadataSchemaName(), $this->getAssocType()); return $metadataDescription; } /** * Return all field names introduced by the * meta-data schema that might have to be persisted. * * @param bool $translated if true, return localized field * names, otherwise return additional field names. * * @return array an array of field names to be persisted. */ public function getMetadataFieldNames($translated = true) { // Do we need to build the field name cache first? if (is_null($this->_metadataFieldNames)) { // Initialize the cache array $this->_metadataFieldNames = []; // Retrieve all properties and add // their names to the cache $metadataSchema = & $this->getMetadataSchema(); $metadataSchemaNamespace = $metadataSchema->getNamespace(); $properties = & $metadataSchema->getProperties(); foreach ($properties as $property) { $propertyAssocTypes = $property->getAssocTypes(); if (in_array($this->_assocType, $propertyAssocTypes)) { // Separate translated and non-translated property names // and add the name space so that field names are unique // across various meta-data schemas. $this->_metadataFieldNames[$property->getTranslated()][] = $metadataSchemaNamespace . ':' . $property->getName(); } } } // Return the field names return $this->_metadataFieldNames[$translated]; } /** * Set several localized statements in a meta-data schema. * * @param MetadataDescription $metadataDescription * @param string $propertyName * @param array $localizedValues (keys: locale, values: localized values) */ public function addLocalizedStatements(&$metadataDescription, $propertyName, $localizedValues) { if (is_array($localizedValues)) { foreach ($localizedValues as $locale => $values) { // Handle cardinality "many" and "one" in the same way. if (is_scalar($values)) { $values = [$values]; } foreach ($values as $value) { $metadataDescription->addStatement($propertyName, $value, $locale); unset($value); } } } } /** * Directly inject all fields that are not mapped to the * data object into the data object's data array for * automatic persistence by the meta-data framework. * * @param MetadataDescription $metadataDescription * @param DataObject $dataObject */ public function injectUnmappedDataObjectMetadataFields(&$metadataDescription, &$dataObject) { // Handle translated and non-translated statements separately. foreach ([true, false] as $translated) { // Retrieve the unmapped fields. foreach ($this->getDataObjectMetadataFieldNames($translated) as $unmappedProperty) { // Identify the corresponding property name. [$namespace, $propertyName] = explode(':', $unmappedProperty); // Find out whether we have a statement for this unmapped property. if ($metadataDescription->hasStatement($propertyName)) { // Add the unmapped statement directly to the // data object. if ($translated) { $dataObject->setData($unmappedProperty, $metadataDescription->getStatementTranslations($propertyName)); } else { $dataObject->setData($unmappedProperty, $metadataDescription->getStatement($propertyName)); } } } } } /** * Directly extract all fields that are not mapped to the * data object from the data object's data array. * * @param DataObject $dataObject * @param MetadataDescription $metadataDescription */ public function extractUnmappedDataObjectMetadataFields(&$dataObject, &$metadataDescription) { $metadataSchema = & $this->getMetadataSchema(); $handledNamespace = $metadataSchema->getNamespace(); // Handle translated and non-translated statements separately. foreach ([true, false] as $translated) { // Retrieve the unmapped fields. foreach ($this->getDataObjectMetadataFieldNames($translated) as $unmappedProperty) { // Find out whether we have a statement for this unmapped property. if ($dataObject->hasData($unmappedProperty)) { // Identify the corresponding property name and namespace. [$namespace, $propertyName] = explode(':', $unmappedProperty); // Only extract data if the namespace of the property // is the same as the one handled by this adapter and the // property is within the current description. if ($namespace == $handledNamespace && $metadataSchema->hasProperty($propertyName)) { // Add the unmapped statement to the metadata description. if ($translated) { $this->addLocalizedStatements($metadataDescription, $propertyName, $dataObject->getData($unmappedProperty)); } else { $metadataDescription->addStatement($propertyName, $dataObject->getData($unmappedProperty)); } } } } } } } if (!PKP_STRICT_MODE) { class_alias('\PKP\metadata\MetadataDataObjectAdapter', '\MetadataDataObjectAdapter'); define('METADATA_DOA_INJECTION_MODE', MetadataDataObjectAdapter::METADATA_DOA_INJECTION_MODE); define('METADATA_DOA_EXTRACTION_MODE', MetadataDataObjectAdapter::METADATA_DOA_EXTRACTION_MODE); }