• Модуль: tasks
  • Путь к файлу: ~/bitrix/modules/tasks/lib/internals/database/structure/closuretree.php
  • Класс: BitrixTasksInternalsDataBaseStructureClosureTree
  • Вызов: ClosureTree::attach
static function attach($id, $parentId = 0, array $settings = array())
{
	$result = static::canAttach($id, $parentId);

	if($result->isSuccess())
	{
		// check if link is already on its place
		if($parentId && static::isPathExist($parentId, $id, array('DIRECT' => true)))
		{
			$result->addWarning('PATH_EXISTS', Loc::getMessage('TASKS_CLOSURE_TREE_LINK_EXISTS'));
			return $result;
		}

		if(static::isNodeExist($id))
		{
			if ($settings['NEW_NODE'] ?? null)
			{
				$result->addError('NODE_EXISTS', Loc::getMessage('TASKS_CLOSURE_TREE_NODE_EXISTS_BUT_DECLARED_NEW'));
			}
			else
			{
				// we should do detach node from the previous point, if any
				$dResult = static::detach($id);
				$result->adoptErrors($dResult);
			}
		}

		// if !$parentId, then it behaves like detachNode()
		if($result->isSuccess() && $parentId)
		{
			// attach to a new point
			static::ensureNodeExists($parentId);
			static::ensureNodeExists($id);

			$pCName = static::getParentNodeColumnName();
			$cName = static::getNodeColumnName();

			// now link each item of path to $parentId with each item of subtree of $id

			// todo: rewrite this IN SQL
			$path = static::getPath($parentId, array(), array('RETURN_ARRAY' => true));
			$subTree = static::getSubTree($id, array(), array('RETURN_ARRAY' => true));

			$edgeBuffer = array();

			foreach($path as $pItem)
			{
				foreach($subTree as $stItem)
				{
					$edgeBuffer[] = array(
						$pCName => $pItem['__ID'],
						$cName => $stItem['__ID'],
						'DIRECT' => $pItem['__ID'] == $parentId && $stItem['__ID'] == $id ? 1 : 0
					);
				}
			}

			try
			{
				Helper::insertBatch(static::getTableName(), $edgeBuffer);
			}
			catch(DBSqlException $e)
			{
				$result->addException($e, 'Error linking nodes');
			}
		}
	}

	return $result;
}