• Модуль: webdav
  • Путь к файлу: ~/bitrix/modules/webdav/classes/iblock.php
  • Класс: CWebDavIblock
  • Вызов: CWebDavIblock::copy_commit
function copy_commit($arFrom, $arTo, $options, $drop = false)
{
	$result = true;
	$actionWithSymlink = !empty($arFrom['is_symlink']) || !empty($arTo['is_symlink']);
	$action = ($drop ? 'move' : 'copy');
	if (!$this->CheckWebRights("", array('action' => $action, 'from' => $arFrom, 'to' => $arTo))) // warning: array param
		return $this->ThrowAccessDenied(__LINE__);


	$toIblockId = $this->IBLOCK_ID;
	if(!empty($arTo['IBLOCK_ID']))
	{
		$toIblockId = $arTo['IBLOCK_ID'];
	}

	$fromIblockId = $this->IBLOCK_ID;
	if(!empty($arFrom['IBLOCK_ID']))
	{
		$fromIblockId = $arFrom['IBLOCK_ID'];
	}

	$arFromSections = $this->GetSectionsTree(array("section_id" => $arFrom["ID"]));
	$arToSections = $this->GetSectionsTree(array("section_id" => $arTo["ID"], 'not_check_permissions' => true));
	$res = array();
	foreach ($arToSections as $key => $val)
		$res[$val["PATH"]] = $val;
	$arToSections = $res;

	$arSectionsToCopyElements[$arFrom["ID"]] = array("TO_ID" => $arTo["ID"], "NEED_CHECK_NAME" => true);
	$result = true;
	$bSectionsWasUpdated = false;
	$res = reset($arFromSections);
	$arParentId = array(intval($arTo["ID"]), $res["ID"]);
	$iParentDeep = intval($res["DEPTH_LEVEL"]);
	if (!empty($arFromSections))
	{
		$se = new CIBlockSection();
		do
		{
			$res["DEPTH_LEVEL"] = intval($res["DEPTH_LEVEL"]);
			while ($res["DEPTH_LEVEL"] <= $iParentDeep)
			{
				array_pop($arParentId);
				$iParentDeep--;
			}
			if (!array_key_exists($res["PATH"], $arToSections))
			{
				if (!$actionWithSymlink && $drop === true) // Moving folders
				{
					$GLOBALS['DB']->StartTransaction();
					$se_result = $se->Update($res["ID"], array("IBLOCK_SECTION_ID" => end($arParentId)));

					if (!$se_result)
					{
						$GLOBALS['DB']->Rollback();
						$result = $this->ThrowError("409 Conflict", "FOLDER_IS_NOT_MOVED", str_replace(
							array("#FOLDER#", "#TEXT_ERROR#"),
							array($res["PATH"], $se->LAST_ERROR), GetMessage("WD_FILE_ERROR103")), __LINE__);
						break;
					}
					else
					{
						$GLOBALS['DB']->Commit();
					}
					$this->_onEvent( 'Move', $res["ID"], "FOLDER", array( 'TO' => end($arParentId)));
					$bSectionsWasUpdated = true;
					// Remove brunch elements as we move all the brunch
					$deep = intval($res["DEPTH_LEVEL"]);
					while ($res = next($arFromSections))
					{
						$res["DEPTH_LEVEL"] = intval($res["DEPTH_LEVEL"]);
						if ($deep <= $res["DEPTH_LEVEL"])
						{
							prev($arFromSections);
							break;
						}
					}
				}
				else // Copy folders
				{
					$se_result = $se->Add(array("IBLOCK_ID" => $toIblockId, "IBLOCK_SECTION_ID" => end($arParentId), "NAME" => $res["NAME"]));
					if (!$se_result)
					{
						$result = $this->ThrowError("409 Conflict", "FOLDER_IS_NOT_MOVED", str_replace(
							array("#FOLDER#", "#TEXT_ERROR#"),
							array($res["PATH"], $se->LAST_ERROR), GetMessage("WD_FILE_ERROR104")), __LINE__);
						break;
					}
					$this->_onEvent('Add', $se_result, 'FOLDER');
					$bSectionsWasUpdated = true;
					$arSectionsToCopyElements[$res["ID"]] = array("TO_ID" => $se_result, "NEED_CHECK_NAME" => false);
					$arParentId[] = $se_result;
					$iParentDeep++;
				}
			}
			else
			{
				$arParentId[] = $arToSections[$res["PATH"]]["ID"];
				$iParentDeep++;

				if (!$options["overwrite"])
				{
					$result = $this->ThrowError("409 Conflict", "FOLDER_ALREADY_EXISTS", str_replace("#FOLDER#", $res["PATH"], GetMessage("WD_FILE_ERROR5")), __LINE__);
					break;
				}
				else
				{
					$arSectionsToCopyElements[$res["ID"]] = array("TO_ID" => $arToSections[$res["PATH"]]["ID"], "NEED_CHECK_NAME" => true);
				}
			}
		} while ($res = next($arFromSections));

		if ($bSectionsWasUpdated)
		{
			$this->ClearCache("section");
		}
	}

	if ($result === true)
	{
		$el = new CIBlockElement();
		foreach ($arSectionsToCopyElements as $iFromSectionID => $arElement)
		{
			$arToElements = array();
			if ($arElement["NEED_CHECK_NAME"] != false)
			{
				$db_res = CIBlockElement::GetList(
					array("NAME" => "ASC"),
					array("IBLOCK_ID" => $toIblockId, "SECTION_ID" => $arElement["TO_ID"], "SHOW_NEW" => "Y", "CHECK_PERMISSIONS" => "N"),
					false,
					false,
					array("ID", "NAME"));
				if ($db_res && $res = $db_res->Fetch())
				{
					do
					{
						$arToElements[mb_strtolower($res["NAME"])] = $res;
					} while ($res = $db_res->Fetch());
				}
			}

			$db_res = CIBlockElement::GetList(
				array("NAME" => "ASC"),
				array("IBLOCK_ID" => $fromIblockId, "SECTION_ID" => $iFromSectionID, "SHOW_NEW" => "Y"),
				false,
				false,
				array("ID", "NAME", "IBLOCK_SECTION_ID", "PROPERTY_".$this->file_prop));

			if ($db_res && $res = $db_res->Fetch())
			{
				do
				{
					$res["NAME"] = mb_strtolower($res["NAME"]);

					if (array_key_exists($res["NAME"], $arToElements))
					{
						if (!$options["overwrite"])
						{
							$result = $this->ThrowError( "409 Conflict", "FILE_ALREADY_EXISTS", str_replace("#FILE#", $res["NAME"], GetMessage("WD_FILE_ERROR8")), __LINE__);
							break;
						}
						else
						{ // TODO: check permission to destroy elements
							$tmp = $arToElements[$res["NAME"]];
							$this->_onEvent('Delete', $tmp["ID"]);
							$this->_ib_elm_delete($tmp["ID"]);
						}
					}

					if (!$actionWithSymlink && $drop == true)
					{
						if ($this->workflow == 'bizproc' || $this->workflow == 'bizproc_limited')
						{
							$this->AddDocumentToHistory($res['ID'], $res['NAME']);
						}
						$el->Update(
							$res["ID"],
							array("IBLOCK_SECTION_ID" => $arElement["TO_ID"], "WF_COMMENTS" => GetMessage("WD_FILE_IS_MOVED")),
							($this->workflow == 'workflow'));
						$this->_onEvent( 'Move', $res["ID"], "FILE", array( 'TO' => $arElement["TO_ID"]));
						if ($this->workflow == 'bizproc' || $this->workflow == 'bizproc_limited')
						{
							$db_res2 = CIBlockElement::GetList(array(), array("WF_PARENT_ELEMENT_ID" => $res["ID"], "SHOW_HISTORY" => "Y"), false, false, array("ID"));
							if ($db_res2 && $res2 = $db_res2->Fetch())
							{
								do
								{
									$res = $el->Update($res2["ID"], array("IBLOCK_SECTION_ID" => $arElement["TO_ID"]), false, true, false, false);
								} while ($res2 = $db_res2->Fetch());
							}
						}
					}
					else
					{
						if($actionWithSymlink)
						{
							//move and don't delete item
							if(!self::_move_from_iblock_to_iblock($res["ID"], $toIblockId, $arElement["TO_ID"], false, true))
							{
								return '409 Conflict';
							}
							elseif($drop) //move action
							{
								//$this->DELETE(array("element_id" => $res["ID"]));
								//delete section in method COPY
							}
						}
						else
						{
							$arFile = CFile::GetFileArray($res["PROPERTY_".$this->file_prop."_VALUE"]);
							$optionsPut = array(
								'path' => $this->_udecode($this->_get_path($arElement["TO_ID"]))."/".$res["NAME"],
								'content_length' => $arFile['FILE_SIZE'],
								'content_type' => $arFile['CONTENT_TYPE']);
							$stat = $this->PUT($optionsPut);
							if ($stat === false)
							{
								return '403 Forbidden';
							}
							elseif (is_resource($stat) && get_resource_type($stat) == 'stream')
							{
								fclose($stat);

								$arTmpFile = CFile::MakeFileArray($arFile['ID']); // since CopyDirFiles doesn't support clouds
								if (!(is_array($arTmpFile) && is_set($arTmpFile, 'tmp_name')))
									return '409 Conflict';

								CopyDirFiles($arTmpFile['tmp_name'], $optionsPut["TMP_FILE"]);
								clearstatcache();

								$optionsPut['USER_FIELDS'] = $this->GetUfFields($res["ID"]);
								if (!$this->put_commit($optionsPut))
								{
									return '409 Conflict';
								}
							}
						}
					}
				} while ($res = $db_res->Fetch());
			}
			if ($result !== true)
			{
				break;
			}
		}
	}
	return $result;
}