public function _setValue($value, $type = PropertyType::UNDEFINED, $constructor = false)
{
if (null === $value) {
$this->remove();
return;
}
if (is_string($type)) {
$type = PropertyType::valueFromName($type);
} elseif (!is_numeric($type)) {
// @codeCoverageIgnoreStart
throw new RepositoryException("INTERNAL ERROR -- No valid type specified ({$type})");
// @codeCoverageIgnoreEnd
} else {
//sanity check. this will throw InvalidArgumentException if $type is not a valid type
PropertyType::nameFromValue($type);
}
if ($constructor || $this->isNew()) {
$this->isMultiple = is_array($value);
}
if (is_array($value) && !$this->isMultiple) {
throw new ValueFormatException('Can not set a single value property (' . $this->name . ') with an array of values');
}
if ($this->isMultiple && is_scalar($value)) {
throw new ValueFormatException('Can not set a multivalue property (' . $this->name . ') with a scalar value');
}
if ($this->isMultiple) {
foreach ($value as $key => $v) {
if (null === $v) {
unset($value[$key]);
}
}
}
//TODO: check if changing type allowed.
/*
* if ($type !== null && ! canHaveType($type)) {
* throw new ConstraintViolationException("Can not set this property to type ".PropertyType::nameFromValue($type));
* }
*/
if (PropertyType::UNDEFINED === $type) {
// avoid changing type of multivalue property with empty array
if (!$this->isMultiple() || count($value) || PropertyType::UNDEFINED === $this->type) {
$type = $this->valueConverter->determineType($value);
} else {
$type = $this->type;
}
}
$targetType = $type;
/*
* TODO: find out with node type definition if the new type is allowed
if ($this->type !== $type) {
if (!canHaveType($type)) {
//convert to an allowed type
}
}
*/
if (PropertyType::BINARY !== $targetType || $constructor && $this->isNew() || !$this->isNew() && PropertyType::UNDEFINED !== $this->type && $this->type !== $targetType) {
$value = $this->valueConverter->convertType($value, $targetType, $constructor ? PropertyType::UNDEFINED : $type);
}
if (PropertyType::BINARY === $targetType) {
if ($constructor && !$this->isNew()) {
// reading a binary property from backend, we do not get the stream immediately but just the size
if (is_array($value)) {
$this->isMultiple = true;
}
$this->type = PropertyType::BINARY;
$this->length = $value;
$this->value = null;
return;
}
if (is_array($value)) {
$this->length = array();
foreach ($value as $v) {
$stat = is_resource($v) ? fstat($v) : array('size' => -1);
$this->length[] = $stat['size'];
}
} elseif (is_resource($value)) {
$stat = fstat($value);
$this->length = $stat['size'];
} else {
$this->length = -1;
}
}
$this->type = $targetType;
$this->value = $value;
}