One Hat Cyber Team
Your IP :
216.73.216.182
Server IP :
203.175.9.166
Server :
Linux tanggamus.iixcp.rumahweb.net 5.14.0-427.28.1.el9_4.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Aug 2 03:44:10 EDT 2024 x86_64
Server Software :
LiteSpeed
PHP Version :
7.4.33
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
home
/
cite5577
/
www
/
lib
/
pkp
/
classes
/
metadata
/
View File Name :
MetadataProperty.inc.php
<?php /** * @file classes/metadata/MetadataProperty.inc.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 MetadataProperty * @ingroup metadata * @see MetadataSchema * @see MetadataRecord * * @brief Class representing metadata properties. It specifies type and cardinality * of a meta-data property (=term, field, ...) and whether the property can * be internationalized. It also provides a validator to test whether input * conforms to the property specification. * * In the DCMI abstract model, this class specifies a property together with its * allowed range and cardinality. * * We also define the resource types (application entities, association types) * that can be described with the property. This allows us to check that only * valid resource associations are made. It also allows us to prepare property * entry forms or displays for a given resource type and integrate these in the * work-flow of the resource. By dynamically adding or removing assoc types, * end users will be able to configure the meta-data fields that they wish to * make available, persist or enter in their application. */ // literal values (plain) define('METADATA_PROPERTY_TYPE_STRING', 0x01); // literal values (typed) define('METADATA_PROPERTY_TYPE_DATE', 0x02); // This is W3CDTF encoding without time (YYYY[-MM[-DD]])! define('METADATA_PROPERTY_TYPE_INTEGER', 0x03); // non-literal value string from a controlled vocabulary define('METADATA_PROPERTY_TYPE_VOCABULARY', 0x04); // non-literal value URI define('METADATA_PROPERTY_TYPE_URI', 0x05); // non-literal value pointing to a separate description set instance (=another MetadataRecord object) define('METADATA_PROPERTY_TYPE_COMPOSITE', 0x06); // allowed cardinality of statements for a given property type in a meta-data schema define('METADATA_PROPERTY_CARDINALITY_ONE', 0x01); define('METADATA_PROPERTY_CARDINALITY_MANY', 0x02); class MetadataProperty { /** @var string property name */ var $_name; /** @var string a translation id */ var $_displayName; /** @var int the resource types that can be described with this property */ var $_assocTypes; /** @var array allowed property types */ var $_allowedTypes; /** @var boolean flag that defines whether the property can be translated */ var $_translated; /** @var integer property cardinality */ var $_cardinality; /** @var string validation message */ var $_validationMessage; /** @var boolean */ var $_mandatory; /** * Constructor * @param $name string the unique name of the property within a meta-data schema (can be a property URI) * @param $assocTypes array an array of integers that define the application entities that can * be described with this property. * @param $allowedTypes mixed must be a scalar or an array with the supported types, default: METADATA_PROPERTY_TYPE_STRING * @param $translated boolean whether the property may have various language versions, default: false * @param $cardinality integer must be on of the supported cardinalities, default: METADATA_PROPERTY_CARDINALITY_ONE * @param $displayName string * @param $validationMessage string A string that can be displayed in case a user tries to set an invalid value for this property. * @param $mandatory boolean Is this a mandatory property within the schema? */ function __construct($name, $assocTypes = array(), $allowedTypes = METADATA_PROPERTY_TYPE_STRING, $translated = false, $cardinality = METADATA_PROPERTY_CARDINALITY_ONE, $displayName = null, $validationMessage = null, $mandatory = false) { // Validate name and assoc type array if (!is_string($name)) throw new InvalidArgumentException('$name should be a string.'); if (!is_array($assocTypes)) throw new InvalidArgumentException('$assocTypes should be an array.'); // A single type will be transformed to an // array of types so that we can handle them // uniformly. if (is_scalar($allowedTypes) || count($allowedTypes) == 1) { $allowedTypes = array($allowedTypes); } // Validate types $canonicalizedTypes = array(); foreach($allowedTypes as $allowedType) { if (is_array($allowedType)) { // We expect an array with a single entry // of the form "type => additional parameter". assert(count($allowedType) == 1); // Reset the array, just in case... reset($allowedType); // Extract the type and the additional parameter $allowedTypeId = key($allowedType); $allowedTypeParam = current($allowedType); } else { // No additional parameter has been set. $allowedTypeId = $allowedType; $allowedTypeParam = null; } // Validate type if (!in_array($allowedTypeId, MetadataProperty::getSupportedTypes())) throw new InvalidArgumentException('Allowed types must be supported types!'); // Transform the type array in a // structure that is easy to handle // in for loops. $canonicalizedTypes[$allowedTypeId][] = $allowedTypeParam; // Validate additional type parameter. switch($allowedTypeId) { case METADATA_PROPERTY_TYPE_COMPOSITE: // Validate the assoc id of the composite. if (!is_integer($allowedTypeParam)) throw new InvalidArgumentException('Allowed type parameter should be an integer.'); // Properties that allow composite types cannot be translated. if ($translated) throw new InvalidArgumentException('Properties that allow composite types cannot be translated.'); break; case METADATA_PROPERTY_TYPE_VOCABULARY: // Validate the symbolic name of the vocabulary. if (!is_string($allowedTypeParam)) throw new InvalidArgumentException('Allowed type parameter should be a string.'); break; default: // No other types support an additional parameter if (!is_null($allowedTypeParam)) throw new InvalidArgumentException('An additional parameter was supplied for an unsupported metadata property type.'); } } // Validate translation and cardinality if (!is_bool($translated)) throw new InvalidArgumentException('$translated must be a boolean'); if (!in_array($cardinality, MetadataProperty::getSupportedCardinalities())) throw new InvalidArgumentException('$cardinality must be a supported cardinality.'); // Default display name if (is_null($displayName)) $displayName = 'metadata.property.displayName.'.$name; if (!is_string($displayName)) throw new InvalidArgumentException('$displayName must be a string.'); // Default validation message if (is_null($validationMessage)) $validationMessage = 'metadata.property.validationMessage.'.$name; if (!is_string($validationMessage)) throw new InvalidArgumentException('$validationMessage must be a string.'); // Initialize the class $this->_name = (string)$name; $this->_assocTypes =& $assocTypes; $this->_allowedTypes =& $canonicalizedTypes; $this->_translated = (boolean)$translated; $this->_cardinality = (integer)$cardinality; $this->_displayName = (string)$displayName; $this->_validationMessage = (string)$validationMessage; $this->_mandatory = (boolean)$mandatory; } /** * Get the name * @return string */ function getName() { return $this->_name; } /** * Returns a canonical form of the property * name ready to be used as a property id in an * external context (e.g. Forms or Templates). * @return string */ function getId() { // Replace special characters in XPath-like names // as 'person-group[@person-group-type="author"]'. $from = array( '[', ']', '@', '"', '=' ); $to = array( '-', '', '', '', '-' ); $propertyId = trim(str_replace($from, $to, $this->getName()), '-'); $propertyId = PKPString::camelize($propertyId); return $propertyId; } /** * Get the translation id representing * the display name of the property. * @return string */ function getDisplayName() { return $this->_displayName; } /** * Get the allowed association types * (resources that can be described * with this property) * @return array a list of integers representing * association types. */ function &getAssocTypes() { return $this->_assocTypes; } /** * Get the allowed type * @return integer */ function getAllowedTypes() { return $this->_allowedTypes; } /** * Is this property translated? * @return boolean */ function getTranslated() { return $this->_translated; } /** * Get the cardinality * @return integer */ function getCardinality() { return $this->_cardinality; } /** * Get the validation message * @return string */ function getValidationMessage() { return $this->_validationMessage; } /** * Is this property mandatory? * @return boolean */ function getMandatory() { return $this->_mandatory; } // // Public methods // /** * Validate a given input against the property specification * * The given value must validate against at least one of the * allowed types. The first allowed type id will be returned as * validation result. If the given value fits none of the allowed * types, then we'll return 'false'. * * @param $value mixed the input to be validated * @param $locale string the locale to be used for validation * @return array|boolean an array with a single entry of the format * "type => additional type parameter" against which the value * validated or boolean false if not validated at all. */ function isValid($value, $locale = null) { // We never accept null values or arrays. if (is_null($value) || is_array($value)) return false; // Translate the locale. if (is_null($locale)) $locale = ''; // MetadataProperty::getSupportedTypes() returns an ordered // list of possible meta-data types with the most specific // type coming first so that we always correctly identify // specializations (e.g. a date is a specialized string). $allowedTypes = $this->getAllowedTypes(); foreach (MetadataProperty::getSupportedTypes() as $testedType) { if (isset($allowedTypes[$testedType])) { foreach ($allowedTypes[$testedType] as $allowedTypeParam) { // Type specific validation switch ($testedType) { case METADATA_PROPERTY_TYPE_COMPOSITE: // Composites can either be represented by a meta-data description // or by a string of the form AssocType:AssocId if the composite // has already been persisted in the database. switch(true) { // Test for MetadataDescription format case is_a($value, 'MetadataDescription'): $assocType = $value->getAssocType(); break; // Test for AssocType:AssocId format case is_string($value): $valueParts = explode(':', $value); if (count($valueParts) != 2) break 2; // break the outer switch list($assocType, $assocId) = $valueParts; if (!(is_numeric($assocType) && is_numeric($assocId))) break 2; // break the outer switch $assocType = (integer)$assocType; break; default: // None of the allowed types break; } // Check that the association type matches // with the allowed association type (which // is configured as an additional type parameter). if (isset($assocType) && $assocType === $allowedTypeParam) return array(METADATA_PROPERTY_TYPE_COMPOSITE => $assocType); break; case METADATA_PROPERTY_TYPE_VOCABULARY: // Interpret the type parameter of this type like this: // symbolic[:assoc-type:assoc-id]. If no assoc type/id are // given then we assume :0:0 to represent site-wide vocabs. $vocabNameParts = explode(':', $allowedTypeParam); $vocabNamePartsCount = count($vocabNameParts); switch ($vocabNamePartsCount) { case 1: // assume a site-wide vocabulary $symbolic = $allowedTypeParam; $assocType = $assocId = 0; break; case 3: // assume a context-specific vocabulary list($symbolic, $assocType, $assocId) = $vocabNameParts; break; default: // Invalid configuration assert(false); } if (is_string($value)) { // Try to translate the string value into a controlled vocab entry $controlledVocabEntryDao = DAORegistry::getDAO('ControlledVocabEntryDAO'); /* @var $controlledVocabEntryDao ControlledVocabEntryDAO */ if (!is_null($controlledVocabEntryDao->getBySetting($value, $symbolic, $assocType, $assocId, 'name', $locale))) { // The string was successfully translated so mark it as "valid". return array(METADATA_PROPERTY_TYPE_VOCABULARY => $allowedTypeParam); } } if (is_integer($value)) { // Validate with controlled vocabulary validator import('lib.pkp.classes.validation.ValidatorControlledVocab'); $validator = new ValidatorControlledVocab($symbolic, $assocType, $assocId); if ($validator->isValid($value)) { return array(METADATA_PROPERTY_TYPE_VOCABULARY => $allowedTypeParam); } } break; case METADATA_PROPERTY_TYPE_URI: import('lib.pkp.classes.validation.ValidatorFactory'); $validator = ValidatorFactory::make( array('uri' => $value), array('uri' => 'url') ); if (!$validator->fails()) { return array(METADATA_PROPERTY_TYPE_URI => null); } break; case METADATA_PROPERTY_TYPE_DATE: // We allow the following patterns: // YYYY-MM-DD, YYYY-MM and YYYY $datePattern = '/^[0-9]{4}(-[0-9]{2}(-[0-9]{2})?)?$/'; if (!preg_match($datePattern, $value)) break; // Check whether the given string is really a valid date $dateParts = explode('-', $value); // Set the day and/or month to 1 if not set $dateParts = array_pad($dateParts, 3, 1); // Extract the date parts list($year, $month, $day) = $dateParts; // Validate the date (only leap days will pass unnoticed ;-) ) // Who invented this argument order? if (checkdate($month, $day, $year)) return array(METADATA_PROPERTY_TYPE_DATE => null); break; case METADATA_PROPERTY_TYPE_INTEGER: if (is_integer($value)) return array(METADATA_PROPERTY_TYPE_INTEGER => null); break; case METADATA_PROPERTY_TYPE_STRING: if (is_string($value)) return array(METADATA_PROPERTY_TYPE_STRING => null); break; default: // Unknown type. As we validate type in the setter, this // should be unreachable code. assert(false); } } } } // Return false if the value didn't validate against any // of the allowed types. return false; } // // Public static methods // /** * Return supported meta-data property types * * NB: These types are sorted from most specific to * most general and will be validated in this order * so that we'll always identify more specific types * as such (see MetadataProperty::isValid() for more * details). * * @return array supported meta-data property types */ static function getSupportedTypes() { static $_supportedTypes = array( METADATA_PROPERTY_TYPE_COMPOSITE, METADATA_PROPERTY_TYPE_VOCABULARY, METADATA_PROPERTY_TYPE_URI, METADATA_PROPERTY_TYPE_DATE, METADATA_PROPERTY_TYPE_INTEGER, METADATA_PROPERTY_TYPE_STRING ); return $_supportedTypes; } /** * Return supported cardinalities * @return array supported cardinalities */ static function getSupportedCardinalities() { static $_supportedCardinalities = array( METADATA_PROPERTY_CARDINALITY_ONE, METADATA_PROPERTY_CARDINALITY_MANY ); return $_supportedCardinalities; } }