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