/**
  * Get the names of properties with a given data type.
  * @param $propertyType mixed a valid property type description
  * @return array an array of string values representing valid property names
  */
 function getPropertyNamesByType($propertyType)
 {
     assert(in_array($propertyType, MetadataProperty::getSupportedTypes()));
     $propertyNames = array();
     foreach ($this->_properties as $property) {
         $allowedPropertyTypes = $property->getAllowedTypes();
         if (isset($allowedPropertyTypes[$propertyType])) {
             $propertyNames[] = $property->getName();
         }
     }
     return $propertyNames;
 }
Beispiel #2
0
 /**
  * @covers MetadataProperty::isValid
  */
 public function testValidateMultitype()
 {
     $metadataProperty = new MetadataProperty('testElement', array(), array(METADATA_PROPERTY_TYPE_DATE, METADATA_PROPERTY_TYPE_INTEGER), false, METADATA_PROPERTY_CARDINALITY_ONE);
     self::assertEquals(array(METADATA_PROPERTY_TYPE_DATE => null), $metadataProperty->isValid('2009-07-28'));
     self::assertEquals(array(METADATA_PROPERTY_TYPE_INTEGER => null), $metadataProperty->isValid(5));
     self::assertFalse($metadataProperty->isValid(null));
     self::assertFalse($metadataProperty->isValid('string'));
 }
 /**
  * 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
                             // 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 = (int) $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:
                         // Validate with the URI validator
                         import('lib.pkp.classes.validation.ValidatorUri');
                         $validator = new ValidatorUri();
                         if ($validator->isValid($value)) {
                             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;
 }
Beispiel #4
0
 /**
  * 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 $types 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 $compositeType integer an association type, mandatory if $type is METADATA_PROPERTY_TYPE_COMPOSITE
  */
 function MetadataProperty($name, $assocTypes = array(), $types = METADATA_PROPERTY_TYPE_STRING, $translated = false, $cardinality = METADATA_PROPERTY_CARDINALITY_ONE, $displayName = null)
 {
     // Validate name and assoc type array
     assert(is_string($name));
     assert(is_array($assocTypes));
     // A single type (scalar or composite) will be
     // transformed to an array of types so that we
     // can treat them uniformly.
     if (is_scalar($types) || count($types) == 1) {
         $types = array($types);
     }
     // Validate types
     foreach ($types as $type) {
         if (is_array($type)) {
             // Validate composite types
             assert(count($type) == 1 && isset($type[METADATA_PROPERTY_TYPE_COMPOSITE]) && is_integer($type[METADATA_PROPERTY_TYPE_COMPOSITE]));
             // Properties that allow composite types cannot be translated
             assert(!$translated);
         } else {
             // Validate all other types
             assert($type != METADATA_PROPERTY_TYPE_COMPOSITE && in_array($type, MetadataProperty::getSupportedTypes()));
         }
     }
     // Validate translation and cardinality
     assert(is_bool($translated));
     assert(in_array($cardinality, MetadataProperty::getSupportedCardinalities()));
     // Default display name
     if (is_null($displayName)) {
         $displayName = 'metadata.property.displayName.' . $name;
     }
     assert(is_string($displayName));
     // Initialize the class
     $this->_name = (string) $name;
     $this->_assocTypes =& $assocTypes;
     $this->_types =& $types;
     $this->_translated = (bool) $translated;
     $this->_cardinality = (int) $cardinality;
     $this->_displayName = (string) $displayName;
 }