• Модуль: 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;
}