- Модуль: main
- Путь к файлу: ~/bitrix/modules/main/lib/orm/objectify/entityobject.php
- Класс: BitrixMainORMObjectifyEntityObject
- Вызов: EntityObject::sysSetValue
public function sysSetValue($fieldName, $value)
{
$fieldName = StringHelper::strtoupper($fieldName);
$field = $this->entity->getField($fieldName);
// system validations
if ($field instanceof ScalarField)
{
// restrict updating primary
if ($this->_state !== State::RAW && in_array($field->getName(), $this->entity->getPrimaryArray()))
{
throw new SystemException(sprintf(
'Setting value for Primary `%s` in `%s` is not allowed, it is read-only field',
$field->getName(), get_called_class()
));
}
}
// no setter for expressions
if ($field instanceof ExpressionField && !($field instanceof UserTypeField))
{
throw new SystemException(sprintf(
'Setting value for ExpressionField `%s` in `%s` is not allowed, it is read-only field',
$fieldName, get_called_class()
));
}
if ($field instanceof Reference)
{
if (!empty($value))
{
// validate object class and skip null
$remoteObjectClass = $field->getRefEntity()->getObjectClass();
if (!($value instanceof $remoteObjectClass))
{
throw new ArgumentException(sprintf(
'Expected instance of `%s`, got `%s` instead',
$remoteObjectClass,
is_object($value) ? get_class($value) : gettype($value)
));
}
}
}
// change only if value is different from actual
// exclude UF fields for this check as long as UF file fields look into request to change value
// (BitrixMainUserFieldTypesFileType::onBeforeSave)
// let UF manager handle all the values without optimization
if (array_key_exists($fieldName, $this->_actualValues) && !($field instanceof UserTypeField))
{
if ($field instanceof IReadable)
{
if ($field->cast($value) === $this->_actualValues[$fieldName]
// double check if value objects are different, but db values are the same
|| $field->convertValueToDb($field->modifyValueBeforeSave($value, []))
=== $field->convertValueToDb($field->modifyValueBeforeSave($this->_actualValues[$fieldName], []))
)
{
// forget previous runtime change
unset($this->_currentValues[$fieldName]);
return $this;
}
}
elseif ($field instanceof Reference)
{
/** @var static $value */
if ($value->primary === $this->_actualValues[$fieldName]->primary)
{
// forget previous runtime change
unset($this->_currentValues[$fieldName]);
return $this;
}
}
}
// set value
if ($field instanceof ScalarField || $field instanceof UserTypeField)
{
$this->_currentValues[$fieldName] = $value;
}
elseif ($field instanceof Reference)
{
/** @var static $value */
$this->_currentValues[$fieldName] = $value;
// set elemental fields if there are any
$elementals = $field->getElementals();
if (!empty($elementals))
{
$elementalsChanged = false;
foreach ($elementals as $localFieldName => $remoteFieldName)
{
if ($this->entity->getField($localFieldName)->isPrimary())
{
// skip local primary in non-raw state
if ($this->state !== State::RAW)
{
continue;
}
// skip autocomplete
if ($this->state === State::RAW && $this->entity->getField($localFieldName)->isAutocomplete())
{
continue;
}
}
$remoteField = $field->getRefEntity()->getField($remoteFieldName);
if (!empty($value) && !$value->sysHasValue($remoteField->getName())
&& $value->state === State::RAW && $remoteField->isPrimary() && $remoteField->isAutocomplete())
{
// get primary value after save
$localObject = $this;
$remoteObject = $value;
$remoteObject->sysAddOnPrimarySetListener(function () use (
$localObject, $localFieldName, $remoteObject, $remoteFieldName
) {
$localObject->sysSetValue($localFieldName, $remoteObject->get($remoteFieldName));
});
}
else
{
$elementalValue = empty($value) ? null : $value->sysGetValue($remoteFieldName);
$this->sysSetValue($localFieldName, $elementalValue);
}
$elementalsChanged = true;
}
if (!$elementalsChanged)
{
// object was not changed actually
return $this;
}
}
}
else
{
throw new SystemException(sprintf(
'Unknown field type `%s` in system setter of `%s`', get_class($field), get_called_class()
));
}
if ($this->_state == State::ACTUAL)
{
$this->sysChangeState(State::CHANGED);
}
// on primary gain event
if ($field instanceof ScalarField && $field->isPrimary() && $this->sysHasPrimary())
{
$this->sysOnPrimarySet();
}
return $this;
}