public function canSetProperty($propertyName, $value, $throw = false)
{
$propDefs = $this->getPropertyDefinitions();
try {
$type = $this->valueConverter->determineType($value);
} catch (ValueFormatException $e) {
if ($throw) {
throw new ValueFormatException(sprintf('Invalid value for property "%s": %s', $propertyName, $e->getMessage()), $e->getCode(), $e);
}
return false;
}
// check explicit matches first and keep wildcard definitions for later
$wildcards = array();
foreach ($propDefs as $prop) {
if ('*' === $prop->getName()) {
$wildcards[] = $prop;
} elseif ($propertyName == $prop->getName()) {
if (is_array($value) !== $prop->isMultiple()) {
if ($prop->isMultiple()) {
throw new ConstraintViolationException("The property definition is multivalued, but the value '{$value}' is not.");
}
if (is_array($value)) {
throw new ConstraintViolationException("The value {$value} is multivalued, but the property definition is not.");
}
}
$requiredType = $prop->getRequiredType();
if (PropertyType::UNDEFINED === $requiredType || $type === $requiredType) {
return true;
}
// try if we can convert. OPTIMIZE: would be nice to know without actually attempting to convert
try {
$this->valueConverter->convertType($value, $prop->getRequiredType(), $type);
return true;
} catch (ValueFormatException $e) {
// fall through and return false
}
if ($throw) {
throw new ConstraintViolationException("The property '{$propertyName}' with value '{$value}' can't be converted to an existing type.");
}
return false;
// if there is an explicit match, it has to fit
}
}
// now check if any of the wildcards matches
/** @var $prop PropertyDefinition */
foreach ($wildcards as $prop) {
if (is_array($value) != $prop->isMultiple()) {
continue;
}
$requiredType = $prop->getRequiredType();
if (PropertyType::UNDEFINED === $requiredType || $type === $requiredType) {
return true;
}
// try if we can convert. OPTIMIZE: would be nice to know without actually attempting to convert
try {
$this->valueConverter->convertType($value, $prop->getRequiredType(), $type);
return true;
} catch (ValueFormatException $e) {
if ($throw) {
throw new ValueFormatException($propertyName . ': ' . $e->getMessage(), $e->getCode(), $e);
}
return false;
// if there is an explicit match, it has to fit
}
}
if ($throw) {
$val = is_object($value) ? get_class($value) : (is_scalar($value) ? (string) $value : gettype($value));
throw new ConstraintViolationException("Node type definition does not allow to set the property with name '{$propertyName}' and value '{$val}'");
}
return false;
}