• Модуль: iblock
  • Путь к файлу: ~/bitrix/modules/iblock/classes/general/cml2.php
  • Класс: CIBlockCMLImport
  • Вызов: CIBlockCMLImport::ImportMetaData
function ImportMetaData($xml_root_id, $IBLOCK_TYPE, $IBLOCK_LID, $bUpdateIBlock = true)
{
	global $APPLICATION;

	$rs = $this->_xml_file->GetList(
		array("ID" => "asc"),
		array("ID" => $xml_root_id),
		array("ID", "NAME", "ATTRIBUTES")
	);
	$ar = $rs->Fetch();

	if ($ar)
	{
		foreach(array(LANGUAGE_ID, "en", "ru") as $lang)
		{
			$mess = MainLocalizationLoc::loadLanguageFile(__FILE__, $lang);
			if($ar["NAME"] === $mess["IBLOCK_XML2_COMMERCE_INFO"])
			{
				$this->mess = $mess;
				$this->next_step["lang"] = $lang;
			}
		}
		$xml_root_id = $ar["ID"];
	}

	if($ar && ($ar["ATTRIBUTES"] <> ''))
	{
		$info = unserialize($ar["ATTRIBUTES"], ['allowed_classes' => false]);
		if(is_array($info) && array_key_exists($this->mess["IBLOCK_XML2_SUM_FORMAT"], $info))
		{
			if(preg_match("#".$this->mess["IBLOCK_XML2_SUM_FORMAT_DELIM"]."=(.);{0,1}#", $info[$this->mess["IBLOCK_XML2_SUM_FORMAT"]], $match))
			{
				$this->next_step["sdp"] = $match[1];
			}
		}
	}

	$meta_data_xml_id = false;
	$XML_ELEMENTS_PARENT = false;
	$XML_SECTIONS_PARENT = false;
	$XML_PROPERTIES_PARENT = false;
	$XML_SECTIONS_PROPERTIES_PARENT = false;
	$XML_PRICES_PARENT = false;
	$XML_STORES_PARENT = false;
	$XML_BASE_UNITS_PARENT = false;
	$XML_SECTION_PROPERTIES = false;
	$arIBlock = array();

	$this->next_step["bOffer"] = false;
	$rs = $this->_xml_file->GetList(
		array(),
		array("PARENT_ID" => $xml_root_id, "NAME" => $this->mess["IBLOCK_XML2_CATALOG"]),
		array("ID", "ATTRIBUTES")
	);
	$ar = $rs->Fetch();
	if(!$ar)
	{
		$rs = $this->_xml_file->GetList(
			array(),
			array("PARENT_ID" => $xml_root_id, "NAME" => $this->mess["IBLOCK_XML2_OFFER_LIST"]),
			array("ID", "ATTRIBUTES")
		);
		$ar = $rs->Fetch();
		$this->next_step["bOffer"] = true;
	}
	if(!$ar)
	{
		$rs = $this->_xml_file->GetList(
			array(),
			array("PARENT_ID" => $xml_root_id, "NAME" => $this->mess["IBLOCK_XML2_OFFERS_CHANGE"]),
			array("ID", "ATTRIBUTES")
		);
		$ar = $rs->Fetch();
		$this->next_step["bOffer"] = true;
		$this->next_step["bUpdateOnly"] = true;
		$bUpdateIBlock = false;
	}

	if ($this->next_step["bOffer"] && !$this->bCatalog)
		return GetMessage('IBLOCK_XML2_MODULE_CATALOG_IS_ABSENT');

	if($ar)
	{
		if($ar["ATTRIBUTES"] <> '')
		{
			$attrs = unserialize($ar["ATTRIBUTES"], ['allowed_classes' => false]);
			if (is_array($attrs))
			{
				if (isset($attrs[$this->mess["IBLOCK_XML2_UPDATE_ONLY"]]))
				{
					$this->next_step["bUpdateOnly"] = $attrs[$this->mess["IBLOCK_XML2_UPDATE_ONLY"]] === "true"
						|| (int)$attrs[$this->mess["IBLOCK_XML2_UPDATE_ONLY"]] > 0
					;
				}
			}
		}

		$rs = $this->_xml_file->GetList(
			array("ID" => "asc"),
			array("PARENT_ID" => $ar["ID"])
		);
		while($ar = $rs->Fetch())
		{
			if(isset($ar["VALUE_CLOB"]))
				$ar["VALUE"] = $ar["VALUE_CLOB"];

			$trueValue = $ar['VALUE'] === 'true' || (int)$ar['VALUE'] > 0;

			if($ar["NAME"] == $this->mess["IBLOCK_XML2_ID"])
				$arIBlock["XML_ID"] = ($this->use_iblock_type_id? $IBLOCK_TYPE."-": "").$ar["VALUE"];
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_CATALOG_ID"])
				$arIBlock["CATALOG_XML_ID"] = ($this->use_iblock_type_id? $IBLOCK_TYPE."-": "").$ar["VALUE"];
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_NAME"])
				$arIBlock["NAME"] = $ar["VALUE"];
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_DESCRIPTION"])
			{
				$arIBlock["DESCRIPTION"] = $ar["VALUE"];
				$arIBlock["DESCRIPTION_TYPE"] = "html";
			}
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_POSITIONS"] || $ar["NAME"] == $this->mess["IBLOCK_XML2_OFFERS"])
				$XML_ELEMENTS_PARENT = $ar["ID"];
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_PRICE_TYPES"])
				$XML_PRICES_PARENT = $ar["ID"];
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_STORES"])
				$XML_STORES_PARENT = $ar["ID"];
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_BASE_UNITS"])
				$XML_BASE_UNITS_PARENT = $ar["ID"];
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_METADATA_ID"])
				$meta_data_xml_id = $ar["VALUE"];
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_UPDATE_ONLY"])
				$this->next_step["bUpdateOnly"] = $trueValue;
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_BX_CODE"])
				$arIBlock["CODE"] = $ar["VALUE"];
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_BX_API_CODE"])
				$arIBlock["API_CODE"] = $ar["VALUE"];
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_BX_SORT"])
				$arIBlock["SORT"] = $ar["VALUE"];
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_BX_LIST_URL"])
				$arIBlock["LIST_PAGE_URL"] = $ar["VALUE"];
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_BX_DETAIL_URL"])
				$arIBlock["DETAIL_PAGE_URL"] = $ar["VALUE"];
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_BX_SECTION_URL"])
				$arIBlock["SECTION_PAGE_URL"] = $ar["VALUE"];
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_BX_CANONICAL_URL"])
				$arIBlock["CANONICAL_PAGE_URL"] = $ar["VALUE"];
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_BX_INDEX_ELEMENTS"])
				$arIBlock["INDEX_ELEMENT"] = $trueValue ? "Y": "N";
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_BX_INDEX_SECTIONS"])
				$arIBlock["INDEX_SECTION"] = $trueValue ? "Y": "N";
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_BX_SECTIONS_NAME"])
				$arIBlock["SECTIONS_NAME"] = $ar["VALUE"];
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_BX_SECTION_NAME"])
				$arIBlock["SECTION_NAME"] = $ar["VALUE"];
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_BX_ELEMENTS_NAME"])
				$arIBlock["ELEMENTS_NAME"] = $ar["VALUE"];
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_BX_ELEMENT_NAME"])
				$arIBlock["ELEMENT_NAME"] = $ar["VALUE"];
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_BX_PICTURE"])
			{
				if($ar["VALUE"] <> '')
					$arIBlock["PICTURE"] = $this->MakeFileArray($ar["VALUE"]);
				else
					$arIBlock["PICTURE"] = $this->MakeFileArray($this->_xml_file->GetAllChildrenArray($ar["ID"]));
			}
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_BX_WORKFLOW"])
				$arIBlock["WORKFLOW"] = ($ar["VALUE"]=="true") || intval($ar["VALUE"])? "Y": "N";
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_INHERITED_TEMPLATES"])
			{
				$arIBlock["IPROPERTY_TEMPLATES"] = array();
				$arTemplates = $this->_xml_file->GetAllChildrenArray($ar["ID"]);
				foreach($arTemplates as $TEMPLATE)
				{
					$id = $TEMPLATE[$this->mess["IBLOCK_XML2_ID"]];
					$template = $TEMPLATE[$this->mess["IBLOCK_XML2_VALUE"]];
					if($id <> '' && $template <> '')
						$arIBlock["IPROPERTY_TEMPLATES"][$id] = $template;
				}
			}
			elseif($ar["NAME"] == $this->mess["IBLOCK_XML2_LABELS"])
			{
				$arLabels = $this->_xml_file->GetAllChildrenArray($ar["ID"]);
				foreach($arLabels as $arLabel)
				{
					$id = $arLabel[$this->mess["IBLOCK_XML2_ID"]];
					$label = $arLabel[$this->mess["IBLOCK_XML2_VALUE"]];
					if($id <> '' && $label <> '')
						$arIBlock[$id] = $label;
				}
			}
		}
		if($this->next_step["bOffer"] && !$this->use_offers)
		{
			if (isset($arIBlock["CATALOG_XML_ID"]) && $arIBlock["CATALOG_XML_ID"] !== '')
			{
				$arIBlock["XML_ID"] = $arIBlock["CATALOG_XML_ID"];
				$this->next_step["bUpdateOnly"] = true;
			}
		}

		$obIBlock = new CIBlock;
		$rsIBlocks = $obIBlock->GetList(array(), array("XML_ID"=>$arIBlock["XML_ID"]));
		$ar = $rsIBlocks->Fetch();

		//Also check for non bitrix xml file
		if(!$ar && !array_key_exists("CODE", $arIBlock))
		{
			if($this->next_step["bOffer"] && $this->use_offers)
				$rsIBlocks = $obIBlock->GetList(array(), array("XML_ID"=>"FUTURE-1C-OFFERS"));
			else
				$rsIBlocks = $obIBlock->GetList(array(), array("XML_ID"=>"FUTURE-1C-CATALOG"));
			$ar = $rsIBlocks->Fetch();
		}
		if($ar)
		{
			if($bUpdateIBlock && (!$this->next_step["bOffer"] || $this->use_offers))
			{
				if($obIBlock->Update($ar["ID"], $arIBlock))
					$arIBlock["ID"] = $ar["ID"];
				else
					return $obIBlock->LAST_ERROR;
			}
			else
			{
				$arIBlock["ID"] = $ar["ID"];
			}
		}
		else
		{
			$arIBlock["IBLOCK_TYPE_ID"] = $this->CheckIBlockType($IBLOCK_TYPE);
			if(!$arIBlock["IBLOCK_TYPE_ID"])
				return GetMessage("IBLOCK_XML2_TYPE_ADD_ERROR");
			$arIBlock["GROUP_ID"] = array(2=>"R");
			$arIBlock["LID"] = $this->CheckSites($IBLOCK_LID);
			$arIBlock["ACTIVE"] = "Y";
			$arIBlock["WORKFLOW"] = "N";
			if (
				$this->translit_on_add
				&& !array_key_exists("CODE", $arIBlock)
			)
			{
				$arIBlock["FIELDS"] = array(
					"CODE" => array( "DEFAULT_VALUE" => array(
						"TRANSLITERATION" => "Y",
						"TRANS_LEN" => $this->translit_on_add["max_len"],
						"TRANS_CASE" => $this->translit_on_add["change_case"],
						"TRANS_SPACE" => $this->translit_on_add["replace_space"],
						"TRANS_OTHER" => $this->translit_on_add["replace_other"],
						"TRANS_EAT" => $this->translit_on_add["delete_repeat_replace"]? "Y": "N",
					)),
					"SECTION_CODE" => array( "DEFAULT_VALUE" => array(
						"TRANSLITERATION" => "Y",
						"TRANS_LEN" => $this->translit_on_add["max_len"],
						"TRANS_CASE" => $this->translit_on_add["change_case"],
						"TRANS_SPACE" => $this->translit_on_add["replace_space"],
						"TRANS_OTHER" => $this->translit_on_add["replace_other"],
						"TRANS_EAT" => $this->translit_on_add["delete_repeat_replace"]? "Y": "N",
					)),
				);
			}
			$arIBlock["ID"] = $obIBlock->Add($arIBlock);
			if(!$arIBlock["ID"])
				return $obIBlock->LAST_ERROR;
		}

		//Make this catalog
		if($this->bCatalog && $this->next_step["bOffer"])
		{
			$obCatalog = new CCatalog();
			$intParentID = $this->GetIBlockByXML_ID($arIBlock["CATALOG_XML_ID"] ?? '');
			if (0 < intval($intParentID) && $this->use_offers)
			{
				$mxSKUProp = $obCatalog->LinkSKUIBlock($intParentID,$arIBlock["ID"]);
				if (!$mxSKUProp)
				{
					if ($ex = $APPLICATION->GetException())
					{
						$result = $ex->GetString();
						return $result;
					}
				}
				else
				{
					$rs = CCatalog::GetList(array(),array("IBLOCK_ID"=>$arIBlock["ID"]));
					if($arOffer = $rs->Fetch())
					{
						$boolFlag = $obCatalog->Update($arIBlock["ID"],array('PRODUCT_IBLOCK_ID' => $intParentID,'SKU_PROPERTY_ID' => $mxSKUProp));
					}
					else
					{
						$boolFlag = $obCatalog->Add(array("IBLOCK_ID"=>$arIBlock["ID"], "YANDEX_EXPORT"=>"N", "SUBSCRIPTION"=>"N",'PRODUCT_IBLOCK_ID' => $intParentID,'SKU_PROPERTY_ID' => $mxSKUProp));
					}
					if (!$boolFlag)
					{
						if ($ex = $APPLICATION->GetException())
						{
							$result = $ex->GetString();
							return $result;
						}
					}
				}
			}
			else
			{
				$rs = CCatalog::GetList(array(),array("IBLOCK_ID"=>$arIBlock["ID"]));
				if(!($rs->Fetch()))
				{
					$boolFlag = $obCatalog->Add(array("IBLOCK_ID"=>$arIBlock["ID"], "YANDEX_EXPORT"=>"N", "SUBSCRIPTION"=>"N"));
					if (!$boolFlag)
					{
						if ($ex = $APPLICATION->GetException())
						{
							$result = $ex->GetString();
							return $result;
						}
					}
				}
			}
		}

		//For non bitrix xml file
		//Check for mandatory properties and add them as necessary
		if(!array_key_exists("CODE", $arIBlock))
		{
			$arProperties = [];
			$arProperties['CML2_BAR_CODE'] = GetMessage('IBLOCK_XML2_BAR_CODE');
			$arProperties['CML2_ARTICLE'] = GetMessage('IBLOCK_XML2_ARTICLE');
			$arProperties['CML2_ATTRIBUTES'] = [
				'NAME' => GetMessage('IBLOCK_XML2_ATTRIBUTES'),
				'MULTIPLE' => 'Y',
				'WITH_DESCRIPTION' => 'Y',
				'MULTIPLE_CNT' => 1,
			];
			$arProperties['CML2_TRAITS'] = [
				'NAME' => GetMessage('IBLOCK_XML2_TRAITS'),
				'MULTIPLE' => 'Y',
				'WITH_DESCRIPTION' => 'Y',
				'MULTIPLE_CNT' => 1,
			];
			$arProperties['CML2_BASE_UNIT'] = [
				'NAME' => GetMessage('IBLOCK_XML2_BASE_UNIT_NAME'),
				'WITH_DESCRIPTION' => 'Y',
			];
			$arProperties['CML2_TAXES'] = [
				'NAME' => GetMessage('IBLOCK_XML2_TAXES'),
				'MULTIPLE' => 'Y',
				'WITH_DESCRIPTION' => 'Y',
				'MULTIPLE_CNT' => 1,
			];
			$arProperties[CIBlockPropertyTools::XML_MORE_PHOTO] = CIBlockPropertyTools::getPropertyDescription(
				CIBlockPropertyTools::CODE_MORE_PHOTO,
				['IBLOCK_ID' => $arIBlock['ID']]
			);
			$arProperties['CML2_FILES'] = [
				'NAME' => GetMessage('IBLOCK_XML2_FILES'),
				'MULTIPLE' => 'Y',
				'WITH_DESCRIPTION' => 'Y',
				'MULTIPLE_CNT' => 1,
				'PROPERTY_TYPE' => IblockPropertyTable::TYPE_FILE,
				'CODE' => 'FILES',
			];
			$arProperties['CML2_MANUFACTURER'] = [
				'NAME' => GetMessage('IBLOCK_XML2_PROP_MANUFACTURER'),
				'MULTIPLE' => 'N',
				'WITH_DESCRIPTION' => 'N',
				'MULTIPLE_CNT' => 1,
				'PROPERTY_TYPE' => IblockPropertyTable::TYPE_LIST,
			];

			foreach($arProperties as $k=>$v)
			{
				$result = $this->CheckProperty($arIBlock["ID"], $k, $v);
				if($result!==true)
					return $result;
			}
			//For offers make special property: link to catalog
			if (isset($arIBlock['CATALOG_XML_ID']) && $this->use_offers)
			{
				$this->CheckProperty(
					$arIBlock['ID'],
					CIBlockPropertyTools::XML_SKU_LINK,
					CIBlockPropertyTools::getPropertyDescription(
						CIBlockPropertyTools::CODE_SKU_LINK,
						[
							'IBLOCK_ID' => $arIBlock['ID'],
							'LINK_IBLOCK_ID' => $this->GetIBlockByXML_ID($arIBlock['CATALOG_XML_ID']),
						]
					)
				);
			}
		}

		$this->next_step["IBLOCK_ID"] = $arIBlock["ID"];
		$this->next_step["XML_ELEMENTS_PARENT"] = $XML_ELEMENTS_PARENT;
	}

	if($meta_data_xml_id)
	{
		$rs = $this->_xml_file->GetList(
			array(),
			array("PARENT_ID" => $xml_root_id, "NAME" => $this->mess["IBLOCK_XML2_METADATA"]),
			array("ID")
		);
		while($arMetadata = $rs->Fetch())
		{
			//Find referenced metadata
			$bMetaFound = false;
			$meta_roots = array();
			$rsMetaRoots = $this->_xml_file->GetList(
				array("ID" => "asc"),
				array("PARENT_ID" => $arMetadata["ID"])
			);
			while($arMeta = $rsMetaRoots->Fetch())
			{
				if(isset($arMeta["VALUE_CLOB"]))
					$arMeta["VALUE"] = $arMeta["VALUE_CLOB"];

				if($arMeta["NAME"] == $this->mess["IBLOCK_XML2_ID"] && $arMeta["VALUE"] == $meta_data_xml_id)
					$bMetaFound = true;

				$meta_roots[] = $arMeta;
			}

			//Get xml parents of the properties and sections
			if($bMetaFound)
			{
				foreach($meta_roots as $arMeta)
				{
					if($arMeta["NAME"] == $this->mess["IBLOCK_XML2_GROUPS"])
						$XML_SECTIONS_PARENT = $arMeta["ID"];
					elseif($arMeta["NAME"] == $this->mess["IBLOCK_XML2_PROPERTIES"])
						$XML_PROPERTIES_PARENT = $arMeta["ID"];
					elseif($arMeta["NAME"] == $this->mess["IBLOCK_XML2_GROUPS_PROPERTIES"])
						$XML_SECTIONS_PROPERTIES_PARENT = $arMeta["ID"];
					elseif($arMeta["NAME"] == $this->mess["IBLOCK_XML2_SECTION_PROPERTIES"])
						$XML_SECTION_PROPERTIES = $arMeta["ID"];
					elseif($arMeta["NAME"] == $this->mess["IBLOCK_XML2_PRICE_TYPES"])
						$XML_PRICES_PARENT = $arMeta["ID"];
					elseif($arMeta["NAME"] == $this->mess["IBLOCK_XML2_STORES"])
						$XML_STORES_PARENT = $arMeta["ID"];
					elseif($arMeta["NAME"] == $this->mess["IBLOCK_XML2_BASE_UNITS"])
						$XML_BASE_UNITS_PARENT = $arMeta["ID"];
				}
				break;
			}
		}
	}

	$iblockFields = CIBlock::GetFields($arIBlock["ID"]);
	$iblockFields["XML_IMPORT_START_TIME"] = array(
		"NAME" => "XML_IMPORT_START_TIME",
		"IS_REQUIRED" => "N",
		"DEFAULT_VALUE" => date("Y-m-d H:i:s"),
	);
	CIBlock::SetFields($arIBlock["ID"], $iblockFields);

	if($XML_PROPERTIES_PARENT)
	{
		$result = $this->ImportProperties($XML_PROPERTIES_PARENT, $arIBlock["ID"]);
		if($result!==true)
			return $result;
	}

	if($XML_SECTION_PROPERTIES)
	{
		$result = $this->ImportSectionProperties($XML_SECTION_PROPERTIES, $arIBlock["ID"]);
		if($result!==true)
			return $result;
	}

	if($XML_SECTIONS_PROPERTIES_PARENT)
	{
		$result = $this->ImportSectionsProperties($XML_SECTIONS_PROPERTIES_PARENT, $arIBlock["ID"]);
		if($result!==true)
			return $result;
	}

	if($XML_PRICES_PARENT)
	{
		if($this->bCatalog)
		{
			$result = $this->ImportPrices($XML_PRICES_PARENT, $arIBlock["ID"], $IBLOCK_LID);
			if($result!==true)
				return $result;
		}
	}

	if($XML_STORES_PARENT)
	{
		if($this->bCatalog)
		{
			$result = $this->ImportStores($XML_STORES_PARENT);
			if($result!==true)
				return $result;
		}
	}

	if($XML_BASE_UNITS_PARENT)
	{
		if($this->bCatalog)
		{
			$result = $this->ImportBaseUnits($XML_BASE_UNITS_PARENT);
			if($result!==true)
				return $result;
		}
	}

	$this->next_step["section_sort"] = 100;
	$this->next_step["XML_SECTIONS_PARENT"] = $XML_SECTIONS_PARENT;

	$rs = $this->_xml_file->GetList(
		array(),
		array("PARENT_ID" => $xml_root_id, "NAME" => $this->mess["IBLOCK_XML2_PRODUCTS_SETS"]),
		array("ID", "ATTRIBUTES")
	);
	$ar = $rs->Fetch();
	if ($ar)
	{
		$this->next_step["SETS"] = (int)$ar["ID"];
	}

	return true;
}