• Модуль: main
  • Путь к файлу: ~/bitrix/modules/main/lib/orm/objectify/entityobject.php
  • Класс: BitrixMainORMObjectifyEntityObject
  • Вызов: EntityObject::sysSaveRelations
public function sysSaveRelations(Result $result)
{
	$saveCascade = true;

	foreach ($this->_actualValues as $fieldName => $value)
	{
		$field = $this->entity->getField($fieldName);

		if ($field instanceof Reference && !array_key_exists($fieldName, $this->_currentValues))
		{
			// if there is a new relation, then the old one is not into cascade anymore
			if ($saveCascade && !empty($value))
			{
				$value->save();
			}
		}
		elseif ($field instanceof OneToMany)
		{
			$collection = $value;

			/** @var static[] $objectsToSave */
			$objectsToSave = [];

			/** @var static[] $objectsToDelete */
			$objectsToDelete = [];

			if ($collection->sysIsChanged())
			{
				// save changed elements of collection
				foreach ($collection->sysGetChanges() as $change)
				{
					list($remoteObject, $changeType) = $change;

					if ($changeType == Collection::OBJECT_ADDED)
					{
						$objectsToSave[] = $remoteObject;
					}
					elseif ($changeType == Collection::OBJECT_REMOVED)
					{
						if ($field->getCascadeDeletePolicy() == CascadePolicy::FOLLOW)
						{
							$objectsToDelete[] = $remoteObject;
						}
						else
						{
							// set null by default
							$objectsToSave[] = $remoteObject;
						}
					}
				}
			}

			if ($saveCascade)
			{
				// everything should be saved, except deleted
				foreach ($collection->getAll() as $remoteObject)
				{
					if (!in_array($remoteObject, $objectsToDelete) && !in_array($remoteObject, $objectsToSave))
					{
						$objectsToSave[] = $remoteObject;
					}
				}
			}

			// save remote objects
			foreach ($objectsToSave as $remoteObject)
			{
				$remoteResult = $remoteObject->save();

				if (!$remoteResult->isSuccess())
				{
					$result->addErrors($remoteResult->getErrors());
				}
			}

			// delete remote objects
			foreach ($objectsToDelete as $remoteObject)
			{
				$remoteResult = $remoteObject->delete();

				if (!$remoteResult->isSuccess())
				{
					$result->addErrors($remoteResult->getErrors());
				}
			}

			// forget collection changes
			if ($collection->sysIsChanged())
			{
				$collection->sysResetChanges();
			}
		}
		elseif ($field instanceof ManyToMany)
		{
			$collection = $value;

			if ($value->sysIsChanged())
			{
				foreach ($collection->sysGetChanges() as $change)
				{
					list($remoteObject, $changeType) = $change;

					// initialize mediator object
					$mediatorObjectClass = $field->getMediatorEntity()->getObjectClass();
					$localReferenceName = $field->getLocalReferenceName();
					$remoteReferenceName = $field->getRemoteReferenceName();

					/** @var static $mediatorObject */
					$mediatorObject = new $mediatorObjectClass;
					$mediatorObject->sysSetValue($localReferenceName, $this);
					$mediatorObject->sysSetValue($remoteReferenceName, $remoteObject);

					// add or remove mediator depending on changeType
					if ($changeType == Collection::OBJECT_ADDED)
					{
						$mediatorObject->save();
					}
					elseif ($changeType == Collection::OBJECT_REMOVED)
					{
						// destroy directly through data class
						$mediatorDataClass = $field->getMediatorEntity()->getDataClass();
						$mediatorDataClass::delete($mediatorObject->primary);
					}
				}

				// forget collection changes
				$collection->sysResetChanges();
			}

			// should everything be saved?
			if ($saveCascade)
			{
				foreach ($collection->getAll() as $remoteObject)
				{
					$remoteResult = $remoteObject->save();

					if (!$remoteResult->isSuccess())
					{
						$result->addErrors($remoteResult->getErrors());
					}
				}
			}
		}

		// remove deleted objects from collections
		if ($value instanceof Collection)
		{
			$value->sysReviseDeletedObjects();
		}
	}

	if ($saveCascade)
	{
		$this->sysSaveCurrentReferences();
	}
}