Current Path : /var/www/www-root/data/www/monolith-realty.ru/bitrix/modules/iblock/classes/general/ |
Current File : /var/www/www-root/data/www/monolith-realty.ru/bitrix/modules/iblock/classes/general/cml2.php |
<?php use Bitrix\Main; use Bitrix\Main\ModuleManager; use Bitrix\Main\Loader; use Bitrix\Iblock; use Bitrix\Catalog; use Bitrix\Catalog\Product; IncludeModuleLangFile(__FILE__); class CIBlockCMLImport { public const IBLOCK_CACHE_FREEZE = 'D'; public const IBLOCK_CACHE_FINAL = 'F'; public const IBLOCK_CACHE_HIT = 'H'; public const IBLOCK_CACHE_NORMAL = 'N'; var $LAST_ERROR = ""; /** @var bool|array */ var $next_step = false; var $files_dir = false; var $use_offers = true; var $force_offers = false; var $use_iblock_type_id = false; var $use_crc = true; var $preview = false; var $detail = false; var $iblock_resize = false; /** @var CIBlockXMLFile $_xml_file */ var $_xml_file = null; var $bCatalog = false; var $isCatalogIblock = false; var $PROPERTY_MAP = array(); var $SECTION_MAP = array(); var $PRICES_MAP = array(); var $arProperties = array(); var $arSectionCache = array(); var $arElementCache = array(); var $arEnumCache = array(); var $arCurrencyCache = array(); var $arTaxCache = array(); var $mess = array(); var $arTempFiles = array(); var $arFileDescriptionsMap = array(); var $arElementFilesId = array(); var $arElementFiles = array(); var $arLinkedProps = false; var $translit_on_add = false; var $translit_on_update = false; var $translit_params = array(); var $skip_root_section = false; var $disable_change_price_name = false; protected $activeStores = array(); protected $iblockCacheMode = self::IBLOCK_CACHE_NORMAL; private $bitrix24mode = null; protected $currentUserId = null; protected $currencyIncluded = null; protected array $productSizes = [ 'WIDTH', 'LENGTH', 'HEIGHT', ]; function InitEx(&$next_step, $params) { $defaultParams = array( "files_dir" => false, "use_crc" => true, "preview" => false, "detail" => false, "use_offers" => false, "force_offers" => false, "use_iblock_type_id" => false, "table_name" => "b_xml_tree", "translit_on_add" => false, "translit_on_update" => false, "translit_params" => array( "max_len" => 255, "change_case" => 'L', // 'L' - toLower, 'U' - toUpper, false - do not change "replace_space" => '-', "replace_other" => '-', "delete_repeat_replace" => true, ), "skip_root_section" => false, "disable_change_price_name" => false, "iblock_cache_mode" => self::IBLOCK_CACHE_NORMAL ); foreach($defaultParams as $key => $value) if(!array_key_exists($key, $params)) $params[$key] = $value; $this->Init($next_step, $params["files_dir"], $params["use_crc"], $params["preview"], $params["detail"], $params["use_offers"], $params["use_iblock_type_id"], $params["table_name"] ); if($params["translit_on_add"]) $this->translit_on_add = $params["translit_params"]; if($params["translit_on_update"]) $this->translit_on_update = $params["translit_params"]; if ($params["disable_change_price_name"]) $this->disable_change_price_name = $params["disable_change_price_name"]; $this->skip_root_section = ($params["skip_root_section"] === true); $this->force_offers = ($params["force_offers"] === true); if ( $params['iblock_cache_mode'] == self::IBLOCK_CACHE_FREEZE || $params['iblock_cache_mode'] == self::IBLOCK_CACHE_FINAL || $params['iblock_cache_mode'] == self::IBLOCK_CACHE_HIT || $params['iblock_cache_mode'] == self::IBLOCK_CACHE_NORMAL ) { $this->iblockCacheMode = $params['iblock_cache_mode']; } } function Init(&$next_step, $files_dir = false, $use_crc = true, $preview = false, $detail = false, $use_offers = false, $use_iblock_type_id = false, $table_name = "b_xml_tree") { global $USER; $this->currentUserId = (isset($USER) && $USER instanceof CUser ? (int)$USER->GetID() : 0); $this->next_step = &$next_step; $this->files_dir = $files_dir; $this->use_offers = $use_offers; $this->use_iblock_type_id = $use_iblock_type_id; $this->use_crc = $use_crc; $this->_xml_file = new CIBlockXMLFile($table_name); if(!is_array($preview) && $preview) $this->iblock_resize = true; if(is_array($preview) && count($preview)==2) $this->preview = $preview; else $this->preview = false; if(is_array($detail) && count($detail)==2) $this->detail = $detail; else $this->detail = false; $this->bCatalog = Loader::includeModule('catalog'); $this->currencyIncluded = Loader::includeModule('currency'); $this->bitrix24mode = ModuleManager::isModuleInstalled('bitrix24'); $this->arProperties = array(); $this->PROPERTY_MAP = array(); if (isset($this->next_step["IBLOCK_ID"]) && $this->next_step["IBLOCK_ID"] > 0) { $obProperty = new CIBlockProperty; $rsProperties = $obProperty->GetList(array(), array("IBLOCK_ID"=>$this->next_step["IBLOCK_ID"], "ACTIVE"=>"Y")); while($arProperty = $rsProperties->Fetch()) { $this->PROPERTY_MAP[$arProperty["XML_ID"]] = $arProperty["ID"]; $this->arProperties[$arProperty["ID"]] = $arProperty; } if ($this->bCatalog) { $catalogsIterator = \Bitrix\Catalog\CatalogIblockTable::getList(array( 'select' => array('IBLOCK_ID'), 'filter' => array('=IBLOCK_ID' => $this->next_step["IBLOCK_ID"]) )); if ($catalogData = $catalogsIterator->fetch()) $this->isCatalogIblock = true; unset($catalogData, $catalogsIterator); } } if (isset($this->next_step['lang']) && $this->next_step['lang']) { $this->mess = Main\Localization\Loc::loadLanguageFile(__FILE__, $this->next_step['lang']); } $this->arTempFiles = array(); $this->arLinkedProps = false; } public static function CheckIfFileIsCML($file_name) { if(file_exists($file_name) && is_file($file_name)) { $fp = fopen($file_name, "rb"); if(is_resource($fp)) { $header = fread($fp, 1024); fclose($fp); if(preg_match("/<"."\\?XML[^>]{1,}encoding=[\"']([^>\"']{1,})[\"'][^>]{0,}\\?".">/i", $header, $matches)) { if(strtoupper($matches[1]) !== strtoupper(LANG_CHARSET)) $header = Main\Text\Encoding::convertEncoding($header, $matches[1], LANG_CHARSET); } foreach(array(LANGUAGE_ID, "en", "ru") as $lang) { $mess = Main\Localization\Loc::loadLanguageFile(__FILE__, $lang); if(strpos($header, "<".$mess["IBLOCK_XML2_COMMERCE_INFO"]) !== false) return $lang; } } } return false; } function DropTemporaryTables() { return $this->_xml_file->DropTemporaryTables(); } function CreateTemporaryTables() { return $this->_xml_file->CreateTemporaryTables(); } function IndexTemporaryTables() { return $this->_xml_file->IndexTemporaryTables(); } function ReadXMLToDatabase($fp, &$NS, $time_limit=0, $read_size = 1024) { return $this->_xml_file->ReadXMLToDatabase($fp, $NS, $time_limit, $read_size); } public function GetRoot() { return $this->_xml_file->GetRoot(); } function StartSession($sess_id) { return $this->_xml_file->StartSession($sess_id); } function GetSessionRoot() { return $this->_xml_file->GetSessionRoot(); } function EndSession() { return $this->_xml_file->EndSession(); } public function GetFilePosition() { return $this->_xml_file->GetFilePosition(); } function CleanTempFiles() { foreach($this->arTempFiles as $file) { if (file_exists($file)) unlink($file); } $this->arTempFiles = array(); } function MakeFileArray($file, $fields = array()) { if(is_array($file)) { if( array_key_exists($this->mess["IBLOCK_XML2_BX_URL"], $file) && $file[$this->mess["IBLOCK_XML2_BX_URL"]] <> '' ) { if (Loader::includeModule('clouds')) { $bucket = CCloudStorage::FindBucketByFile($file[$this->mess["IBLOCK_XML2_BX_URL"]]); if(is_object($bucket) && $bucket->READ_ONLY === "Y") { return array( "name" => $file[$this->mess["IBLOCK_XML2_BX_ORIGINAL_NAME"]], "description" => $file[$this->mess["IBLOCK_XML2_DESCRIPTION"]], "tmp_name" => $file[$this->mess["IBLOCK_XML2_BX_URL"]], "file_size" => $file[$this->mess["IBLOCK_XML2_BX_FILE_SIZE"]], "width" => $file[$this->mess["IBLOCK_XML2_BX_FILE_WIDTH"]], "height" => $file[$this->mess["IBLOCK_XML2_BX_FILE_HEIGHT"]], "type" => $file[$this->mess["IBLOCK_XML2_BX_FILE_CONTENT_TYPE"]], "content" => "", //Fake field in order to avoid warning "bucket" => $bucket, ); } } return CFile::MakeFileArray($this->URLEncode($file[$this->mess["IBLOCK_XML2_BX_URL"]])); //Download from the cloud } } else { if ($file <> '') { $external_id = md5($file); if (is_file($this->files_dir.$file)) return CFile::MakeFileArray($this->files_dir.$file, false, false, $external_id); $fileId = $this->CheckFileByName($external_id, $fields); if ($fileId > 0) return CFile::MakeFileArray($fileId); } } return array("tmp_name"=>"", "del"=>"Y"); } function URLEncode($str) { $strEncodedURL = ''; $arUrlComponents = preg_split("#(://|/|\\?|=|&)#", $str, -1, PREG_SPLIT_DELIM_CAPTURE); foreach($arUrlComponents as $i => $part_of_url) { if($i % 2) $strEncodedURL .= $part_of_url; else $strEncodedURL .= urlencode($part_of_url); } return $strEncodedURL; } function CheckFileByName($file, $fields = null) { $external_id = $file; $fileName = bx_basename($file); if (!empty($fields) && $fileName != "") { if (empty($this->arElementFiles)) { $this->arElementFiles = array(); $ID = array(); foreach ($this->arElementFilesId as $fileId) { foreach($fileId as $value) $ID[$value] = $value; } $rsFile = CFile::GetList(array(), array( "@ID" => implode(",", $ID), )); while ($arFile = $rsFile->Fetch()) { $arFile["~ORIGINAL_NAME"] = preg_replace("/(\\.resize[0-9]+\\.)/", ".", $arFile["ORIGINAL_NAME"]); $this->arElementFiles[$arFile["ID"]] = $arFile; } } foreach ($fields as $fieldId) { if (isset($this->arElementFilesId[$fieldId])) { foreach ($this->arElementFilesId[$fieldId] as $fileId) { if (isset($this->arElementFiles[$fileId])) { if ($this->arElementFiles[$fileId]["EXTERNAL_ID"] === $external_id) return $fileId; if ($this->arElementFiles[$fileId]["~ORIGINAL_NAME"] === $fileName) return $fileId; } } } } } return false; } function ResizePicture($file, $resize, $primaryField, $secondaryField = "") { static $errorFile = array("tmp_name"=>"", "del"=>"Y"); $external_id = md5($file); if($file == '') { return $errorFile; } if(file_exists($this->files_dir.$file) && is_file($this->files_dir.$file)) { $file = $this->files_dir.$file; } elseif(file_exists($file) && is_file($file)) { } elseif(($fileId = $this->CheckFileByName($external_id, array($primaryField))) > 0) { return CFile::MakeFileArray($fileId); } elseif($secondaryField && ($fileId = $this->CheckFileByName($external_id, array($secondaryField))) > 0) { $storedFile = CFile::MakeFileArray($fileId); if ($storedFile) { $tempFile = CTempFile::GetFileName(bx_basename($storedFile["tmp_name"])); CheckDirPath($tempFile); if (copy($storedFile["tmp_name"], $tempFile)) { $storedFile["tmp_name"] = $tempFile; return $storedFile; } else { return $errorFile; } } else { return $errorFile; } } else { return $errorFile; } if(!is_array($resize) || !preg_match("#(\\.)([^./\\\\]+?)$#", $file)) { $arFile = CFile::MakeFileArray($file, false, false, $external_id); if($arFile && $this->iblock_resize) $arFile["COPY_FILE"] = "Y"; return $arFile; } $i = 1; while(file_exists(preg_replace("#(\\.)([^./\\\\]+?)$#", ".resize".$i.".\\2", $file))) $i++; $new_file = preg_replace("#(\\.)([^./\\\\]+?)$#", ".resize".$i.".\\2", $file); if (!CFile::ResizeImageFile($file, $new_file, array("width"=>$resize[0], "height"=>$resize[1]))) return CFile::MakeFileArray($file, false, false, $external_id); $this->arTempFiles[] = $new_file; return CFile::MakeFileArray($new_file, false, false, $external_id); } function GetIBlockByXML_ID($XML_ID) { if($XML_ID <> '') { $obIBlock = new CIBlock; $rsIBlock = $obIBlock->GetList(array(), array("XML_ID"=>$XML_ID, "CHECK_PERMISSIONS" => "N")); if($arIBlock = $rsIBlock->Fetch()) return $arIBlock["ID"]; else return false; } return false; } function GetSectionByXML_ID($IBLOCK_ID, $XML_ID) { if (!isset($this->arSectionCache[$IBLOCK_ID])) $this->arSectionCache[$IBLOCK_ID] = array(); if (!isset($this->arSectionCache[$IBLOCK_ID][$XML_ID])) { $rsSection = CIBlockSection::GetList(array(), array("IBLOCK_ID"=>$IBLOCK_ID, "EXTERNAL_ID"=>$XML_ID), false, array('ID')); if($arSection = $rsSection->Fetch()) $this->arSectionCache[$IBLOCK_ID][$XML_ID] = $arSection["ID"]; else $this->arSectionCache[$IBLOCK_ID][$XML_ID] = false; unset($rsSection); unset($arSection); } return $this->arSectionCache[$IBLOCK_ID][$XML_ID]; } function GetElementByXML_ID($IBLOCK_ID, $XML_ID) { if($XML_ID == '') return false; if (!isset($this->arElementCache[$IBLOCK_ID])) $this->arElementCache[$IBLOCK_ID] = array(); if (!isset($this->arElementCache[$IBLOCK_ID][$XML_ID])) { $obElement = new CIBlockElement; $rsElement = $obElement->GetList( array('ID' => 'ASC'), array("=XML_ID" => $XML_ID, "IBLOCK_ID" => $IBLOCK_ID), false, false, array("ID", "XML_ID") ); if($arElement = $rsElement->Fetch()) $this->arElementCache[$IBLOCK_ID][$XML_ID] = $arElement["ID"]; else $this->arElementCache[$IBLOCK_ID][$XML_ID] = false; } return $this->arElementCache[$IBLOCK_ID][$XML_ID]; } function GetEnumByXML_ID($PROP_ID, $XML_ID) { if($XML_ID == '') return ""; if(!isset($this->arEnumCache[$PROP_ID])) $this->arEnumCache[$PROP_ID] = array(); if(!isset($this->arEnumCache[$PROP_ID][$XML_ID])) { $rsEnum = CIBlockPropertyEnum::GetList( array(), array("EXTERNAL_ID" => $XML_ID, "PROPERTY_ID" => $PROP_ID) ); if($arEnum = $rsEnum->Fetch()) $this->arEnumCache[$PROP_ID][$XML_ID] = $arEnum["ID"]; else $this->arEnumCache[$PROP_ID][$XML_ID] = false; } return $this->arEnumCache[$PROP_ID][$XML_ID]; } function GetSectionEnumByXML_ID($FIELD_ID, $XML_ID) { if($XML_ID == '') return ""; $cacheId = "E".$FIELD_ID; if(!isset($this->arEnumCache[$cacheId])) $this->arEnumCache[$cacheId] = array(); if(!isset($this->arEnumCache[$cacheId][$XML_ID])) { $obEnum = new CUserFieldEnum; $rsEnum = $obEnum->GetList(array(), array( "USER_FIELD_ID" => $FIELD_ID, "XML_ID" => $XML_ID, )); if($arEnum = $rsEnum->Fetch()) $this->arEnumCache[$cacheId][$XML_ID] = $arEnum["ID"]; else $this->arEnumCache[$cacheId][$XML_ID] = false; } if ($this->arEnumCache[$cacheId][$XML_ID]) return $this->arEnumCache[$cacheId][$XML_ID]; else return $XML_ID; } function GetPropertyByXML_ID($IBLOCK_ID, $XML_ID) { $obProperty = new CIBlockProperty; $rsProperty = $obProperty->GetList(array(), array("IBLOCK_ID"=>$IBLOCK_ID, "XML_ID"=>$XML_ID)); if($arProperty = $rsProperty->Fetch()) return $arProperty["ID"]; else return false; } function CheckProperty($IBLOCK_ID, $code, $xml_name) { $obProperty = new CIBlockProperty; $rsProperty = $obProperty->GetList(array(), array("IBLOCK_ID"=>$IBLOCK_ID, "XML_ID"=>$code)); $dbProperty = $rsProperty->Fetch(); if(!$dbProperty) { $arProperty = array( "IBLOCK_ID" => $IBLOCK_ID, "NAME" => is_array($xml_name)? $xml_name["NAME"]: $xml_name, "CODE" => $code, "XML_ID" => $code, "MULTIPLE" => "N", "PROPERTY_TYPE" => "S", "ACTIVE" => "Y", ); if(is_array($xml_name)) { foreach($xml_name as $name => $value) $arProperty[$name] = $value; } $ID = $obProperty->Add($arProperty); if(!$ID) return $obProperty->LAST_ERROR; } elseif (is_array($xml_name)) { $update = array(); foreach($xml_name as $name => $value) { if (($name != "NAME") && ($dbProperty[$name] != $value)) { $update[$name] = $value; } } if ($update) { $obProperty->Update($dbProperty["ID"], $update); } } return true; } function CheckTax($title, $rate) { if ($rate === null) { $taxName = GetMessage('IBLOCK_NO_VAT_TITLE'); } else { $taxName = $title . " " . $rate . "%"; } if (isset($this->arTaxCache[$taxName])) { return $this->arTaxCache[$taxName]; } $vatParams = [ 'select' => ['ID'], ]; if ($rate === null) { $vatParams['filter'] = [ '=EXCLUDE_VAT' => 'Y', ]; } else { $vatParams['filter'] = [ '=NAME' => $taxName, '=EXCLUDE_VAT' => 'N', '=RATE' => $rate, ]; } $getResult = \Bitrix\Catalog\Model\Vat::getList($vatParams)->fetch(); if (isset($getResult['ID'])) { $vatId = $getResult['ID']; $this->arTaxCache[$taxName] = $vatId; return $vatId; } $addParams = [ 'ACTIVE' => 'Y', 'NAME' => $taxName, ]; if ($rate === null) { $addParams['EXCLUDE_VAT'] = 'Y'; } else { $addParams['RATE'] = $rate; } $this->arTaxCache[$taxName] = \Bitrix\Catalog\Model\Vat::add($addParams)->getId(); return $this->arTaxCache[$taxName]; } function CheckCurrency($currency) { global $CML2_CURRENCY; if($currency==$this->mess["IBLOCK_XML2_RUB"]) { $currency="RUB"; } elseif(!preg_match("/^[a-zA-Z]+$/", $currency)) { if( is_array($CML2_CURRENCY) && isset($CML2_CURRENCY[$currency]) && is_string($CML2_CURRENCY[$currency]) && preg_match("/^[a-zA-Z0-9]+$/", $CML2_CURRENCY[$currency]) ) { $currency = $CML2_CURRENCY[$currency]; } else { $currency="RUB"; $this->LAST_ERROR = GetMessage("IBLOCK_XML2_CURRENCY_ERROR"); } } if(!isset($this->arCurrencyCache[$currency])) { if($this->bCatalog && $this->currencyIncluded) { CCurrency::Add(array( "CURRENCY" => $currency, )); } $this->arCurrencyCache[$currency] = true; } return $currency; } function CheckIBlockType($ID) { $obType = new CIBlockType; $rsType = $obType->GetByID($ID); if($arType = $rsType->Fetch()) { return $arType["ID"]; } else { $rsType = $obType->GetByID("1c_catalog"); if($arType = $rsType->Fetch()) { return $arType["ID"]; } else { $result = $obType->Add(array( "ID" => "1c_catalog", "SECTIONS" => "Y", "LANG" => array( "ru" => array( "NAME" => GetMessage("IBLOCK_XML2_CATALOG_NAME"), "SECTION_NAME" => GetMessage("IBLOCK_XML2_CATALOG_SECTION_NAME"), "ELEMENT_NAME" => GetMessage("IBLOCK_XML2_CATALOG_ELEMENT_NAME"), ), ), )); if($result) return $result; else return false; } } } function CheckSites($arSite) { $arResult = array(); if(!is_array($arSite)) $arSite = array($arSite); foreach($arSite as $site_id) { if($site_id <> '') { $rsSite = CSite::GetByID($site_id); if($rsSite->Fetch()) $arResult[] = $site_id; } } if(!defined("ADMIN_SECTION")) { $rsSite = CSite::GetByID(SITE_ID); if($rsSite->Fetch()) $arResult[] = SITE_ID; } if(count($arResult)<1) $arResult[] = CSite::GetDefSite(); return $arResult; } 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 = Main\Localization\Loc::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' => Iblock\PropertyTable::TYPE_FILE, 'CODE' => 'FILES', ]; $arProperties['CML2_MANUFACTURER'] = [ 'NAME' => GetMessage('IBLOCK_XML2_PROP_MANUFACTURER'), 'MULTIPLE' => 'N', 'WITH_DESCRIPTION' => 'N', 'MULTIPLE_CNT' => 1, 'PROPERTY_TYPE' => Iblock\PropertyTable::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; } function ImportSections() { if($this->next_step["XML_SECTIONS_PARENT"]) { $rs = $this->_xml_file->GetList( array("ID" => "asc"), array("PARENT_ID" => $this->next_step["XML_SECTIONS_PARENT"]), array("ID", "NAME", "VALUE") ); $arID = array(); while($ar = $rs->Fetch()) $arID[] = $ar["ID"]; if($this->skip_root_section && (count($arID) == 1)) { $rs = $this->_xml_file->GetList( array("ID" => "asc"), array("PARENT_ID" => $arID[0]), array("ID", "NAME", "VALUE") ); $XML_SECTIONS_PARENT = false; while($ar = $rs->Fetch()) if($ar["NAME"] == $this->mess["IBLOCK_XML2_GROUPS"]) $XML_SECTIONS_PARENT = $ar["ID"]; $arID = array(); if($XML_SECTIONS_PARENT > 0) { $rs = $this->_xml_file->GetList( array("ID" => "asc"), array("PARENT_ID" => $XML_SECTIONS_PARENT), array("ID", "NAME", "VALUE") ); while($ar = $rs->Fetch()) $arID[] = $ar["ID"]; } } foreach($arID as $id) { $result = $this->ImportSection($id, $this->next_step["IBLOCK_ID"], false); if($result !== true) return $result; } } return true; } function DeactivateSections($action) { if(array_key_exists("bUpdateOnly", $this->next_step) && $this->next_step["bUpdateOnly"]) return; if(!$this->next_step["XML_SECTIONS_PARENT"]) return; if($action!="D" && $action!="A") return; $bDelete = $action=="D"; //This will protect us from deactivating when next_step is lost $IBLOCK_ID = intval($this->next_step["IBLOCK_ID"]); if($IBLOCK_ID < 1) return; $arFilter = array( "IBLOCK_ID" => $IBLOCK_ID, ); if(!$bDelete) $arFilter["ACTIVE"] = "Y"; $obSection = new CIBlockSection; $rsSection = $obSection->GetList(array("ID"=>"asc"), $arFilter, false, ['ID', 'IBLOCK_ID']); while($arSection = $rsSection->Fetch()) { $rs = $this->_xml_file->GetList( array(), array("PARENT_ID+0" => 0, "LEFT_MARGIN" => $arSection["ID"]), array("ID") ); $ar = $rs->Fetch(); if(!$ar) { if($bDelete) { $obSection->Delete($arSection["ID"]); } else { $obSection->Update($arSection["ID"], array("ACTIVE"=>"N")); } } else { $this->_xml_file->Delete($ar["ID"]); } } return; } function SectionsResort() { CIBlockSection::ReSort($this->next_step["IBLOCK_ID"]); } function ImportPrices($XML_PRICES_PARENT, $IBLOCK_ID, $IBLOCK_LID) { $price_sort = 0; $this->next_step["XML_PRICES_PARENT"] = $XML_PRICES_PARENT; $arLang = array(); foreach($IBLOCK_LID as $site_id) { $rsSite = CSite::GetList("sort", "asc", array("ID" => $site_id)); while ($site = $rsSite->Fetch()) $arLang[$site["LANGUAGE_ID"]] = $site["LANGUAGE_ID"]; } $arPrices = CCatalogGroup::GetListArray(); if (!Catalog\Config\Feature::isMultiPriceTypesEnabled()) { $prices_limit = 1 - count($arPrices); } else { $prices_limit = null; } $arXMLPrices = $this->_xml_file->GetAllChildrenArray($XML_PRICES_PARENT); $uniqPriceById = array(); foreach($arXMLPrices as $arXMLPrice) { $PRICE_ID = $arXMLPrice[$this->mess["IBLOCK_XML2_ID"]]; $PRICE_NAME = $arXMLPrice[$this->mess["IBLOCK_XML2_NAME"]]; if (array_key_exists($PRICE_ID, $uniqPriceById)) return GetMessage("IBLOCK_XML2_PRICE_DUP_ERROR"); else $uniqPriceById[$PRICE_ID] = true; $found_id = 0; //Check for price by XML_ID if (isset($PRICE_ID) && $PRICE_ID != "") { foreach($arPrices as $i => $arPrice) { if ($PRICE_ID === $arPrice["XML_ID"]) { $found_id = $arPrice["ID"]; $arPrices[$i]["found"] = true; break; } } } //When lookup by it's name if (!$found_id) { foreach($arPrices as $arPrice) { if ($PRICE_NAME === $arPrice["NAME"] && !isset($arPrice["found"])) { $found_id = $arPrice["ID"]; break; } } } //Add new price type if(!$found_id) { $price_sort += 100; $arPrice = array( "NAME" => $PRICE_NAME, "XML_ID" => $PRICE_ID, "SORT" => $price_sort, "USER_LANG" => array(), "USER_GROUP" => array(2), "USER_GROUP_BUY" => array(2), ); foreach($arLang as $lang) { $arPrice["USER_LANG"][$lang] = $arXMLPrice[$this->mess["IBLOCK_XML2_NAME"]]; } if(!isset($prices_limit) || $prices_limit > 0) { CCatalogGroup::Add($arPrice); } elseif (isset($prices_limit)) { if ($this->bitrix24mode) { return GetMessage("IBLOCK_XML2_PRICE_SB_ADD_ERROR_B24"); } else { return GetMessage("IBLOCK_XML2_PRICE_SB_ADD_ERROR"); } } } //We can update XML_ID of the price elseif ($arPrices[$found_id]["XML_ID"] == '' && $PRICE_ID <> '') { CCatalogGroup::Update($found_id, array( "XML_ID" => $PRICE_ID, )); } //We should update NAME of the price elseif ($arPrices[$found_id]["NAME"] !== $PRICE_NAME && !$this->disable_change_price_name) { CCatalogGroup::Update($found_id, array( "NAME" => $PRICE_NAME, )); } if (isset($prices_limit)) $prices_limit--; } return true; } function ImportBaseUnits($XML_BASE_UNITS_PARENT) { $arXMLBaseUnits = $this->_xml_file->GetAllChildrenArray($XML_BASE_UNITS_PARENT); foreach ($arXMLBaseUnits as $arXMLBaseUnit) { $arUnit = array( "CODE" => $arXMLBaseUnit[$this->mess["IBLOCK_XML2_CODE"]], "MEASURE_TITLE" => $arXMLBaseUnit[$this->mess["IBLOCK_XML2_FULL_NAME"]], "SYMBOL_RUS" => $arXMLBaseUnit[$this->mess["IBLOCK_XML2_SHORT_NAME"]], //"SYMBOL_INTL" => $arXMLBaseUnit[$this->mess["IBLOCK_XML2_SHORT_NAME"]], "SYMBOL_LETTER_INTL" => $arXMLBaseUnit[$this->mess["IBLOCK_XML2_INTL_SHORT_NAME"]], ); $rsBaseUnit = CCatalogMeasure::GetList(array(), array("CODE" => $arUnit["CODE"])); $arIDUnit = $rsBaseUnit->Fetch(); if (!$arIDUnit) { $ID = CCatalogMeasure::Add($arUnit); if (!$ID) { return GetMessage("IBLOCK_XML2_BASE_UNIT_ADD_ERROR", array("#CODE#" => $arUnit["CODE"])); } } } return true; } function ImportStores($XML_STORES_PARENT) { $error = ''; $ID = 0; $arDBStores = $this->getStoreList(); $arXMLStores = $this->_xml_file->GetAllChildrenArray($XML_STORES_PARENT); foreach($arXMLStores as $arXMLStore) { $arStore = array( "TITLE" => $arXMLStore[$this->mess["IBLOCK_XML2_NAME"]], "XML_ID" => $arXMLStore[$this->mess["IBLOCK_XML2_ID"]], ); if(isset($arXMLStore[$this->mess["IBLOCK_XML2_STORE_ADDRESS"]])) $arStore["ADDRESS"] = $arXMLStore[$this->mess["IBLOCK_XML2_STORE_ADDRESS"]][$this->mess["IBLOCK_XML2_VIEW"]]; if(isset($arXMLStore[$this->mess["IBLOCK_XML2_STORE_DESCRIPTION"]])) $arStore["DESCRIPTION"] = $arXMLStore[$this->mess["IBLOCK_XML2_STORE_DESCRIPTION"]]; if( isset($arXMLStore[$this->mess["IBLOCK_XML2_STORE_CONTACTS"]]) && is_array($arXMLStore[$this->mess["IBLOCK_XML2_STORE_CONTACTS"]]) ) { $storeContact = array(); foreach($arXMLStore[$this->mess["IBLOCK_XML2_STORE_CONTACTS"]] as $arContact) { if ( is_array($arContact) && ( !isset($arContact[$this->mess["IBLOCK_XML2_TYPE"]]) || mb_substr($arContact[$this->mess["IBLOCK_XML2_TYPE"]], 0, mb_strlen($this->mess["IBLOCK_XML2_STORE_PHONE"])) === $this->mess["IBLOCK_XML2_STORE_PHONE"] ) ) { $storeContact[] = $arContact[$this->mess["IBLOCK_XML2_VALUE"]]; } } if($storeContact) $arStore["PHONE"] = implode(", ", $storeContact); } if (!isset($arDBStores[$arStore["XML_ID"]])) { if ((count($arDBStores) < 1) || Catalog\Config\Feature::isMultiStoresEnabled()) $arDBStores[$arStore["XML_ID"]] = $ID = CCatalogStore::Add($arStore); else $error = GetMessage("IBLOCK_XML2_MULTI_STORE_IMPORT_ERROR"); } else { if ((count($arDBStores) <= 1) || Catalog\Config\Feature::isMultiStoresEnabled()) $ID = CCatalogStore::Update($arDBStores[$arStore["XML_ID"]], $arStore); else $error = GetMessage("IBLOCK_XML2_MULTI_STORE_IMPORT_ERROR"); } } if($error) return $error; if(!$ID) return false; return true; } function ImportStoresAmount($arElement, $elementID, &$counter) { $arFields = array(); $arFields['PRODUCT_ID'] = $elementID; static $arStoreResult = false; if ($arStoreResult === false) { $arStoreResult = $this->getStoreList(); } foreach($arElement as $xmlID => $amount) { if (isset($arStoreResult[$xmlID])) { $arFields['STORE_ID'] = $arStoreResult[$xmlID]; $arFields['AMOUNT'] = $amount; $res = CCatalogStoreProduct::UpdateFromForm($arFields); if(!$res) $counter["ERR"]++; } } return true; } function ImportSectionsProperties($XML_PARENT, $IBLOCK_ID) { /** @var CMain $APPLICATION */ global $APPLICATION; $obTypeManager = new CUserTypeEntity; $sort = 100; $rs = $this->_xml_file->GetList( array("ID" => "asc"), array("PARENT_ID" => $XML_PARENT), array("ID") ); while($ar = $rs->Fetch()) { $XML_ENUM_PARENT = array(); $arField = array( ); $rsP = $this->_xml_file->GetList( array("ID" => "asc"), array("PARENT_ID" => $ar["ID"]) ); while($arP = $rsP->Fetch()) { if(isset($arP["VALUE_CLOB"])) $arP["VALUE"] = $arP["VALUE_CLOB"]; if($arP["NAME"] == $this->mess["IBLOCK_XML2_ID"]) $arField["XML_ID"] = $arP["VALUE"]; elseif($arP["NAME"] == $this->mess["IBLOCK_XML2_NAME"]) $arField["FIELD_NAME"] = $arP["VALUE"]; elseif($arP["NAME"] == $this->mess["IBLOCK_XML2_SORT"]) $arField["SORT"] = $arP["VALUE"]; elseif($arP["NAME"] == $this->mess["IBLOCK_XML2_MULTIPLE"]) $arField["MULTIPLE"] = ($arP["VALUE"]=="true") || intval($arP["VALUE"])? "Y": "N"; elseif($arP["NAME"] == $this->mess["IBLOCK_XML2_BX_PROPERTY_TYPE"]) $arField["USER_TYPE_ID"] = $arP["VALUE"]; elseif($arP["NAME"] == $this->mess["IBLOCK_XML2_BX_IS_REQUIRED"]) $arField["MANDATORY"] = ($arP["VALUE"]=="true") || intval($arP["VALUE"])? "Y": "N"; elseif($arP["NAME"] == $this->mess["IBLOCK_XML2_BX_FILTER"]) $arField["SHOW_FILTER"] = ($arP["VALUE"]=="true") || intval($arP["VALUE"])? "Y": "N"; elseif($arP["NAME"] == $this->mess["IBLOCK_XML2_BX_SHOW_IN_LIST"]) $arField["SHOW_IN_LIST"] = ($arP["VALUE"]=="true") || intval($arP["VALUE"])? "Y": "N"; elseif($arP["NAME"] == $this->mess["IBLOCK_XML2_BX_EDIT_IN_LIST"]) $arField["EDIT_IN_LIST"] = ($arP["VALUE"]=="true") || intval($arP["VALUE"])? "Y": "N"; elseif($arP["NAME"] == $this->mess["IBLOCK_XML2_BX_SEARCH"]) $arField["IS_SEARCHABLE"] = ($arP["VALUE"]=="true") || intval($arP["VALUE"])? "Y": "N"; elseif($arP["NAME"] == $this->mess["IBLOCK_XML2_BX_SETTINGS"]) $arField["SETTINGS"] = unserialize($arP["VALUE"], ['allowed_classes' => false]); elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_CHOICE_VALUES"]) $XML_ENUM_PARENT = $arP["ID"]; } $rsUserFields = $obTypeManager->GetList(array(), array("ENTITY_ID"=> "IBLOCK_".$IBLOCK_ID."_SECTION", "XML_ID"=>$arField["XML_ID"])); $arDBField = $rsUserFields->Fetch(); if(!$arDBField) { $rsUserFields = $obTypeManager->GetList(array(), array("ENTITY_ID"=> "IBLOCK_".$IBLOCK_ID."_SECTION", "FIELD_NAME"=>$arField["FIELD_NAME"])); $arDBField = $rsUserFields->Fetch(); } if($arDBField) { $bChanged = false; foreach($arField as $key=>$value) { if($arDBField[$key] !== $value) { $bChanged = true; break; } } if(!$bChanged) $arField["ID"] = $arDBField["ID"]; elseif($obTypeManager->Update($arDBField["ID"], $arField)) $arField["ID"] = $arDBField["ID"]; else { if($e = $APPLICATION->GetException()) return GetMessage("IBLOCK_XML2_UF_ERROR", array( "#XML_ID#" => $arField["XML_ID"], "#ERROR_TEXT#" => $e->GetString(), )); else return false; } } else { $arField["ENTITY_ID"] = "IBLOCK_".$IBLOCK_ID."_SECTION"; if(!array_key_exists("SORT", $arField)) $arField["SORT"] = $sort; $arField["ID"] = $obTypeManager->Add($arField); if(!$arField["ID"]) { if($e = $APPLICATION->GetException()) return GetMessage("IBLOCK_XML2_UF_ERROR", array( "#XML_ID#" => $arField["XML_ID"], "#ERROR_TEXT#" => $e->GetString(), )); else return false; } } if ($XML_ENUM_PARENT) { $arEnumXmlNodes = array(); $rsE = $this->_xml_file->GetList( array("ID" => "asc"), array("PARENT_ID" => $XML_ENUM_PARENT) ); while($arE = $rsE->Fetch()) { if(isset($arE["VALUE_CLOB"])) $arE["VALUE"] = $arE["VALUE_CLOB"]; $arEnumXmlNodes[] = $arE; } if (!empty($arEnumXmlNodes)) { $this->ImportSectionPropertyEnum($arField["ID"], $arEnumXmlNodes); } } $sort += 100; } return true; } function ImportProperties($XML_PROPERTIES_PARENT, $IBLOCK_ID) { $obProperty = new CIBlockProperty; $sort = 100; $arElementFields = array( "CML2_ACTIVE" => $this->mess["IBLOCK_XML2_BX_ACTIVE"], "CML2_CODE" => $this->mess["IBLOCK_XML2_SYMBOL_CODE"], "CML2_SORT" => $this->mess["IBLOCK_XML2_SORT"], "CML2_ACTIVE_FROM" => $this->mess["IBLOCK_XML2_START_TIME"], "CML2_ACTIVE_TO" => $this->mess["IBLOCK_XML2_END_TIME"], "CML2_PREVIEW_TEXT" => $this->mess["IBLOCK_XML2_ANONS"], "CML2_DETAIL_TEXT" => $this->mess["IBLOCK_XML2_DETAIL"], "CML2_PREVIEW_PICTURE" => $this->mess["IBLOCK_XML2_PREVIEW_PICTURE"], ); $rs = $this->_xml_file->GetList( array("ID" => "asc"), array("PARENT_ID" => $XML_PROPERTIES_PARENT), array("ID") ); while($ar = $rs->Fetch()) { $XML_ENUM_PARENT = false; $isExternal = false; $arProperty = array( ); $rsP = $this->_xml_file->GetList( array("ID" => "asc"), array("PARENT_ID" => $ar["ID"]) ); while($arP = $rsP->Fetch()) { if(isset($arP["VALUE_CLOB"])) $arP["VALUE"] = $arP["VALUE_CLOB"]; if($arP["NAME"]==$this->mess["IBLOCK_XML2_ID"]) { $arProperty["XML_ID"] = $arP["VALUE"]; if(array_key_exists($arProperty["XML_ID"], $arElementFields)) break; } elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_NAME"]) $arProperty["NAME"] = $arP["VALUE"]; elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_MULTIPLE"]) $arProperty["MULTIPLE"] = ($arP["VALUE"]=="true") || intval($arP["VALUE"])? "Y": "N"; elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_BX_SORT"]) $arProperty["SORT"] = $arP["VALUE"]; elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_BX_CODE"]) $arProperty["CODE"] = $arP["VALUE"]; elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_BX_DEFAULT_VALUE"]) $arProperty["DEFAULT_VALUE"] = $arP["VALUE"]; elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_SERIALIZED"]) $arProperty["SERIALIZED"] = ($arP["VALUE"]=="true") || intval($arP["VALUE"])? "Y": "N"; elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_BX_PROPERTY_TYPE"]) { $arProperty["PROPERTY_TYPE"] = $arP["VALUE"]; $arProperty["USER_TYPE"] = ""; } elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_BX_ROWS"]) $arProperty["ROW_COUNT"] = $arP["VALUE"]; elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_BX_COLUMNS"]) $arProperty["COL_COUNT"] = $arP["VALUE"]; elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_BX_LIST_TYPE"]) $arProperty["LIST_TYPE"] = $arP["VALUE"]; elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_BX_FILE_EXT"]) $arProperty["FILE_TYPE"] = $arP["VALUE"]; elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_BX_FIELDS_COUNT"]) $arProperty["MULTIPLE_CNT"] = $arP["VALUE"]; elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_BX_USER_TYPE"]) $arProperty["USER_TYPE"] = $arP["VALUE"]; elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_BX_WITH_DESCRIPTION"]) $arProperty["WITH_DESCRIPTION"] = ($arP["VALUE"]=="true") || intval($arP["VALUE"])? "Y": "N"; elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_BX_SEARCH"]) $arProperty["SEARCHABLE"] = ($arP["VALUE"]=="true") || intval($arP["VALUE"])? "Y": "N"; elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_BX_FILTER"]) $arProperty["FILTRABLE"] = ($arP["VALUE"]=="true") || intval($arP["VALUE"])? "Y": "N"; elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_BX_LINKED_IBLOCK"]) $arProperty["LINK_IBLOCK_ID"] = $this->GetIBlockByXML_ID($arP["VALUE"]); elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_CHOICE_VALUES"]) $XML_ENUM_PARENT = $arP["ID"]; elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_BX_IS_REQUIRED"]) $arProperty["IS_REQUIRED"] = ($arP["VALUE"]=="true") || intval($arP["VALUE"])? "Y": "N"; elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_VALUES_TYPE"]) { if( $arP["VALUE"] == $this->mess["IBLOCK_XML2_TYPE_LIST"] && !$isExternal ) { $arProperty["PROPERTY_TYPE"] = "L"; $arProperty["USER_TYPE"] = ""; } elseif($arP["VALUE"] == $this->mess["IBLOCK_XML2_TYPE_NUMBER"]) { $arProperty["PROPERTY_TYPE"] = "N"; $arProperty["USER_TYPE"] = ""; } elseif($arP["VALUE"] == $this->mess["IBLOCK_XML2_TYPE_STRING"]) { $arProperty["PROPERTY_TYPE"] = "S"; $arProperty["USER_TYPE"] = ""; } elseif($arP["VALUE"] == $this->mess["IBLOCK_XML2_USER_TYPE_DATE"]) { $arProperty["PROPERTY_TYPE"] = "S"; $arProperty["USER_TYPE"] = "Date"; } elseif($arP["VALUE"] == $this->mess["IBLOCK_XML2_USER_TYPE_DATETIME"]) { $arProperty["PROPERTY_TYPE"] = "S"; $arProperty["USER_TYPE"] = "DateTime"; } } elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_VALUES_TYPES"]) { //This property metadata contains information about it's type $rsTypes = $this->_xml_file->GetList( array("ID" => "asc"), array("PARENT_ID" => $arP["ID"]), array("ID", "LEFT_MARGIN", "RIGHT_MARGIN", "NAME") ); $arType = $rsTypes->Fetch(); //We'll process only properties with NOT composing types //composed types will be supported only as simple string properties if($arType && !$rsTypes->Fetch()) { $rsType = $this->_xml_file->GetList( array("ID" => "asc"), array("PARENT_ID" => $arType["ID"]), array("ID", "LEFT_MARGIN", "RIGHT_MARGIN", "NAME", "VALUE") ); while($arType = $rsType->Fetch()) { if($arType["NAME"] == $this->mess["IBLOCK_XML2_TYPE"]) { if($arType["VALUE"] == $this->mess["IBLOCK_XML2_TYPE_LIST"]) $arProperty["PROPERTY_TYPE"] = "L"; elseif($arType["VALUE"] == $this->mess["IBLOCK_XML2_TYPE_NUMBER"]) $arProperty["PROPERTY_TYPE"] = "N"; } elseif($arType["NAME"] == $this->mess["IBLOCK_XML2_CHOICE_VALUES"]) { $XML_ENUM_PARENT = $arType["ID"]; } } } } elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_BX_USER_TYPE_SETTINGS"]) { $arProperty["USER_TYPE_SETTINGS"] = unserialize($arP["VALUE"], ['allowed_classes' => false]); } elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_EXTERNAL"]) { $isExternal = ($arP["VALUE"]=="true") || intval($arP["VALUE"])? true: false; if ($isExternal) { $arProperty["PROPERTY_TYPE"] = "S"; $arProperty["USER_TYPE"] = "directory"; } } elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_BX_PROPERTY_FEATURE_LIST"]) { $arProperty["FEATURES"] = unserialize($arP["VALUE"], ['allowed_classes' => false]); } } if(array_key_exists($arProperty["XML_ID"], $arElementFields)) continue; // Skip properties with no choice values // http://jabber.bx/view.php?id=30476 $arEnumXmlNodes = array(); if($XML_ENUM_PARENT) { $rsE = $this->_xml_file->GetList( array("ID" => "asc"), array("PARENT_ID" => $XML_ENUM_PARENT) ); while($arE = $rsE->Fetch()) { if(isset($arE["VALUE_CLOB"])) $arE["VALUE"] = $arE["VALUE_CLOB"]; $arEnumXmlNodes[] = $arE; } if (empty($arEnumXmlNodes)) continue; } if (isset($arProperty['SERIALIZED'])) { if ($arProperty['SERIALIZED'] === 'Y') { $arProperty['DEFAULT_VALUE'] = unserialize($arProperty['DEFAULT_VALUE'], ['allowed_classes' => false]); } unset($arProperty['SERIALIZED']); } $rsProperty = $obProperty->GetList(array(), array("IBLOCK_ID"=>$IBLOCK_ID, "XML_ID"=>$arProperty["XML_ID"])); if($arDBProperty = $rsProperty->Fetch()) { $bChanged = false; foreach($arProperty as $key=>$value) { if($arDBProperty[$key] !== $value) { $bChanged = true; break; } } if(!$bChanged) $arProperty["ID"] = $arDBProperty["ID"]; elseif($obProperty->Update($arDBProperty["ID"], $arProperty)) $arProperty["ID"] = $arDBProperty["ID"]; else return $obProperty->LAST_ERROR; } else { $arProperty["IBLOCK_ID"] = $IBLOCK_ID; $arProperty["ACTIVE"] = "Y"; if(!array_key_exists("PROPERTY_TYPE", $arProperty)) $arProperty["PROPERTY_TYPE"] = "S"; if(!array_key_exists("SORT", $arProperty)) $arProperty["SORT"] = $sort; if(!array_key_exists("CODE", $arProperty)) { $arProperty["CODE"] = $this->safeTranslit($arProperty["NAME"]); if(preg_match('/^[0-9]/', $arProperty["CODE"])) $arProperty["CODE"] = '_'.$arProperty["CODE"]; $rsProperty = $obProperty->GetList(array(), array("IBLOCK_ID"=>$IBLOCK_ID, "CODE"=>$arProperty["CODE"])); if($arDBProperty = $rsProperty->Fetch()) { $suffix = 0; do { $suffix++; $rsProperty = $obProperty->GetList(array(), array("IBLOCK_ID"=>$IBLOCK_ID, "CODE"=>$arProperty["CODE"]."_".$suffix)); } while ($rsProperty->Fetch()); $arProperty["CODE"] .= '_'.$suffix; } } $arProperty["ID"] = $obProperty->Add($arProperty); if(!$arProperty["ID"]) return $obProperty->LAST_ERROR; } if($XML_ENUM_PARENT) { if ($isExternal) $result = $this->ImportPropertyDirectory($arProperty, $arEnumXmlNodes); else $result = $this->ImportPropertyEnum($arProperty, $arEnumXmlNodes); if ($result !== true) return $result; } $sort += 100; } return true; } function ImportPropertyEnum($arProperty, $arEnumXmlNodes) { $arEnumMap = array(); $arProperty["VALUES"] = array(); $rsEnum = CIBlockProperty::GetPropertyEnum($arProperty["ID"]); while($arEnum = $rsEnum->Fetch()) { $arProperty["VALUES"][$arEnum["ID"]] = $arEnum; $arEnumMap[$arEnum["XML_ID"]] = &$arProperty["VALUES"][$arEnum["ID"]]; } $i = 0; foreach($arEnumXmlNodes as $arE) { if( $arE["NAME"] == $this->mess["IBLOCK_XML2_CHOICE"] || $arE["NAME"] == $this->mess["IBLOCK_XML2_CHOICE_VALUE"] ) { $arE = $this->_xml_file->GetAllChildrenArray($arE); if(isset($arE[$this->mess["IBLOCK_XML2_ID"]])) { $xml_id = $arE[$this->mess["IBLOCK_XML2_ID"]]; if(!array_key_exists($xml_id, $arEnumMap)) { $arProperty["VALUES"]["n".$i] = array(); $arEnumMap[$xml_id] = &$arProperty["VALUES"]["n".$i]; $i++; } $arEnumMap[$xml_id]["CML2_EXPORT_FLAG"] = true; $arEnumMap[$xml_id]["XML_ID"] = $xml_id; if(isset($arE[$this->mess["IBLOCK_XML2_VALUE"]])) $arEnumMap[$xml_id]["VALUE"] = $arE[$this->mess["IBLOCK_XML2_VALUE"]]; if(isset($arE[$this->mess["IBLOCK_XML2_BY_DEFAULT"]])) $arEnumMap[$xml_id]["DEF"] = ($arE[$this->mess["IBLOCK_XML2_BY_DEFAULT"]]=="true") || intval($arE[$this->mess["IBLOCK_XML2_BY_DEFAULT"]])? "Y": "N"; if(isset($arE[$this->mess["IBLOCK_XML2_SORT"]])) $arEnumMap[$xml_id]["SORT"] = intval($arE[$this->mess["IBLOCK_XML2_SORT"]]); } } elseif( $arE["NAME"] == $this->mess["IBLOCK_XML2_TYPE_LIST"] ) { $arE = $this->_xml_file->GetAllChildrenArray($arE); if(isset($arE[$this->mess["IBLOCK_XML2_VALUE_ID"]])) { $xml_id = $arE[$this->mess["IBLOCK_XML2_VALUE_ID"]]; if(!array_key_exists($xml_id, $arEnumMap)) { $arProperty["VALUES"]["n".$i] = array(); $arEnumMap[$xml_id] = &$arProperty["VALUES"]["n".$i]; $i++; } $arEnumMap[$xml_id]["CML2_EXPORT_FLAG"] = true; $arEnumMap[$xml_id]["XML_ID"] = $xml_id; if(isset($arE[$this->mess["IBLOCK_XML2_VALUE"]])) $arEnumMap[$xml_id]["VALUE"] = $arE[$this->mess["IBLOCK_XML2_VALUE"]]; } } } $bUpdateOnly = array_key_exists("bUpdateOnly", $this->next_step) && $this->next_step["bUpdateOnly"]; $sort = 100; foreach($arProperty["VALUES"] as $id=>$arEnum) { if(!isset($arEnum["CML2_EXPORT_FLAG"])) { //Delete value only when full exchange happened if(!$bUpdateOnly) $arProperty["VALUES"][$id]["VALUE"] = ""; } elseif(isset($arEnum["SORT"])) { if($arEnum["SORT"] > $sort) $sort = $arEnum["SORT"] + 100; } else { $arProperty["VALUES"][$id]["SORT"] = $sort; $sort += 100; } } $obProperty = new CIBlockProperty; $obProperty->UpdateEnum($arProperty["ID"], $arProperty["VALUES"], false); return true; } /** * @param array $arProperty * @param array $arEnumXmlNodes * @return true|string * @throws Main\ArgumentException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ function ImportPropertyDirectory($arProperty, $arEnumXmlNodes) { if (!Loader::includeModule('highloadblock')) return true; $rsProperty = CIBlockProperty::GetList(array(), array("ID"=>$arProperty["ID"])); $arProperty = $rsProperty->Fetch(); if (!$arProperty) return true; $tableName = 'b_'.strtolower($arProperty["CODE"]); if ($arProperty["USER_TYPE_SETTINGS"]["TABLE_NAME"] == '') { $hlblock = Bitrix\Highloadblock\HighloadBlockTable::getList(array( "filter" => array( "=TABLE_NAME" => $tableName, )))->fetch(); if (!$hlblock) { $highBlockName = trim($arProperty["CODE"]); $highBlockName = preg_replace("/([^A-Za-z0-9]+)/", "", $highBlockName); if ($highBlockName == "") return GetMessage("IBLOCK_XML2_HBLOCK_NAME_IS_INVALID"); $highBlockName = strtoupper(substr($highBlockName, 0, 1)).substr($highBlockName, 1); $data = array( 'NAME' => $highBlockName, 'TABLE_NAME' => $tableName, ); $result = Bitrix\Highloadblock\HighloadBlockTable::add($data); $highBlockID = $result->getId(); $arFieldsName = array( 'UF_NAME' => array("Y", "string"), 'UF_XML_ID' => array("Y", "string"), 'UF_LINK' => array("N", "string"), 'UF_DESCRIPTION' => array("N", "string"), 'UF_FULL_DESCRIPTION' => array("N", "string"), 'UF_SORT' => array("N", "integer"), 'UF_FILE' => array("N", "file"), 'UF_DEF' => array("N", "boolean"), ); $obUserField = new CUserTypeEntity(); $sort = 100; foreach($arFieldsName as $fieldName => $fieldValue) { $arUserField = array( "ENTITY_ID" => "HLBLOCK_".$highBlockID, "FIELD_NAME" => $fieldName, "USER_TYPE_ID" => $fieldValue[1], "XML_ID" => "", "SORT" => $sort, "MULTIPLE" => "N", "MANDATORY" => $fieldValue[0], "SHOW_FILTER" => "N", "SHOW_IN_LIST" => "Y", "EDIT_IN_LIST" => "Y", "IS_SEARCHABLE" => "N", "SETTINGS" => array(), ); $obUserField->Add($arUserField); $sort += 100; } } $arProperty["USER_TYPE_SETTINGS"]["TABLE_NAME"] = $tableName; $obProperty = new CIBlockProperty; $obProperty->Update($arProperty["ID"], $arProperty); } $hlblock = Bitrix\Highloadblock\HighloadBlockTable::getList(array( "filter" => array( "=TABLE_NAME" => $arProperty["USER_TYPE_SETTINGS"]["TABLE_NAME"], )))->fetch(); if (empty($hlblock)) { return GetMessage( "IBLOCK_XML2_HBLOCK_ABSENT", array( "#ID#" => $arProperty["ID"], "#NAME#" => $arProperty["NAME"] ) ); } $entity = Bitrix\Highloadblock\HighloadBlockTable::compileEntity($hlblock); $entity_data_class = $entity->getDataClass(); $arEnumMap = array(); $rsData = $entity_data_class::getList(array( "select" => array("ID", "UF_NAME", "UF_XML_ID", "UF_SORT"), )); while($arData = $rsData->fetch()) { $arEnumMap[$arData["UF_XML_ID"]] = $arData; } $i = 0; foreach($arEnumXmlNodes as $arE) { if( $arE["NAME"] == $this->mess["IBLOCK_XML2_TYPE_LIST"] ) { $arE = $this->_xml_file->GetAllChildrenArray($arE); if( isset($arE[$this->mess["IBLOCK_XML2_VALUE_ID"]]) && isset($arE[$this->mess["IBLOCK_XML2_VALUE"]]) ) { $xml_id = $arE[$this->mess["IBLOCK_XML2_VALUE_ID"]]; $arFields = array( "UF_XML_ID" => $xml_id, "UF_NAME" => $arE[$this->mess["IBLOCK_XML2_VALUE"]], ); if (isset($arE[$this->mess["IBLOCK_XML2_PICTURE"]])) { $arFields["UF_FILE"] = $this->MakeFileArray($arE[$this->mess["IBLOCK_XML2_PICTURE"]]); } if(!array_key_exists($xml_id, $arEnumMap)) { $entity_data_class::add($arFields); } elseif ($arEnumMap[$xml_id]["UF_NAME"] !== $arFields['UF_NAME']) { $entity_data_class::update($arEnumMap[$xml_id]["ID"], $arFields); } } } } return true; } function ImportSectionPropertyEnum($FIELD_ID, $arEnumXmlNodes) { $arEnumMap = array(); $arEnumValues = array(); $obEnum = new CUserFieldEnum; $rsEnum = $obEnum->GetList(array(), array( "USER_FIELD_ID" => $FIELD_ID, )); while($arEnum = $rsEnum->Fetch()) { $arEnumValues[$arEnum["ID"]] = $arEnum; $arEnumMap[$arEnum["XML_ID"]] = &$arEnumValues[$arEnum["ID"]]; } $i = 0; foreach($arEnumXmlNodes as $arE) { if($arE["NAME"] == $this->mess["IBLOCK_XML2_CHOICE"]) { $arE = $this->_xml_file->GetAllChildrenArray($arE); if(isset($arE[$this->mess["IBLOCK_XML2_ID"]])) { $xml_id = $arE[$this->mess["IBLOCK_XML2_ID"]]; if(!array_key_exists($xml_id, $arEnumMap)) { $arEnumValues["n".$i] = array(); $arEnumMap[$xml_id] = &$arEnumValues["n".$i]; $i++; } $arEnumMap[$xml_id]["CML2_EXPORT_FLAG"] = true; $arEnumMap[$xml_id]["XML_ID"] = $xml_id; if(isset($arE[$this->mess["IBLOCK_XML2_VALUE"]])) $arEnumMap[$xml_id]["VALUE"] = $arE[$this->mess["IBLOCK_XML2_VALUE"]]; if(isset($arE[$this->mess["IBLOCK_XML2_BY_DEFAULT"]])) $arEnumMap[$xml_id]["DEF"] = ($arE[$this->mess["IBLOCK_XML2_BY_DEFAULT"]]=="true") || intval($arE[$this->mess["IBLOCK_XML2_BY_DEFAULT"]])? "Y": "N"; if(isset($arE[$this->mess["IBLOCK_XML2_SORT"]])) $arEnumMap[$xml_id]["SORT"] = intval($arE[$this->mess["IBLOCK_XML2_SORT"]]); } } } $bUpdateOnly = array_key_exists("bUpdateOnly", $this->next_step) && $this->next_step["bUpdateOnly"]; $sort = 100; foreach($arEnumValues as $id=>$arEnum) { if(!isset($arEnum["CML2_EXPORT_FLAG"])) { //Delete value only when full exchange happened if(!$bUpdateOnly) $arEnumValues[$id]["VALUE"] = ""; } elseif(isset($arEnum["SORT"])) { if($arEnum["SORT"] > $sort) $sort = $arEnum["SORT"] + 100; } else { $arEnumValues[$id]["SORT"] = $sort; $sort += 100; } } $obEnum = new CUserFieldEnum; $res = $obEnum->SetEnumValues($FIELD_ID, $arEnumValues); return true; } function ImportSectionProperties($XML_SECTION_PROPERTIES, $IBLOCK_ID, $SECTION_ID = 0) { if($SECTION_ID == 0) { CIBlockSectionPropertyLink::DeleteByIBlock($IBLOCK_ID); $ib = new CIBlock; $ib->Update($IBLOCK_ID, array("SECTION_PROPERTY" => "Y")); } $rs = $this->_xml_file->GetList( array("ID" => "asc"), array("PARENT_ID" => $XML_SECTION_PROPERTIES), array("ID") ); while($ar = $rs->Fetch()) { $iblockId = 0; $sectionId = 0; $arLink = array( ); $rsP = $this->_xml_file->GetList( array("ID" => "asc"), array("PARENT_ID" => $ar["ID"]) ); while($arP = $rsP->Fetch()) { if($arP["NAME"]==$this->mess["IBLOCK_XML2_ID"]) $arLink["XML_ID"] = $arP["VALUE"]; elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_SMART_FILTER"]) $arLink["SMART_FILTER"] = ($arP["VALUE"]=="true") || intval($arP["VALUE"])? "Y": "N"; elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_SMART_FILTER_DISPLAY_TYPE"]) $arLink["DISPLAY_TYPE"] = $arP["VALUE"]; elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_SMART_FILTER_DISPLAY_EXPANDED"]) $arLink["DISPLAY_EXPANDED"] = ($arP["VALUE"]=="true") || intval($arP["VALUE"])? "Y": "N"; elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_SMART_FILTER_HINT"]) $arLink["FILTER_HINT"] = $arP["VALUE"]; elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_BX_LINKED_IBLOCK"]) $iblockId = $this->GetIBlockByXML_ID($arP["VALUE"]); elseif($arP["NAME"]==$this->mess["IBLOCK_XML2_GROUP"] && $iblockId > 0) $sectionId = $this->GetSectionByXML_ID($iblockId, $arP["VALUE"]); } if ($iblockId > 0) $arLink["IBLOCK_ID"] = $iblockId; $rsProperty = CIBlockProperty::GetList(array(), array( "IBLOCK_ID" => $IBLOCK_ID, "XML_ID" => $arLink["XML_ID"], "CHECK_PERMISSIONS" => "N", )); if($arDBProperty = $rsProperty->Fetch()) { CIBlockSectionPropertyLink::Add($sectionId? $sectionId: $SECTION_ID, $arDBProperty["ID"], $arLink); } } return true; } function ReadCatalogData(&$SECTION_MAP, &$PRICES_MAP) { if(!is_array($SECTION_MAP)) { $SECTION_MAP = array(); $rsSections = CIBlockSection::GetList(array(), array("IBLOCK_ID"=>$this->next_step["IBLOCK_ID"]), false); while($ar = $rsSections->Fetch()) $SECTION_MAP[$ar["XML_ID"]] = $ar["ID"]; unset($rsSections); } $this->SECTION_MAP = $SECTION_MAP; if(!is_array($PRICES_MAP)) { $arPrices = array(); if($this->bCatalog) { $arPrices = CCatalogGroup::GetListArray(); } $PRICES_MAP = array(); if(isset($this->next_step["XML_PRICES_PARENT"])) { $rs = $this->_xml_file->GetList( array("ID" => "asc"), array("PARENT_ID" => $this->next_step["XML_PRICES_PARENT"]) ); while($arParent = $rs->Fetch()) { if(isset($arParent["VALUE_CLOB"])) $arParent["VALUE"] = $arParent["VALUE_CLOB"]; $arXMLPrice = $this->_xml_file->GetAllChildrenArray($arParent); $PRICE_ID = $arXMLPrice[$this->mess["IBLOCK_XML2_ID"]]; $PRICE_NAME = $arXMLPrice[$this->mess["IBLOCK_XML2_NAME"]]; $arPrice = array( "NAME" => $PRICE_NAME, "XML_ID" => $PRICE_ID, "CURRENCY" => $arXMLPrice[$this->mess["IBLOCK_XML2_CURRENCY"]] ?? '', "TAX_NAME" => $arXMLPrice[$this->mess["IBLOCK_XML2_TAX"]][$this->mess["IBLOCK_XML2_NAME"]] ?? '', "TAX_IN_SUM" => $arXMLPrice[$this->mess["IBLOCK_XML2_TAX"]][$this->mess["IBLOCK_XML2_IN_SUM"]] ?? '', ); if($this->bCatalog) { $found_id = 0; //Check for price by XML_ID if (isset($PRICE_ID) && $PRICE_ID != "") { foreach($arPrices as $price) { if ($PRICE_ID === $price["XML_ID"]) { $found_id = $price["ID"]; break; } } } //When lookup by it's name if (!$found_id) { foreach($arPrices as $price) { if ($PRICE_NAME === $price["NAME"]) { $found_id = $price["ID"]; break; } } } if($found_id) $arPrice["ID"] = $found_id; else $arPrice["ID"] = 0; } else { $obProperty = new CIBlockProperty; $rsProperty = $obProperty->GetList(array(), array("IBLOCK_ID"=>$this->next_step["IBLOCK_ID"], "XML_ID"=>$arPrice["XML_ID"])); if($ar = $rsProperty->Fetch()) $arPrice["ID"] = $ar["ID"]; else $arPrice["ID"] = 0; } $PRICES_MAP[$PRICE_ID] = $arPrice; } } else { foreach($arPrices as $arPrice) { $arPrice['TAX_NAME'] = ''; $arPrice['TAX_IN_SUM'] = ''; $PRICES_MAP[$arPrice["XML_ID"]] = $arPrice; } } } $this->PRICES_MAP = $PRICES_MAP; } function GetElementCRC($arElement) { if(!is_array($arElement)) { $parent_id = $arElement; $rsElement = $this->_xml_file->GetList( array("ID" => "asc"), array("PARENT_ID" => $parent_id) ); $arElement = array(); while($ar = $rsElement->Fetch()) $arElement[] = array( $ar["NAME"], $ar["VALUE"], $ar["VALUE_CLOB"], $ar["ATTRIBUTES"], ); } $c = crc32(print_r($arElement, true)); if($c > 0x7FFFFFFF) $c = -(0xFFFFFFFF - $c + 1); return $c; } function CheckManufacturer($xml) { if (!$xml) { return ""; } if (!isset($this->PROPERTY_MAP["CML2_MANUFACTURER"])) { return ''; } $propertyId = $this->PROPERTY_MAP["CML2_MANUFACTURER"]; $enumXmlId = $xml[$this->mess["IBLOCK_XML2_ID"]]; $enumName = $xml[$this->mess["IBLOCK_XML2_NAME"]]; if ($enumXmlId == '') { return ""; } $enumValue = CIBlockPropertyEnum::GetList(array(), array( "PROPERTY_ID" => $propertyId, "XML_ID" => $enumXmlId, )); $enum = $enumValue->Fetch(); if ($enum) { if ($enum["VALUE"] !== $enumName) { CIBlockPropertyEnum::Update($enum["ID"], array( "VALUE" => $enumName, )); } return $enum["ID"]; } else { return CIBlockPropertyEnum::Add(array( "VALUE" => $enumName, "PROPERTY_ID" => $propertyId, "DEF" => "N", "XML_ID" => $enumXmlId, )); } } /** * @return bool */ public function GetTotalCountElementsForImport() { $result = true; if (isset($this->next_step["XML_ELEMENTS_PARENT"]) && $this->next_step["XML_ELEMENTS_PARENT"] > 0) { if (!isset($this->next_step["DONE"])) $this->next_step["DONE"] = []; if (!isset($this->next_step["DONE"]["ALL"])) $this->next_step["DONE"]["ALL"] = 0; if ($this->next_step["DONE"]["ALL"] <= 0) { if ($this->_xml_file->IsExistTemporaryTable()) { $this->next_step["DONE"]["ALL"] = $this->_xml_file->GetCountItemsWithParent($this->next_step["XML_ELEMENTS_PARENT"]); } else { $this->LAST_ERROR = GetMessage("IBLOCK_XML2_TEMPORARY_TABLE_EXIST_ERROR"); $result = false; } } } return $result; } /** * @param int $start_time * @param int $interval * @return array */ public function ImportElements($start_time, $interval) { global $DB; $counter = array( "ADD" => 0, "UPD" => 0, "DEL" => 0, "DEA" => 0, "ERR" => 0, "CRC" => 0, ); if($this->next_step["XML_ELEMENTS_PARENT"]) { Iblock\PropertyIndex\Manager::enableDeferredIndexing(); if ($this->bCatalog) Catalog\Product\Sku::enableDeferredCalculation(); $this->activeStores = $this->getActiveStores(); $obElement = new CIBlockElement(); $obElement->CancelWFSetMove(); $bWF = Loader::includeModule("workflow"); $filter = [ 'PARENT_ID' => $this->next_step['XML_ELEMENTS_PARENT'], ]; if (isset($this->next_step['XML_LAST_ID'])) { $filter['>ID'] = $this->next_step['XML_LAST_ID']; } $rsParents = $this->_xml_file->GetList( array("ID" => "asc"), $filter, array("ID", "LEFT_MARGIN", "RIGHT_MARGIN") ); while($arParent = $rsParents->Fetch()) { if (!$arParent["RIGHT_MARGIN"]) continue; $counter["CRC"]++; $arXMLElement = $this->_xml_file->GetAllChildrenArray($arParent); $hashPosition = strrpos($arXMLElement[$this->mess["IBLOCK_XML2_ID"]], "#"); if(!$this->next_step["bOffer"] && $this->use_offers) { if($hashPosition !== false) { $this->next_step["XML_LAST_ID"] = $arParent["ID"]; continue; } } if(array_key_exists($this->mess["IBLOCK_XML2_STATUS"], $arXMLElement) && ($arXMLElement[$this->mess["IBLOCK_XML2_STATUS"]] == $this->mess["IBLOCK_XML2_DELETED"])) { $ID = $this->GetElementByXML_ID($this->next_step["IBLOCK_ID"], $arXMLElement[$this->mess["IBLOCK_XML2_ID"]]); if($ID && $obElement->Update($ID, array("ACTIVE"=>"N"), $bWF)) { if($this->use_offers) $this->ChangeOffersStatus($ID, "N", $bWF); $counter["DEA"]++; } else { $counter["ERR"]++; } } elseif(array_key_exists($this->mess["IBLOCK_XML2_BX_TAGS"], $arXMLElement)) { //This is our export file $ID = $this->ImportElement($arXMLElement, $counter, $bWF, $arParent); } else { $this->arFileDescriptionsMap = array(); $this->arElementFilesId = array(); $this->arElementFiles = array(); //offers.xml if ($this->next_step["bOffer"]) { if (!$this->use_offers) { //We have only one information block $ID = $this->ImportElementPrices($arXMLElement, $counter, $arParent); } elseif ($hashPosition === false && !$this->force_offers) { //We have separate offers iblock and there is element price $ID = $this->ImportElementPrices($arXMLElement, $counter, $arParent); } else { $xmlKeys = array_keys($arXMLElement); if ($xmlKeys == array($this->mess["IBLOCK_XML2_ID"], $this->mess["IBLOCK_XML2_PRICES"])) { //prices.xml $ID = $this->ImportElementPrices($arXMLElement, $counter, $arParent); } elseif ($xmlKeys == array($this->mess["IBLOCK_XML2_ID"], $this->mess["IBLOCK_XML2_RESTS"])) { //rests.xml $ID = $this->ImportElementPrices($arXMLElement, $counter, $arParent); } else { //It's an offer in offers iblock $ID = $this->ImportElement($arXMLElement, $counter, $bWF, $arParent); } } } //import.xml else { $ID = $this->ImportElement($arXMLElement, $counter, $bWF, $arParent); } } if($ID) { $ipropValues = new \Bitrix\Iblock\InheritedProperty\ElementValues($this->next_step["IBLOCK_ID"], $ID); $ipropValues->clearValues(); $DB->Query("UPDATE b_iblock_element SET TIMESTAMP_X = ".$DB->CurrentTimeFunction()." WHERE ID=".$ID); $this->_xml_file->Add(array("PARENT_ID" => 0, "LEFT_MARGIN" => $ID)); } $this->next_step["XML_LAST_ID"] = $arParent["ID"]; if($interval > 0 && (time()-$start_time) > (2*$interval/3)) break; } if ($this->bCatalog) { Catalog\Product\Sku::disableDeferredCalculation(); Catalog\Product\Sku::calculate(); } Iblock\PropertyIndex\Manager::disableDeferredIndexing(); Iblock\PropertyIndex\Manager::runDeferredIndexing($this->next_step["IBLOCK_ID"]); } $this->CleanTempFiles(); return $counter; } function ImportProductSets() { if ($this->bCatalog && isset($this->next_step["SETS"]) && $this->next_step["SETS"] > 0) { $rsParents = $this->_xml_file->GetList( array("ID" => "asc"), array("PARENT_ID" => $this->next_step["SETS"]), array("ID", "LEFT_MARGIN", "RIGHT_MARGIN") ); while($arParent = $rsParents->Fetch()) { $arXMLElement = $this->_xml_file->GetAllChildrenArray($arParent); if(isset($arXMLElement[$this->mess["IBLOCK_XML2_ID"]])) { $rsElement = CIBlockElement::GetList( array(), array("=XML_ID" => $arXMLElement[$this->mess["IBLOCK_XML2_ID"]], "IBLOCK_ID" => $this->next_step["IBLOCK_ID"]), false, false, array("ID", "IBLOCK_ID") ); if ($arDBElement = $rsElement->Fetch()) { CCatalogProductSet::deleteAllSetsByProduct($arDBElement["ID"], CCatalogProductSet::TYPE_GROUP); if (isset($arXMLElement[$this->mess["IBLOCK_XML2_PRODUCT_SET"]])) { $arFields = array( "ITEM_ID" => $arDBElement["ID"], "TYPE" => CCatalogProductSet::TYPE_GROUP, "ITEMS" => array(), ); foreach ($arXMLElement[$this->mess["IBLOCK_XML2_PRODUCT_SET"]] as $xmlSet) { $arFields["ITEMS"][] = array( "ITEM_ID" => $this->GetElementByXML_ID($arDBElement["IBLOCK_ID"], $xmlSet[$this->mess["IBLOCK_XML2_VALUE"]]), "SORT" => intval($xmlSet[$this->mess["IBLOCK_XML2_SORT"]]), "QUANTITY" => intval($xmlSet[$this->mess["IBLOCK_XML2_AMOUNT"]]), ); } $ps = new CCatalogProductSet; $ps->add($arFields); } } } } } } function ChangeOffersStatus($ELEMENT_ID, $STATUS = "Y", $bWF = true) { if($this->arLinkedProps === false) { $this->arLinkedProps = array(); $obProperty = new CIBlockProperty; $rsProperty = $obProperty->GetList(array(), array("LINK_IBLOCK_ID"=>$this->next_step["IBLOCK_ID"], "XML_ID"=>"CML2_LINK")); while($arProperty = $rsProperty->Fetch()) $this->arLinkedProps[] = $arProperty; } $obElement = new CIBlockElement; $obElement->CancelWFSetMove(); $elementFields = array("ACTIVE"=>$STATUS); if ((string)\Bitrix\Main\Config\Option::get('iblock', 'change_user_by_group_active_modify') === 'Y') { $elementFields['MODIFIED_BY'] = $this->currentUserId; } foreach($this->arLinkedProps as $arProperty) { $rsElements = $obElement->GetList( Array("ID"=>"asc"), Array( "PROPERTY_".$arProperty["ID"] => $ELEMENT_ID, "IBLOCK_ID" => $arProperty["IBLOCK_ID"], "ACTIVE" => $STATUS=="Y"? "N": "Y", ), false, false, Array("ID", "TMP_ID") ); while($arElement = $rsElements->Fetch()) $obElement->Update($arElement["ID"], $elementFields, $bWF); } } function safeTranslit($str) { $params = array( "max_len" => 50, "change_case" => 'U', // 'L' - toLower, 'U' - toUpper, false - do not change "replace_space" => '_', "replace_other" => '_', "delete_repeat_replace" => true, ); $result = CUtil::translit($str, LANGUAGE_ID, $params); $result = preg_replace("/[^a-zA-Z0-9_]/", $params["replace_other"], $result); if ($params["delete_repeat_replace"]) $result = preg_replace("/".preg_quote($params["replace_other"], "/")."+/", $params["replace_other"], $result); return $result; } /** * @param string $str * @return float */ public function ToFloat($str) { static $search = false; static $replace = false; if(!$search) { if (isset($this->next_step["sdp"]) && $this->next_step["sdp"] !== '') { $search = array("\xc2\xa0", "\xa0", " ", $this->next_step["sdp"], ","); $replace = array("", "", "", ".", "."); } else { $search = array("\xc2\xa0", "\xa0", " ", ","); $replace = array("", "", "", "."); } } return (float)str_replace($search, $replace, $str); } /** * @param string $value * @return float|string */ public function ToFloatEmpty($value) { return ($value === '' ? '' : $this->ToFloat($value)); } /** * @param string $str * @return int */ public function ToInt($str) { static $search = false; static $replace = false; if(!$search) { if (isset($this->next_step["sdp"]) && $this->next_step["sdp"] !== '') { $search = array("\xa0", " ", $this->next_step["sdp"], ","); $replace = array("", "", ".", "."); } else { $search = array("\xa0", " ", ","); $replace = array("", "", "."); } } return (int)str_replace($search, $replace, $str); } function Unserialize($string) { if(defined("BX_UTF")) { // 1 2 3 $decoded_string = preg_replace_callback('/(s:\d+:")(.*?)(";)/s', array($this, "__unserialize_callback"), $string); } else { $decoded_string = $string; } return unserialize($decoded_string, ['allowed_classes' => false]); } function __unserialize_callback($match) { return 's:'.strlen($match[2]).':"'.$match[2].'";'; } function convertBaseUnitFromXmlToPropertyValue($xmlValue) { static $cacheValue = array(); static $cacheDescr = array(); $xmlValue = (int)$xmlValue; if (!isset($cacheValue[$xmlValue])) { $cacheValue[$xmlValue] = $xmlValue; $cacheDescr[$xmlValue] = false; if ($xmlValue > 0 && Loader::includeModule('catalog')) { $rsBaseUnit = CCatalogMeasure::GetList(array(), array("CODE" => $xmlValue)); $arIDUnit = $rsBaseUnit->Fetch(); if ($arIDUnit) { $cacheValue[$xmlValue] = $arIDUnit["SYMBOL_RUS"]; $cacheDescr[$xmlValue] = $arIDUnit["ID"]; } else { $rsBaseUnit = CCatalogMeasure::GetList(array(), array("ID" => $xmlValue)); $arIDUnit = $rsBaseUnit->Fetch(); if ($arIDUnit) { $cacheValue[$xmlValue] = $arIDUnit["SYMBOL_RUS"]; $cacheDescr[$xmlValue] = $arIDUnit["ID"]; } } } } return array( "VALUE" => $cacheValue[$xmlValue], "DESCRIPTION" => $cacheDescr[$xmlValue], ); } function CheckIfElementIsActive($arXMLElement) { $bActive = true; //by default if(isset($arXMLElement[$this->mess["IBLOCK_XML2_PROPERTIES_VALUES"]])) { foreach($arXMLElement[$this->mess["IBLOCK_XML2_PROPERTIES_VALUES"]] as $value) { if($value[$this->mess["IBLOCK_XML2_ID"]] === "CML2_ACTIVE") { if($value[$this->mess["IBLOCK_XML2_VALUE"]] === "false" || $value[$this->mess["IBLOCK_XML2_VALUE"]] === "0") { $bActive = false; break; } } } } return $bActive; } function ImportElement($arXMLElement, &$counter, $bWF, $arParent) { $arElement = array( "ACTIVE" => "Y", "PROPERTY_VALUES" => array(), ); if(isset($arXMLElement[$this->mess["IBLOCK_XML2_VERSION"]])) $arElement["TMP_ID"] = $arXMLElement[$this->mess["IBLOCK_XML2_VERSION"]]; else $arElement["TMP_ID"] = $this->GetElementCRC($arXMLElement); if(isset($arXMLElement[$this->mess["IBLOCK_XML2_ID_1C_SITE"]])) $arElement["XML_ID"] = $arXMLElement[$this->mess["IBLOCK_XML2_ID_1C_SITE"]]; elseif(isset($arXMLElement[$this->mess["IBLOCK_XML2_ID"]])) $arElement["XML_ID"] = $arXMLElement[$this->mess["IBLOCK_XML2_ID"]]; $obElement = new CIBlockElement; $obElement->CancelWFSetMove(); $rsElement = $obElement->GetList( Array("ID"=>"asc"), Array("=XML_ID" => $arElement["XML_ID"], "IBLOCK_ID" => $this->next_step["IBLOCK_ID"]), false, false, Array("ID", "TMP_ID", "ACTIVE", "CODE", "PREVIEW_PICTURE", "DETAIL_PICTURE") ); $bMatch = false; if($arDBElement = $rsElement->Fetch()) $bMatch = ($arElement["TMP_ID"] == $arDBElement["TMP_ID"]); if($bMatch && $this->use_crc) { //Check Active flag in XML is not set to false if($this->CheckIfElementIsActive($arXMLElement)) { //In case element is not active in database we have to activate it and its offers if($arDBElement["ACTIVE"] != "Y") { $obElement->Update($arDBElement["ID"], array("ACTIVE"=>"Y"), $bWF); $this->ChangeOffersStatus($arDBElement["ID"], "Y", $bWF); $counter["UPD"]++; } } $arElement["ID"] = $arDBElement["ID"]; } elseif(isset($arXMLElement[$this->mess["IBLOCK_XML2_NAME"]])) { if($arDBElement) { if ($arDBElement["PREVIEW_PICTURE"] > 0) $this->arElementFilesId["PREVIEW_PICTURE"] = array($arDBElement["PREVIEW_PICTURE"]); if ($arDBElement["DETAIL_PICTURE"] > 0) $this->arElementFilesId["DETAIL_PICTURE"] = array($arDBElement["DETAIL_PICTURE"]); $rsProperties = $obElement->GetProperty($this->next_step["IBLOCK_ID"], $arDBElement["ID"], "sort", "asc"); while($arProperty = $rsProperties->Fetch()) { if(!array_key_exists($arProperty["ID"], $arElement["PROPERTY_VALUES"])) $arElement["PROPERTY_VALUES"][$arProperty["ID"]] = array( "bOld" => true, ); $arElement["PROPERTY_VALUES"][$arProperty["ID"]][$arProperty['PROPERTY_VALUE_ID']] = array( "VALUE"=>$arProperty['VALUE'], "DESCRIPTION"=>$arProperty["DESCRIPTION"] ); if($arProperty["PROPERTY_TYPE"] == "F" && $arProperty["VALUE"] > 0) $this->arElementFilesId[$arProperty["ID"]][] = $arProperty["VALUE"]; } } if ($this->bCatalog && $this->next_step["bOffer"]) { if (isset($this->PROPERTY_MAP["CML2_LINK"])) { $p = strpos($arXMLElement[$this->mess["IBLOCK_XML2_ID"]], "#"); if ($p !== false) { $link_xml_id = substr($arXMLElement[$this->mess["IBLOCK_XML2_ID"]], 0, $p); } else { $link_xml_id = $arXMLElement[$this->mess["IBLOCK_XML2_ID"]]; } $arElement["PROPERTY_VALUES"][$this->PROPERTY_MAP["CML2_LINK"]] = [ "n0" => [ "VALUE" => $this->GetElementByXML_ID( $this->arProperties[$this->PROPERTY_MAP["CML2_LINK"]]["LINK_IBLOCK_ID"], $link_xml_id ), "DESCRIPTION" => false, ], ]; } } if(isset($arXMLElement[$this->mess["IBLOCK_XML2_NAME"]])) $arElement["NAME"] = $arXMLElement[$this->mess["IBLOCK_XML2_NAME"]]; if(isset($arXMLElement[$this->mess["IBLOCK_XML2_DELETE_MARK"]])) { $value = $arXMLElement[$this->mess["IBLOCK_XML2_DELETE_MARK"]]; $arElement["ACTIVE"] = ($value=="true") || intval($value)? "N": "Y"; } if(array_key_exists($this->mess["IBLOCK_XML2_BX_TAGS"], $arXMLElement)) $arElement["TAGS"] = $arXMLElement[$this->mess["IBLOCK_XML2_BX_TAGS"]]; if(array_key_exists($this->mess["IBLOCK_XML2_DESCRIPTION"], $arXMLElement)) { if($arXMLElement[$this->mess["IBLOCK_XML2_DESCRIPTION"]] <> '') $arElement["DETAIL_TEXT"] = $arXMLElement[$this->mess["IBLOCK_XML2_DESCRIPTION"]]; else $arElement["DETAIL_TEXT"] = ""; if(preg_match('/<[a-zA-Z0-9]+.*?>/', $arElement["DETAIL_TEXT"])) $arElement["DETAIL_TEXT_TYPE"] = "html"; else $arElement["DETAIL_TEXT_TYPE"] = "text"; } if(array_key_exists($this->mess["IBLOCK_XML2_FULL_TITLE"], $arXMLElement)) { if($arXMLElement[$this->mess["IBLOCK_XML2_FULL_TITLE"]] <> '') $arElement["PREVIEW_TEXT"] = $arXMLElement[$this->mess["IBLOCK_XML2_FULL_TITLE"]]; else $arElement["PREVIEW_TEXT"] = ""; if(preg_match('/<[a-zA-Z0-9]+.*?>/', $arElement["PREVIEW_TEXT"])) $arElement["PREVIEW_TEXT_TYPE"] = "html"; else $arElement["PREVIEW_TEXT_TYPE"] = "text"; } if(array_key_exists($this->mess["IBLOCK_XML2_INHERITED_TEMPLATES"], $arXMLElement)) { $arElement["IPROPERTY_TEMPLATES"] = array(); foreach($arXMLElement[$this->mess["IBLOCK_XML2_INHERITED_TEMPLATES"]] as $TEMPLATE) { $id = $TEMPLATE[$this->mess["IBLOCK_XML2_ID"]]; $template = $TEMPLATE[$this->mess["IBLOCK_XML2_VALUE"]]; if($id <> '' && $template <> '') $arElement["IPROPERTY_TEMPLATES"][$id] = $template; } } if (isset($this->PROPERTY_MAP["CML2_BAR_CODE"])) { if (array_key_exists($this->mess["IBLOCK_XML2_BAR_CODE2"], $arXMLElement)) { $arElement["PROPERTY_VALUES"][$this->PROPERTY_MAP["CML2_BAR_CODE"]] = [ "n0" => [ "VALUE" => $arXMLElement[$this->mess["IBLOCK_XML2_BAR_CODE2"]], "DESCRIPTION" => false, ], ]; } elseif (array_key_exists($this->mess["IBLOCK_XML2_BAR_CODE"], $arXMLElement)) { $arElement["PROPERTY_VALUES"][$this->PROPERTY_MAP["CML2_BAR_CODE"]] = [ "n0" => [ "VALUE" => $arXMLElement[$this->mess["IBLOCK_XML2_BAR_CODE"]], "DESCRIPTION" => false, ], ]; } } if (isset($this->PROPERTY_MAP["CML2_ARTICLE"])) { if (array_key_exists($this->mess["IBLOCK_XML2_ARTICLE"], $arXMLElement)) { $arElement["PROPERTY_VALUES"][$this->PROPERTY_MAP["CML2_ARTICLE"]] = [ "n0" => [ "VALUE" => $arXMLElement[$this->mess["IBLOCK_XML2_ARTICLE"]], "DESCRIPTION" => false, ], ]; } } if ( array_key_exists($this->mess["IBLOCK_XML2_MANUFACTURER"], $arXMLElement) && isset($this->PROPERTY_MAP["CML2_MANUFACTURER"]) && $this->PROPERTY_MAP["CML2_MANUFACTURER"] > 0 ) { $arElement["PROPERTY_VALUES"][$this->PROPERTY_MAP["CML2_MANUFACTURER"]] = array( "n0" => array( "VALUE" => $this->CheckManufacturer($arXMLElement[$this->mess["IBLOCK_XML2_MANUFACTURER"]]), "DESCRIPTION" => false, ), ); } if(array_key_exists($this->mess["IBLOCK_XML2_PICTURE"], $arXMLElement)) { $rsFiles = $this->_xml_file->GetList( array("ID" => "asc"), array("PARENT_ID" => $arParent["ID"], "NAME" => $this->mess["IBLOCK_XML2_PICTURE"]) ); $arFile = $rsFiles->Fetch(); if($arFile) { $description = ""; if($arFile["ATTRIBUTES"] <> '') { $arAttributes = unserialize($arFile["ATTRIBUTES"], ['allowed_classes' => false]); if(is_array($arAttributes) && array_key_exists($this->mess["IBLOCK_XML2_DESCRIPTION"], $arAttributes)) { $description = $arAttributes[$this->mess["IBLOCK_XML2_DESCRIPTION"]]; } } if($arFile["VALUE"] <> '') { $arElement["DETAIL_PICTURE"] = $this->ResizePicture($arFile["VALUE"], $this->detail, "DETAIL_PICTURE", $this->PROPERTY_MAP["CML2_PICTURES"] ?? ''); if(is_array($arElement["DETAIL_PICTURE"])) { $arElement["DETAIL_PICTURE"]["description"] = $description; $this->arFileDescriptionsMap[$arFile["VALUE"]][] = &$arElement["DETAIL_PICTURE"]["description"]; } if(is_array($this->preview)) { $arElement["PREVIEW_PICTURE"] = $this->ResizePicture($arFile["VALUE"], $this->preview, "PREVIEW_PICTURE"); if(is_array($arElement["PREVIEW_PICTURE"])) { $arElement["PREVIEW_PICTURE"]["description"] = $description; $this->arFileDescriptionsMap[$arFile["VALUE"]][] = &$arElement["PREVIEW_PICTURE"]["description"]; } } } else { $arElement["DETAIL_PICTURE"] = $this->MakeFileArray($this->_xml_file->GetAllChildrenArray($arFile["ID"])); if(is_array($arElement["DETAIL_PICTURE"])) { $arElement["DETAIL_PICTURE"]["description"] = $description; } } $prop_id = (int)($this->PROPERTY_MAP["CML2_PICTURES"] ?? 0); if($prop_id > 0) { $i = 1; while($arFile = $rsFiles->Fetch()) { $description = ""; if($arFile["ATTRIBUTES"] <> '') { $arAttributes = unserialize($arFile["ATTRIBUTES"], ['allowed_classes' => false]); if(is_array($arAttributes) && array_key_exists($this->mess["IBLOCK_XML2_DESCRIPTION"], $arAttributes)) { $description = $arAttributes[$this->mess["IBLOCK_XML2_DESCRIPTION"]]; } } if($arFile["VALUE"] <> '') $arPropFile = $this->ResizePicture($arFile["VALUE"], $this->detail, $this->PROPERTY_MAP["CML2_PICTURES"], "DETAIL_PICTURE"); else $arPropFile = $this->MakeFileArray($this->_xml_file->GetAllChildrenArray($arFile["ID"])); if(is_array($arPropFile)) { $arPropFile = array( "VALUE" => $arPropFile, "DESCRIPTION" => $description, ); } $arElement["PROPERTY_VALUES"][$prop_id]["n".$i] = $arPropFile; if ($arFile["VALUE"] <> '') $this->arFileDescriptionsMap[$arFile["VALUE"]][] = &$arElement["PROPERTY_VALUES"][$prop_id]["n".$i]["DESCRIPTION"]; $i++; } if( isset($arElement["PROPERTY_VALUES"][$prop_id]) && is_array($arElement["PROPERTY_VALUES"][$prop_id])) { foreach($arElement["PROPERTY_VALUES"][$prop_id] as $PROPERTY_VALUE_ID => $PROPERTY_VALUE) { if(!$PROPERTY_VALUE_ID) unset($arElement["PROPERTY_VALUES"][$prop_id][$PROPERTY_VALUE_ID]); elseif(strncmp($PROPERTY_VALUE_ID, "n", 1) !== 0) $arElement["PROPERTY_VALUES"][$prop_id][$PROPERTY_VALUE_ID] = array( "tmp_name" => "", "del" => "Y", ); } unset($arElement["PROPERTY_VALUES"][$prop_id]["bOld"]); } } } } $cleanCml2FilesProperty = false; if( array_key_exists($this->mess["IBLOCK_XML2_FILE"], $arXMLElement) && isset($this->PROPERTY_MAP["CML2_FILES"]) ) { $prop_id = $this->PROPERTY_MAP["CML2_FILES"]; $rsFiles = $this->_xml_file->GetList( array("ID" => "asc"), array("PARENT_ID" => $arParent["ID"], "NAME" => $this->mess["IBLOCK_XML2_FILE"]) ); $i = 1; while($arFile = $rsFiles->Fetch()) { if($arFile["VALUE"] <> '') $file = $this->MakeFileArray($arFile["VALUE"], array($prop_id)); else $file = $this->MakeFileArray($this->_xml_file->GetAllChildrenArray($arFile["ID"])); $arElement["PROPERTY_VALUES"][$prop_id]["n".$i] = array( "VALUE" => $file, "DESCRIPTION" => $file["description"], ); if($arFile["ATTRIBUTES"] <> '') { $desc = unserialize($arFile["ATTRIBUTES"], ['allowed_classes' => false]); if(is_array($desc) && array_key_exists($this->mess["IBLOCK_XML2_DESCRIPTION"], $desc)) { $arElement["PROPERTY_VALUES"][$prop_id]["n".$i]["DESCRIPTION"] = $desc[$this->mess["IBLOCK_XML2_DESCRIPTION"]]; } } $i++; } $cleanCml2FilesProperty = true; } if(array_key_exists($this->mess["IBLOCK_XML2_GROUPS"], $arXMLElement)) { $arElement["IBLOCK_SECTION"] = array(); if ( !empty($arXMLElement[$this->mess["IBLOCK_XML2_GROUPS"]]) && is_array($arXMLElement[$this->mess["IBLOCK_XML2_GROUPS"]]) ) { foreach ($arXMLElement[$this->mess["IBLOCK_XML2_GROUPS"]] as $value) { if (array_key_exists($value, $this->SECTION_MAP)) $arElement["IBLOCK_SECTION"][] = $this->SECTION_MAP[$value]; } } if($arElement["IBLOCK_SECTION"]) $arElement["IBLOCK_SECTION_ID"] = $arElement["IBLOCK_SECTION"][0]; } if(array_key_exists($this->mess["IBLOCK_XML2_PRICES"], $arXMLElement)) {//Collect price information for future use $arElement["PRICES"] = array(); if (is_array($arXMLElement[$this->mess["IBLOCK_XML2_PRICES"]])) { foreach($arXMLElement[$this->mess["IBLOCK_XML2_PRICES"]] as $price) { if(isset($price[$this->mess["IBLOCK_XML2_PRICE_TYPE_ID"]]) && array_key_exists($price[$this->mess["IBLOCK_XML2_PRICE_TYPE_ID"]], $this->PRICES_MAP)) { $price["PRICE"] = $this->PRICES_MAP[$price[$this->mess["IBLOCK_XML2_PRICE_TYPE_ID"]]]; $arElement["PRICES"][] = $price; } } } $arElement["DISCOUNTS"] = array(); if(isset($arXMLElement[$this->mess["IBLOCK_XML2_DISCOUNTS"]])) { foreach($arXMLElement[$this->mess["IBLOCK_XML2_DISCOUNTS"]] as $discount) { if( isset($discount[$this->mess["IBLOCK_XML2_DISCOUNT_CONDITION"]]) && $discount[$this->mess["IBLOCK_XML2_DISCOUNT_CONDITION"]]===$this->mess["IBLOCK_XML2_DISCOUNT_COND_VOLUME"] ) { $discount_value = $this->ToInt($discount[$this->mess["IBLOCK_XML2_DISCOUNT_COND_VALUE"]]); $discount_percent = $this->ToFloat($discount[$this->mess["IBLOCK_XML2_DISCOUNT_COND_PERCENT"]]); if($discount_value > 0 && $discount_percent > 0) $arElement["DISCOUNTS"][$discount_value] = $discount_percent; } } } } if($this->bCatalog && array_key_exists($this->mess["IBLOCK_XML2_AMOUNT"], $arXMLElement)) { $arElement["QUANTITY_RESERVED"] = 0; if($arDBElement) { $iterator = Catalog\Model\Product::getList([ 'select' => ['ID', 'QUANTITY_RESERVED'], 'filter' => ['=ID' => $arDBElement['ID']] ]); $arElementTmp = $iterator->fetch(); if (isset($arElementTmp["QUANTITY_RESERVED"])) $arElement["QUANTITY_RESERVED"] = (float)$arElementTmp["QUANTITY_RESERVED"]; unset($arElementTmp); unset($iterator); } $arElement["QUANTITY"] = $this->ToFloat($arXMLElement[$this->mess["IBLOCK_XML2_AMOUNT"]]) - $arElement["QUANTITY_RESERVED"]; } if ( isset($arXMLElement[$this->mess["IBLOCK_XML2_ITEM_ATTRIBUTES"]]) && isset($this->PROPERTY_MAP["CML2_ATTRIBUTES"]) ) { $arElement["PROPERTY_VALUES"][$this->PROPERTY_MAP["CML2_ATTRIBUTES"]] = array(); $i = 0; foreach($arXMLElement[$this->mess["IBLOCK_XML2_ITEM_ATTRIBUTES"]] as $value) { $arElement["PROPERTY_VALUES"][$this->PROPERTY_MAP["CML2_ATTRIBUTES"]]["n".$i] = array( "VALUE" => $value[$this->mess["IBLOCK_XML2_VALUE"]], "DESCRIPTION" => $value[$this->mess["IBLOCK_XML2_NAME"]], ); $i++; } } $i = 0; $weightKey = false; if (isset($arXMLElement[$this->mess["IBLOCK_XML2_TRAITS_VALUES"]])) { if (isset($this->PROPERTY_MAP["CML2_TRAITS"])) { $arElement["PROPERTY_VALUES"][$this->PROPERTY_MAP["CML2_TRAITS"]] = []; } foreach($arXMLElement[$this->mess["IBLOCK_XML2_TRAITS_VALUES"]] as $value) { if( !array_key_exists("PREVIEW_TEXT", $arElement) && $value[$this->mess["IBLOCK_XML2_NAME"]] == $this->mess["IBLOCK_XML2_FULL_TITLE2"] ) { $arElement["PREVIEW_TEXT"] = $value[$this->mess["IBLOCK_XML2_VALUE"]]; if(strpos($arElement["PREVIEW_TEXT"], "<") !== false) $arElement["PREVIEW_TEXT_TYPE"] = "html"; else $arElement["PREVIEW_TEXT_TYPE"] = "text"; } elseif( $value[$this->mess["IBLOCK_XML2_NAME"]] == $this->mess["IBLOCK_XML2_HTML_DESCRIPTION"] ) { if($value[$this->mess["IBLOCK_XML2_VALUE"]] <> '') { $arElement["DETAIL_TEXT"] = $value[$this->mess["IBLOCK_XML2_VALUE"]]; $arElement["DETAIL_TEXT_TYPE"] = "html"; } } elseif( $value[$this->mess["IBLOCK_XML2_NAME"]] == $this->mess["IBLOCK_XML2_FILE"] ) { if($value[$this->mess["IBLOCK_XML2_VALUE"]] <> '') { $prop_id = $this->PROPERTY_MAP["CML2_FILES"] ?? 0; $j = 1; while (isset($arElement["PROPERTY_VALUES"][$prop_id]["n".$j])) $j++; $file = $this->MakeFileArray($value[$this->mess["IBLOCK_XML2_VALUE"]], array($prop_id)); if (is_array($file)) { $arElement["PROPERTY_VALUES"][$prop_id]["n".$j] = array( "VALUE" => $file, "DESCRIPTION" => "", ); unset($arElement["PROPERTY_VALUES"][$prop_id]["bOld"]); $this->arFileDescriptionsMap[$value[$this->mess["IBLOCK_XML2_VALUE"]]][] = &$arElement["PROPERTY_VALUES"][$prop_id]["n".$j]["DESCRIPTION"]; $cleanCml2FilesProperty = true; } } } elseif( $value[$this->mess["IBLOCK_XML2_NAME"]] == $this->mess["IBLOCK_XML2_FILE_DESCRIPTION"] ) { if($value[$this->mess["IBLOCK_XML2_VALUE"]] <> '') { [$fileName, $description] = explode("#", $value[$this->mess["IBLOCK_XML2_VALUE"]]); if (isset($this->arFileDescriptionsMap[$fileName])) { foreach($this->arFileDescriptionsMap[$fileName] as $k => $tmp) $this->arFileDescriptionsMap[$fileName][$k] = $description; } } } else { if($value[$this->mess["IBLOCK_XML2_NAME"]] == $this->mess["IBLOCK_XML2_WEIGHT"]) { $arElement["BASE_WEIGHT"] = $this->ToFloat($value[$this->mess["IBLOCK_XML2_VALUE"]])*1000; $weightKey = "n".$i; } if (isset($this->PROPERTY_MAP["CML2_TRAITS"])) { $arElement["PROPERTY_VALUES"][$this->PROPERTY_MAP["CML2_TRAITS"]]["n" . $i] = [ "VALUE" => $value[$this->mess["IBLOCK_XML2_VALUE"]], "DESCRIPTION" => $value[$this->mess["IBLOCK_XML2_NAME"]], ]; } $i++; } } } if (isset($arXMLElement[$this->mess["IBLOCK_XML2_WEIGHT"]])) { if (isset($this->PROPERTY_MAP["CML2_TRAITS"])) { if ($weightKey === false) { if (!isset($arElement["PROPERTY_VALUES"][$this->PROPERTY_MAP["CML2_TRAITS"]])) { $arElement["PROPERTY_VALUES"][$this->PROPERTY_MAP["CML2_TRAITS"]] = []; $weightKey = "n0"; } else // $weightKey === false && isset($arElement["PROPERTY_VALUES"][$this->PROPERTY_MAP["CML2_TRAITS"]]) { $weightKey = "n" . $i; } } $arElement["PROPERTY_VALUES"][$this->PROPERTY_MAP["CML2_TRAITS"]][$weightKey] = [ "VALUE" => $arXMLElement[$this->mess["IBLOCK_XML2_WEIGHT"]], "DESCRIPTION" => $this->mess["IBLOCK_XML2_WEIGHT"], ]; } $arElement["BASE_WEIGHT"] = $this->ToFloat($arXMLElement[$this->mess["IBLOCK_XML2_WEIGHT"]])*1000; } if ($this->bCatalog) { $arElement = array_merge( $arElement, $this->getProductFieldsFromXml($arXMLElement) ); } if ($cleanCml2FilesProperty) { $prop_id = $this->PROPERTY_MAP["CML2_FILES"] ?? 0; if ( isset($arElement["PROPERTY_VALUES"][$prop_id]) && is_array($arElement["PROPERTY_VALUES"][$prop_id]) ) { foreach($arElement["PROPERTY_VALUES"][$prop_id] as $PROPERTY_VALUE_ID => $PROPERTY_VALUE) { if(!$PROPERTY_VALUE_ID) unset($arElement["PROPERTY_VALUES"][$prop_id][$PROPERTY_VALUE_ID]); elseif(strncmp($PROPERTY_VALUE_ID, "n", 1) !== 0) $arElement["PROPERTY_VALUES"][$prop_id][$PROPERTY_VALUE_ID] = array( "tmp_name" => "", "del" => "Y", ); } unset($arElement["PROPERTY_VALUES"][$prop_id]["bOld"]); } } if (isset($arXMLElement[$this->mess["IBLOCK_XML2_TAXES_VALUES"]])) { if (isset($this->PROPERTY_MAP["CML2_TAXES"])) { $arElement["PROPERTY_VALUES"][$this->PROPERTY_MAP["CML2_TAXES"]] = []; $i = 0; foreach ($arXMLElement[$this->mess["IBLOCK_XML2_TAXES_VALUES"]] as $value) { $arElement["PROPERTY_VALUES"][$this->PROPERTY_MAP["CML2_TAXES"]]["n" . $i] = [ "VALUE" => $value[$this->mess["IBLOCK_XML2_TAX_VALUE"]], "DESCRIPTION" => $value[$this->mess["IBLOCK_XML2_NAME"]], ]; $i++; } } } $rsBaseUnit = $this->_xml_file->GetList( array("ID" => "asc"), array( "><LEFT_MARGIN" => array($arParent["LEFT_MARGIN"], $arParent["RIGHT_MARGIN"]), "NAME" => $this->mess["IBLOCK_XML2_BASE_UNIT"], ), array("ID", "ATTRIBUTES") ); while ($arBaseUnit = $rsBaseUnit->Fetch()) { if($arBaseUnit["ATTRIBUTES"] <> '') { $info = unserialize($arBaseUnit["ATTRIBUTES"], ['allowed_classes' => false]); if( is_array($info) && array_key_exists($this->mess["IBLOCK_XML2_CODE"], $info) ) { $arXMLElement[$this->mess["IBLOCK_XML2_BASE_UNIT"]] = $info[$this->mess["IBLOCK_XML2_CODE"]]; } } } if(isset($arXMLElement[$this->mess["IBLOCK_XML2_BASE_UNIT"]])) { $unitData = $this->convertBaseUnitFromXmlToPropertyValue($arXMLElement[$this->mess["IBLOCK_XML2_BASE_UNIT"]]); if (isset($this->PROPERTY_MAP["CML2_BASE_UNIT"])) { $arElement["PROPERTY_VALUES"][$this->PROPERTY_MAP["CML2_BASE_UNIT"]] = [ "n0" => $unitData, ]; } if ($unitData["DESCRIPTION"]) { $arElement['MEASURE'] = $unitData["DESCRIPTION"]; } } if(isset($arXMLElement[$this->mess["IBLOCK_XML2_PROPERTIES_VALUES"]])) { foreach($arXMLElement[$this->mess["IBLOCK_XML2_PROPERTIES_VALUES"]] as $value) { if(!array_key_exists($this->mess["IBLOCK_XML2_ID"], $value)) continue; $prop_id = $value[$this->mess["IBLOCK_XML2_ID"]]; unset($value[$this->mess["IBLOCK_XML2_ID"]]); //Handle properties which is actually element fields if(!array_key_exists($prop_id, $this->PROPERTY_MAP)) { if($prop_id == "CML2_CODE") $arElement["CODE"] = $value[$this->mess["IBLOCK_XML2_VALUE"]] ?? ""; elseif($prop_id == "CML2_ACTIVE") { $value = array_pop($value); $arElement["ACTIVE"] = ($value=="true") || intval($value)? "Y": "N"; } elseif($prop_id == "CML2_SORT") $arElement["SORT"] = array_pop($value); elseif($prop_id == "CML2_ACTIVE_FROM") $arElement["ACTIVE_FROM"] = CDatabase::FormatDate(array_pop($value), "YYYY-MM-DD HH:MI:SS", CLang::GetDateFormat("FULL")); elseif($prop_id == "CML2_ACTIVE_TO") $arElement["ACTIVE_TO"] = CDatabase::FormatDate(array_pop($value), "YYYY-MM-DD HH:MI:SS", CLang::GetDateFormat("FULL")); elseif($prop_id == "CML2_PREVIEW_TEXT") { if(array_key_exists($this->mess["IBLOCK_XML2_VALUE"], $value)) { if(isset($value[$this->mess["IBLOCK_XML2_VALUE"]])) $arElement["PREVIEW_TEXT"] = $value[$this->mess["IBLOCK_XML2_VALUE"]]; else $arElement["PREVIEW_TEXT"] = ""; if(isset($value[$this->mess["IBLOCK_XML2_TYPE"]])) $arElement["PREVIEW_TEXT_TYPE"] = $value[$this->mess["IBLOCK_XML2_TYPE"]]; else $arElement["PREVIEW_TEXT_TYPE"] = "html"; } } elseif($prop_id == "CML2_DETAIL_TEXT") { if(array_key_exists($this->mess["IBLOCK_XML2_VALUE"], $value)) { if(isset($value[$this->mess["IBLOCK_XML2_VALUE"]])) $arElement["DETAIL_TEXT"] = $value[$this->mess["IBLOCK_XML2_VALUE"]]; else $arElement["DETAIL_TEXT"] = ""; if(isset($value[$this->mess["IBLOCK_XML2_TYPE"]])) $arElement["DETAIL_TEXT_TYPE"] = $value[$this->mess["IBLOCK_XML2_TYPE"]]; else $arElement["DETAIL_TEXT_TYPE"] = "html"; } } elseif($prop_id == "CML2_PREVIEW_PICTURE") { if(!is_array($this->preview) || !$arElement["PREVIEW_PICTURE"]) { $arElement["PREVIEW_PICTURE"] = $this->MakeFileArray($value[$this->mess["IBLOCK_XML2_VALUE"]], array("PREVIEW_PICTURE")); $arElement["PREVIEW_PICTURE"]["COPY_FILE"] = "Y"; } } continue; } $prop_id = $this->PROPERTY_MAP[$prop_id]; $prop_type = $this->arProperties[$prop_id]["PROPERTY_TYPE"]; if(!array_key_exists($prop_id, $arElement["PROPERTY_VALUES"])) $arElement["PROPERTY_VALUES"][$prop_id] = array(); //check for bitrix extended format if(array_key_exists($this->mess["IBLOCK_XML2_PROPERTY_VALUE"], $value)) { $i = 1; $strPV = $this->mess["IBLOCK_XML2_PROPERTY_VALUE"]; $lPV = mb_strlen($strPV); foreach($value as $k=>$prop_value) { if ($prop_value === null) { continue; } if(mb_substr($k, 0, $lPV) === $strPV) { if(array_key_exists($this->mess["IBLOCK_XML2_SERIALIZED"], $prop_value)) $prop_value[$this->mess["IBLOCK_XML2_VALUE"]] = $this->Unserialize($prop_value[$this->mess["IBLOCK_XML2_VALUE"]]); if($prop_type=="F") { $prop_value[$this->mess["IBLOCK_XML2_VALUE"]] = $this->MakeFileArray($prop_value[$this->mess["IBLOCK_XML2_VALUE"]], array($prop_id)); } elseif($prop_type=="G") $prop_value[$this->mess["IBLOCK_XML2_VALUE"]] = $this->GetSectionByXML_ID($this->arProperties[$prop_id]["LINK_IBLOCK_ID"], $prop_value[$this->mess["IBLOCK_XML2_VALUE"]]); elseif($prop_type=="E") $prop_value[$this->mess["IBLOCK_XML2_VALUE"]] = $this->GetElementByXML_ID($this->arProperties[$prop_id]["LINK_IBLOCK_ID"], $prop_value[$this->mess["IBLOCK_XML2_VALUE"]]); elseif($prop_type=="L") $prop_value[$this->mess["IBLOCK_XML2_VALUE"]] = $this->GetEnumByXML_ID($this->arProperties[$prop_id]["ID"], $prop_value[$this->mess["IBLOCK_XML2_VALUE"]]); if(array_key_exists("bOld", $arElement["PROPERTY_VALUES"][$prop_id])) { if($prop_type=="F") { foreach($arElement["PROPERTY_VALUES"][$prop_id] as $PROPERTY_VALUE_ID => $PROPERTY_VALUE) $arElement["PROPERTY_VALUES"][$prop_id][$PROPERTY_VALUE_ID] = array( "tmp_name" => "", "del" => "Y", ); unset($arElement["PROPERTY_VALUES"][$prop_id]["bOld"]); } else $arElement["PROPERTY_VALUES"][$prop_id] = array(); } $arElement["PROPERTY_VALUES"][$prop_id]["n".$i] = array( "VALUE" => $prop_value[$this->mess["IBLOCK_XML2_VALUE"]], "DESCRIPTION" => $prop_value[$this->mess["IBLOCK_XML2_DESCRIPTION"]] ?? null, ); $i++; } } } else { if($prop_type == "L" && !array_key_exists($this->mess["IBLOCK_XML2_VALUE_ID"], $value)) $l_key = $this->mess["IBLOCK_XML2_VALUE"]; else $l_key = $this->mess["IBLOCK_XML2_VALUE_ID"]; $i = 0; foreach($value as $k=>$prop_value) { if(array_key_exists("bOld", $arElement["PROPERTY_VALUES"][$prop_id])) { if($prop_type=="F") { foreach($arElement["PROPERTY_VALUES"][$prop_id] as $PROPERTY_VALUE_ID => $PROPERTY_VALUE) $arElement["PROPERTY_VALUES"][$prop_id][$PROPERTY_VALUE_ID] = array( "tmp_name" => "", "del" => "Y", ); unset($arElement["PROPERTY_VALUES"][$prop_id]["bOld"]); } else { $arElement["PROPERTY_VALUES"][$prop_id] = array(); } } if($prop_type == "L" && $k == $l_key) { $prop_value = $this->GetEnumByXML_ID($this->arProperties[$prop_id]["ID"], $prop_value); } elseif($prop_type == "N" && isset($this->next_step["sdp"])) { if ($prop_value <> '') $prop_value = $this->ToFloat($prop_value); } $arElement["PROPERTY_VALUES"][$prop_id]["n".$i] = array( "VALUE" => $prop_value, "DESCRIPTION" => false, ); $i++; } } } } //If there is no BaseUnit specified check prices for it if (isset($this->PROPERTY_MAP["CML2_BASE_UNIT"])) { if ( ( !array_key_exists($this->PROPERTY_MAP["CML2_BASE_UNIT"], $arElement["PROPERTY_VALUES"]) || ( is_array($arElement["PROPERTY_VALUES"][$this->PROPERTY_MAP["CML2_BASE_UNIT"]]) && array_key_exists("bOld", $arElement["PROPERTY_VALUES"][$this->PROPERTY_MAP["CML2_BASE_UNIT"]]) ) ) && isset($arXMLElement[$this->mess["IBLOCK_XML2_PRICES"]]) ) { foreach ($arXMLElement[$this->mess["IBLOCK_XML2_PRICES"]] as $price) { if ( isset($price[$this->mess["IBLOCK_XML2_PRICE_TYPE_ID"]]) && array_key_exists($price[$this->mess["IBLOCK_XML2_PRICE_TYPE_ID"]], $this->PRICES_MAP) && array_key_exists($this->mess["IBLOCK_XML2_MEASURE"], $price) ) { $arElement["PROPERTY_VALUES"][$this->PROPERTY_MAP["CML2_BASE_UNIT"]] = [ "n0" => $this->convertBaseUnitFromXmlToPropertyValue($price[$this->mess["IBLOCK_XML2_MEASURE"]]), ]; break; } } } } if($arDBElement) { foreach($arElement["PROPERTY_VALUES"] as $prop_id=>$prop) { if(is_array($arElement["PROPERTY_VALUES"][$prop_id]) && array_key_exists("bOld", $arElement["PROPERTY_VALUES"][$prop_id])) { if($this->arProperties[$prop_id]["PROPERTY_TYPE"]=="F") unset($arElement["PROPERTY_VALUES"][$prop_id]); else unset($arElement["PROPERTY_VALUES"][$prop_id]["bOld"]); } } if (!isset($arElement['MODIFIED_BY']) || (int)$arElement['MODIFIED_BY'] <= 0) { if ($this->currentUserId > 0) { $arElement['MODIFIED_BY'] = $this->currentUserId; } } if(!array_key_exists("CODE", $arElement) && is_array($this->translit_on_update)) { $CODE = CUtil::translit($arElement["NAME"], LANGUAGE_ID, $this->translit_on_update); $CODE = $this->CheckElementCode($this->next_step["IBLOCK_ID"], $arDBElement["ID"], $CODE); if($CODE !== false) $arElement["CODE"] = $CODE; } //Check if detail picture hasn't been changed if ( isset($arElement["DETAIL_PICTURE"]) && !isset($arElement["PREVIEW_PICTURE"]) && is_array($arElement["DETAIL_PICTURE"]) && isset($arElement["DETAIL_PICTURE"]["external_id"]) && $this->arElementFilesId && $this->arElementFilesId["DETAIL_PICTURE"] && isset($this->arElementFiles[$this->arElementFilesId["DETAIL_PICTURE"][0]]) && $this->arElementFiles[$this->arElementFilesId["DETAIL_PICTURE"][0]]["EXTERNAL_ID"] === $arElement["DETAIL_PICTURE"]["external_id"] && $this->arElementFiles[$this->arElementFilesId["DETAIL_PICTURE"][0]]["DESCRIPTION"] === $arElement["DETAIL_PICTURE"]["description"] ) { unset($arElement["DETAIL_PICTURE"]); } $updateResult = $obElement->Update($arDBElement["ID"], $arElement, $bWF, true, $this->iblock_resize); //In case element was not active in database we have to activate its offers if($arDBElement["ACTIVE"] != "Y") { $this->ChangeOffersStatus($arDBElement["ID"], "Y", $bWF); } $arElement["ID"] = $arDBElement["ID"]; if($updateResult) { $counter["UPD"]++; } else { $this->LAST_ERROR = $obElement->LAST_ERROR; $counter["ERR"]++; } } else { if(!array_key_exists("CODE", $arElement) && is_array($this->translit_on_add)) { $CODE = CUtil::translit($arElement["NAME"], LANGUAGE_ID, $this->translit_on_add); $CODE = $this->CheckElementCode($this->next_step["IBLOCK_ID"], 0, $CODE); if($CODE !== false) $arElement["CODE"] = $CODE; } $arElement["IBLOCK_ID"] = $this->next_step["IBLOCK_ID"]; $this->fillDefaultPropertyValues($arElement, $this->arProperties); $arElement["ID"] = $obElement->Add($arElement, $bWF, true, $this->iblock_resize); if($arElement["ID"]) { $counter["ADD"]++; } else { $this->LAST_ERROR = $obElement->LAST_ERROR; $counter["ERR"]++; } } } elseif(array_key_exists($this->mess["IBLOCK_XML2_PRICES"], $arXMLElement)) { //Collect price information for future use $arElement["PRICES"] = array(); if (is_array($arXMLElement[$this->mess["IBLOCK_XML2_PRICES"]])) { foreach($arXMLElement[$this->mess["IBLOCK_XML2_PRICES"]] as $price) { if(isset($price[$this->mess["IBLOCK_XML2_PRICE_TYPE_ID"]]) && array_key_exists($price[$this->mess["IBLOCK_XML2_PRICE_TYPE_ID"]], $this->PRICES_MAP)) { $price["PRICE"] = $this->PRICES_MAP[$price[$this->mess["IBLOCK_XML2_PRICE_TYPE_ID"]]]; $arElement["PRICES"][] = $price; } } } $arElement["DISCOUNTS"] = array(); if(isset($arXMLElement[$this->mess["IBLOCK_XML2_DISCOUNTS"]])) { foreach($arXMLElement[$this->mess["IBLOCK_XML2_DISCOUNTS"]] as $discount) { if( isset($discount[$this->mess["IBLOCK_XML2_DISCOUNT_CONDITION"]]) && $discount[$this->mess["IBLOCK_XML2_DISCOUNT_CONDITION"]]===$this->mess["IBLOCK_XML2_DISCOUNT_COND_VOLUME"] ) { $discount_value = $this->ToInt($discount[$this->mess["IBLOCK_XML2_DISCOUNT_COND_VALUE"]]); $discount_percent = $this->ToFloat($discount[$this->mess["IBLOCK_XML2_DISCOUNT_COND_PERCENT"]]); if($discount_value > 0 && $discount_percent > 0) $arElement["DISCOUNTS"][$discount_value] = $discount_percent; } } } if ($arDBElement) { $arElement["ID"] = $arDBElement["ID"]; $counter["UPD"]++; } } if(isset($arXMLElement[$this->mess["IBLOCK_XML2_STORE_AMOUNT_LIST"]])) { $arElement["STORE_AMOUNT"] = array(); foreach($arXMLElement[$this->mess["IBLOCK_XML2_STORE_AMOUNT_LIST"]] as $storeAmount) { if(isset($storeAmount[$this->mess["IBLOCK_XML2_STORE_ID"]])) { $storeXMLID = $storeAmount[$this->mess["IBLOCK_XML2_STORE_ID"]]; $amount = $this->ToFloat($storeAmount[$this->mess["IBLOCK_XML2_AMOUNT"]]); $arElement["STORE_AMOUNT"][$storeXMLID] = $amount; } } } elseif( array_key_exists($this->mess["IBLOCK_XML2_STORES"], $arXMLElement) || array_key_exists($this->mess["IBLOCK_XML2_STORE"], $arXMLElement) ) { $arElement["STORE_AMOUNT"] = array(); $rsStores = $this->_xml_file->GetList( array("ID" => "asc"), array( "><LEFT_MARGIN" => array($arParent["LEFT_MARGIN"], $arParent["RIGHT_MARGIN"]), "NAME" => $this->mess["IBLOCK_XML2_STORE"], ), array("ID", "ATTRIBUTES") ); while ($arStore = $rsStores->Fetch()) { if($arStore["ATTRIBUTES"] <> '') { $info = unserialize($arStore["ATTRIBUTES"], ['allowed_classes' => false]); if( is_array($info) && array_key_exists($this->mess["IBLOCK_XML2_STORE_ID"], $info) && array_key_exists($this->mess["IBLOCK_XML2_STORE_AMOUNT"], $info) ) { $arElement["STORE_AMOUNT"][$info[$this->mess["IBLOCK_XML2_STORE_ID"]]] = $this->ToFloat($info[$this->mess["IBLOCK_XML2_STORE_AMOUNT"]]); } } } } if($bMatch && $this->use_crc) { //nothing to do } elseif($arElement["ID"] && $this->bCatalog && $this->isCatalogIblock) { $arProduct = array( "ID" => $arElement["ID"], ); if(isset($arElement["QUANTITY"])) $arProduct["QUANTITY"] = (float)$arElement["QUANTITY"]; elseif(isset($arElement["STORE_AMOUNT"]) && !empty($arElement["STORE_AMOUNT"])) $arProduct["QUANTITY"] = $this->countTotalQuantity($arElement["STORE_AMOUNT"]); $CML_LINK = ''; $CML_LINK_ELEMENT = 0; if (isset($this->PROPERTY_MAP["CML2_LINK"])) { $CML_LINK = $this->PROPERTY_MAP["CML2_LINK"]; if (isset($arElement["PROPERTY_VALUES"][$CML_LINK])) { $CML_LINK_ELEMENT = $arElement["PROPERTY_VALUES"][$CML_LINK]; } } if (is_array($CML_LINK_ELEMENT) && isset($CML_LINK_ELEMENT["n0"])) { $CML_LINK_ELEMENT = $CML_LINK_ELEMENT["n0"]; } if (is_array($CML_LINK_ELEMENT) && isset($CML_LINK_ELEMENT["VALUE"])) { $CML_LINK_ELEMENT = $CML_LINK_ELEMENT["VALUE"]; } if(isset($arElement["BASE_WEIGHT"])) { $arProduct["WEIGHT"] = (float)$arElement["BASE_WEIGHT"]; } elseif ($CML_LINK_ELEMENT > 0) { $rsWeight = CIBlockElement::GetProperty($this->arProperties[$CML_LINK]["LINK_IBLOCK_ID"], $CML_LINK_ELEMENT, array(), array("CODE" => "CML2_TRAITS")); while($arWeight = $rsWeight->Fetch()) { if($arWeight["DESCRIPTION"] == $this->mess["IBLOCK_XML2_WEIGHT"]) $arProduct["WEIGHT"] = $this->ToFloat($arWeight["VALUE"])*1000; } } if ($CML_LINK_ELEMENT > 0) { $rsUnit = CIBlockElement::GetProperty($this->arProperties[$CML_LINK]["LINK_IBLOCK_ID"], $CML_LINK_ELEMENT, array(), array("CODE" => "CML2_BASE_UNIT")); while($arUnit = $rsUnit->Fetch()) { if($arUnit["DESCRIPTION"] > 0) $arProduct["MEASURE"] = $arUnit["DESCRIPTION"]; } } if(isset($arElement["PRICES"])) { //Here start VAT handling //Check if all the taxes exists in BSM catalog $arTaxMap = array(); if ($CML_LINK !== '' && isset($this->arProperties[$CML_LINK]) && $CML_LINK_ELEMENT > 0) { $rsTaxProperty = CIBlockElement::GetProperty( $this->arProperties[$CML_LINK]["LINK_IBLOCK_ID"], $CML_LINK_ELEMENT, "sort", "asc", [ "CODE" => "CML2_TAXES", ] ); while ($arTaxProperty = $rsTaxProperty->Fetch()) { if ( $arTaxProperty["DESCRIPTION"] <> '' && !array_key_exists($arTaxProperty["DESCRIPTION"], $arTaxMap) ) { if ($arTaxProperty["VALUE"] === '' || !is_numeric($arTaxProperty["VALUE"])) { $taxValue = null; } else { $taxValue = $this->ToFloat($arTaxProperty["VALUE"]); } $arTaxMap[$arTaxProperty["DESCRIPTION"]] = [ "RATE" => $this->ToFloat($arTaxProperty["VALUE"]), "ID" => $this->CheckTax($arTaxProperty["DESCRIPTION"], $taxValue), ]; } } unset($rsTaxProperty); } //First find out if all the prices have TAX_IN_SUM true $TAX_IN_SUM = "Y"; foreach($arElement["PRICES"] as $price) { if($price["PRICE"]["TAX_IN_SUM"] !== "true") { $TAX_IN_SUM = "N"; break; } } //If there was found not included tax we'll make sure //that all prices has the same flag if($TAX_IN_SUM === "N") { foreach($arElement["PRICES"] as $price) { if($price["PRICE"]["TAX_IN_SUM"] !== "false") { $TAX_IN_SUM = "Y"; break; } } //Check if there is a mix of tax in sum //and correct it by recalculating all the prices if($TAX_IN_SUM === "Y") { foreach($arElement["PRICES"] as $key=>$price) { if($price["PRICE"]["TAX_IN_SUM"] !== "true") { $TAX_NAME = $price["PRICE"]["TAX_NAME"]; if(array_key_exists($TAX_NAME, $arTaxMap)) { $PRICE_WO_TAX = $this->ToFloat($price[$this->mess["IBLOCK_XML2_PRICE_FOR_ONE"]]); $PRICE = $PRICE_WO_TAX + ($PRICE_WO_TAX / 100.0 * $arTaxMap[$TAX_NAME]["RATE"]); $arElement["PRICES"][$key][$this->mess["IBLOCK_XML2_PRICE_FOR_ONE"]] = $PRICE; } } } } } foreach($arElement["PRICES"] as $price) { $TAX_NAME = $price["PRICE"]["TAX_NAME"]; if(array_key_exists($TAX_NAME, $arTaxMap)) { $arProduct["VAT_ID"] = $arTaxMap[$TAX_NAME]["ID"]; break; } } $arProduct["VAT_INCLUDED"] = $TAX_IN_SUM; } $arProduct = array_merge( $arProduct, $this->getPreparedProductFieldsFromArray($arElement) ); $productCache = Catalog\Model\Product::getCacheItem($arProduct['ID'], true); if (!empty($productCache)) { $productResult = Catalog\Model\Product::update( $arProduct['ID'], array( 'fields' => $arProduct, 'external_fields' => array( 'IBLOCK_ID' => $this->next_step["IBLOCK_ID"] ) ) ); } else { $productResult = Catalog\Model\Product::add( array( 'fields' => $arProduct, 'external_fields' => array( 'IBLOCK_ID' => $this->next_step["IBLOCK_ID"] ) ) ); } if ($productResult->isSuccess()) { //TODO: replace this code after upload measure ratio from 1C $iterator = \Bitrix\Catalog\MeasureRatioTable::getList(array( 'select' => array('ID'), 'filter' => array('=PRODUCT_ID' => $arElement['ID']) )); $ratioRow = $iterator->fetch(); if (empty($ratioRow)) { $ratioResult = \Bitrix\Catalog\MeasureRatioTable::add(array( 'PRODUCT_ID' => $arElement['ID'], 'RATIO' => 1, 'IS_DEFAULT' => 'Y' )); unset($ratioResult); } unset($ratioRow, $iterator); } if(isset($arElement["PRICES"])) $this->SetProductPrice($arElement["ID"], $arElement["PRICES"], $arElement["DISCOUNTS"]); if(isset($arElement["STORE_AMOUNT"])) $this->ImportStoresAmount($arElement["STORE_AMOUNT"], $arElement["ID"], $counter); } return $arElement["ID"]; } protected function getProductFieldsFromXml(array $xmlElement): array { $result = []; if (array_key_exists($this->mess['IBLOCK_XML2_MARKING_CODE_GROUP'], $xmlElement)) { $result[Product\SystemField\MarkingCodeGroup::FIELD_ID] = $xmlElement[$this->mess['IBLOCK_XML2_MARKING_CODE_GROUP']] ?? ''; } if (array_key_exists($this->mess['IBLOCK_XML2_PRODUCT_MAPPING'], $xmlElement)) { $result[Product\SystemField\ProductMapping::FIELD_ID] = []; if (is_array($xmlElement[$this->mess['IBLOCK_XML2_PRODUCT_MAPPING']])) { foreach ($xmlElement[$this->mess['IBLOCK_XML2_PRODUCT_MAPPING']] as $value) { $value = (string)$value; if ($value !== '') { $result[Product\SystemField\ProductMapping::FIELD_ID][] = $value; } } } } if (isset($xmlElement[$this->mess['IBLOCK_XML2_WIDTH']])) { $result['WIDTH'] = $this->ToFloatEmpty($xmlElement[$this->mess['IBLOCK_XML2_WIDTH']]); } if (isset($xmlElement[$this->mess['IBLOCK_XML2_LENGTH']])) { $result['LENGTH'] = $this->ToFloatEmpty($xmlElement[$this->mess['IBLOCK_XML2_LENGTH']]); } if (isset($xmlElement[$this->mess['IBLOCK_XML2_HEIGHT']])) { $result['HEIGHT'] = $this->ToFloatEmpty($xmlElement[$this->mess['IBLOCK_XML2_HEIGHT']]); } return $result; } protected function getPreparedProductFieldsFromArray(array $element): array { $result = []; $productSystemFields = Product\SystemField::getImportSelectFields(); if (!empty($productSystemFields)) { foreach ($productSystemFields as $index => $value) { $fieldName = is_string($index) ? $index : $value; if (isset($element[$fieldName])) { $result[$fieldName] = $element[$fieldName] === '' ? null : $element[$fieldName]; } } unset($fieldName, $index, $value); Product\SystemField::prepareRow($result, Product\SystemField::OPERATION_IMPORT); } if (isset($element['MEASURE'])) { $result['MEASURE'] = ($element['MEASURE'] === '' ? null : (int)$element['MEASURE']); } foreach ($this->productSizes as $fieldName) { if (isset($element[$fieldName])) { $result[$fieldName] = $element[$fieldName] === '' ? null : $element[$fieldName]; } } unset($fieldName); return $result; } function ImportElementPrices($arXMLElement, &$counter, $arParent = false) { /** @global CMain $APPLICATION */ global $APPLICATION; static $catalogs = array(); $arElement = array( "ID" => 0, "XML_ID" => $arXMLElement[$this->mess["IBLOCK_XML2_ID"]], ); $hashPosition = strrpos($arElement["XML_ID"], "#"); if ( $this->use_offers && $hashPosition === false && !$this->force_offers && isset($this->PROPERTY_MAP["CML2_LINK"]) && isset($this->arProperties[$this->PROPERTY_MAP["CML2_LINK"]]) ) { $IBLOCK_ID = $this->arProperties[$this->PROPERTY_MAP["CML2_LINK"]]["LINK_IBLOCK_ID"]; if (!isset($catalogs[$IBLOCK_ID])) { $catalogs[$IBLOCK_ID] = true; $rs = CCatalog::GetList(array(),array("IBLOCK_ID" => $IBLOCK_ID)); if (!$rs->Fetch()) { $obCatalog = new CCatalog(); $boolFlag = $obCatalog->Add(array( "IBLOCK_ID" => $IBLOCK_ID, "YANDEX_EXPORT" => "N", "SUBSCRIPTION" => "N", )); if (!$boolFlag) { if ($ex = $APPLICATION->GetException()) $this->LAST_ERROR = $ex->GetString(); return 0; } } } } else { $IBLOCK_ID = $this->next_step["IBLOCK_ID"]; } $obElement = new CIBlockElement; $rsElement = $obElement->GetList( Array("ID"=>"asc"), Array("=XML_ID" => $arElement["XML_ID"], "IBLOCK_ID" => $IBLOCK_ID), false, false, Array("ID", "TMP_ID", "ACTIVE") ); $arDBElement = $rsElement->Fetch(); if($arDBElement) $arElement["ID"] = $arDBElement["ID"]; if(isset($arXMLElement[$this->mess["IBLOCK_XML2_STORE_AMOUNT_LIST"]])) { $arElement["STORE_AMOUNT"] = array(); foreach($arXMLElement[$this->mess["IBLOCK_XML2_STORE_AMOUNT_LIST"]] as $storeAmount) { if(isset($storeAmount[$this->mess["IBLOCK_XML2_STORE_ID"]])) { $storeXMLID = $storeAmount[$this->mess["IBLOCK_XML2_STORE_ID"]]; $amount = $this->ToFloat($storeAmount[$this->mess["IBLOCK_XML2_AMOUNT"]]); $arElement["STORE_AMOUNT"][$storeXMLID] = $amount; } } } elseif(isset($arXMLElement[$this->mess["IBLOCK_XML2_RESTS"]])) { $arElement["STORE_AMOUNT"] = array(); foreach($arXMLElement[$this->mess["IBLOCK_XML2_RESTS"]] as $xmlRest) { foreach($xmlRest as $storeAmount) { if(is_array($storeAmount)) { if (isset($storeAmount[$this->mess["IBLOCK_XML2_ID"]])) { $storeXMLID = $storeAmount[$this->mess["IBLOCK_XML2_ID"]]; $amount = $this->ToFloat($storeAmount[$this->mess["IBLOCK_XML2_AMOUNT"]]); $arElement["STORE_AMOUNT"][$storeXMLID] = $amount; } } else { if ($storeAmount <> '') { $amount = $this->ToFloat($storeAmount); $arElement["QUANTITY"] = $amount; } } } } } elseif( $arParent && ( array_key_exists($this->mess["IBLOCK_XML2_STORES"], $arXMLElement) || array_key_exists($this->mess["IBLOCK_XML2_STORE"], $arXMLElement) ) ) { $arElement["STORE_AMOUNT"] = array(); $rsStores = $this->_xml_file->GetList( array("ID" => "asc"), array( "><LEFT_MARGIN" => array($arParent["LEFT_MARGIN"], $arParent["RIGHT_MARGIN"]), "NAME" => $this->mess["IBLOCK_XML2_STORE"], ), array("ID", "ATTRIBUTES") ); while ($arStore = $rsStores->Fetch()) { if($arStore["ATTRIBUTES"] <> '') { $info = unserialize($arStore["ATTRIBUTES"], ['allowed_classes' => false]); if( is_array($info) && array_key_exists($this->mess["IBLOCK_XML2_STORE_ID"], $info) && array_key_exists($this->mess["IBLOCK_XML2_STORE_AMOUNT"], $info) ) { $arElement["STORE_AMOUNT"][$info[$this->mess["IBLOCK_XML2_STORE_ID"]]] = $this->ToFloat($info[$this->mess["IBLOCK_XML2_STORE_AMOUNT"]]); } } } } if(isset($arElement["STORE_AMOUNT"])) $this->ImportStoresAmount($arElement["STORE_AMOUNT"], $arElement["ID"], $counter); if($arDBElement) { $arProduct = array( "ID" => $arElement["ID"], ); if(isset($arXMLElement[$this->mess["IBLOCK_XML2_PRICES"]])) { $arElement["PRICES"] = array(); foreach($arXMLElement[$this->mess["IBLOCK_XML2_PRICES"]] as $price) { if( isset($price[$this->mess["IBLOCK_XML2_PRICE_TYPE_ID"]]) && array_key_exists($price[$this->mess["IBLOCK_XML2_PRICE_TYPE_ID"]], $this->PRICES_MAP) ) { $price["PRICE"] = $this->PRICES_MAP[$price[$this->mess["IBLOCK_XML2_PRICE_TYPE_ID"]]]; $arElement["PRICES"][] = $price; if( array_key_exists($this->mess["IBLOCK_XML2_MEASURE"], $price) && !isset($arProduct["MEASURE"]) ) { $tmp = $this->convertBaseUnitFromXmlToPropertyValue($price[$this->mess["IBLOCK_XML2_MEASURE"]]); if ($tmp["DESCRIPTION"] > 0) $arProduct["MEASURE"] = $tmp["DESCRIPTION"]; } } } $arElement["DISCOUNTS"] = array(); if(isset($arXMLElement[$this->mess["IBLOCK_XML2_DISCOUNTS"]])) { foreach($arXMLElement[$this->mess["IBLOCK_XML2_DISCOUNTS"]] as $discount) { if( isset($discount[$this->mess["IBLOCK_XML2_DISCOUNT_CONDITION"]]) && $discount[$this->mess["IBLOCK_XML2_DISCOUNT_CONDITION"]] === $this->mess["IBLOCK_XML2_DISCOUNT_COND_VOLUME"] ) { $discount_value = $this->ToInt($discount[$this->mess["IBLOCK_XML2_DISCOUNT_COND_VALUE"]]); $discount_percent = $this->ToFloat($discount[$this->mess["IBLOCK_XML2_DISCOUNT_COND_PERCENT"]]); if($discount_value > 0 && $discount_percent > 0) $arElement["DISCOUNTS"][$discount_value] = $discount_percent; } } } } if($this->bCatalog && array_key_exists($this->mess["IBLOCK_XML2_AMOUNT"], $arXMLElement)) { $arElement["QUANTITY_RESERVED"] = 0; if($arElement["ID"]) { $iterator = Catalog\Model\Product::getList([ 'select' => ['ID', 'QUANTITY_RESERVED'], 'filter' => ['=ID' => $arDBElement['ID']] ]); $arElementTmp = $iterator->fetch(); if (!empty($arElementTmp) && is_array($arElementTmp) && isset($arElementTmp["QUANTITY_RESERVED"])) $arElement["QUANTITY_RESERVED"] = (float)$arElementTmp["QUANTITY_RESERVED"]; unset($arElementTmp); unset($iterator); } $arElement["QUANTITY"] = $this->ToFloat($arXMLElement[$this->mess["IBLOCK_XML2_AMOUNT"]]) - $arElement["QUANTITY_RESERVED"]; } if(isset($arElement["PRICES"]) && $this->bCatalog) { if(isset($arElement["QUANTITY"])) $arProduct["QUANTITY"] = (float)$arElement["QUANTITY"]; elseif(isset($arElement["STORE_AMOUNT"]) && !empty($arElement["STORE_AMOUNT"])) $arProduct["QUANTITY"] = $this->countTotalQuantity($arElement["STORE_AMOUNT"]); $rsWeight = CIBlockElement::GetProperty($IBLOCK_ID, $arElement["ID"], array(), array("CODE" => "CML2_TRAITS")); while($arWeight = $rsWeight->Fetch()) { if($arWeight["DESCRIPTION"] == $this->mess["IBLOCK_XML2_WEIGHT"]) $arProduct["WEIGHT"] = $this->ToFloat($arWeight["VALUE"])*1000; } $rsUnit = CIBlockElement::GetProperty($IBLOCK_ID, $arElement["ID"], array(), array("CODE" => "CML2_BASE_UNIT")); while($arUnit = $rsUnit->Fetch()) { if($arUnit["DESCRIPTION"] > 0) $arProduct["MEASURE"] = $arUnit["DESCRIPTION"]; } //Here start VAT handling //Check if all the taxes exists in BSM catalog $arTaxMap = array(); $rsTaxProperty = CIBlockElement::GetProperty($IBLOCK_ID, $arElement["ID"], array("sort" => "asc"), array("CODE" => "CML2_TAXES")); while($arTaxProperty = $rsTaxProperty->Fetch()) { if( $arTaxProperty["DESCRIPTION"] <> '' && !array_key_exists($arTaxProperty["DESCRIPTION"], $arTaxMap) ) { if ($arTaxProperty["VALUE"] === '' || !is_numeric($arTaxProperty["VALUE"])) { $taxValue = null; } else { $taxValue = $this->ToFloat($arTaxProperty["VALUE"]); } $arTaxMap[$arTaxProperty["DESCRIPTION"]] = array( "RATE" => $this->ToFloat($arTaxProperty["VALUE"]), "ID" => $this->CheckTax($arTaxProperty["DESCRIPTION"], $taxValue), ); } } //Try to search in main element if ( !$arTaxMap && $this->use_offers && $hashPosition !== false && isset($this->PROPERTY_MAP["CML2_LINK"]) && $this->arProperties[$this->PROPERTY_MAP["CML2_LINK"]]["LINK_IBLOCK_ID"] > 0 ) { $rsLinkProperty = CIBlockElement::GetProperty($IBLOCK_ID, $arElement["ID"], array("sort" => "asc"), array("CODE" => "CML2_LINK")); if( ($arLinkProperty = $rsLinkProperty->Fetch()) && ($arLinkProperty["VALUE"] > 0)) { $rsTaxProperty = CIBlockElement::GetProperty($this->arProperties[$this->PROPERTY_MAP["CML2_LINK"]]["LINK_IBLOCK_ID"], $arLinkProperty["VALUE"], array("sort" => "asc"), array("CODE" => "CML2_TAXES")); while($arTaxProperty = $rsTaxProperty->Fetch()) { if( $arTaxProperty["DESCRIPTION"] <> '' && !array_key_exists($arTaxProperty["DESCRIPTION"], $arTaxMap) ) { if ($arTaxProperty["VALUE"] === '' || !is_numeric($arTaxProperty["VALUE"])) { $taxValue = null; } else { $taxValue = $this->ToFloat($arTaxProperty["VALUE"]); } $arTaxMap[$arTaxProperty["DESCRIPTION"]] = array( "RATE" => $this->ToFloat($arTaxProperty["VALUE"]), "ID" => $this->CheckTax($arTaxProperty["DESCRIPTION"], $taxValue), ); } } } } //First find out if all the prices have TAX_IN_SUM true $TAX_IN_SUM = "Y"; foreach($arElement["PRICES"] as $price) { if($price["PRICE"]["TAX_IN_SUM"] !== "true") { $TAX_IN_SUM = "N"; break; } } //If there was found not included tax we'll make sure //that all prices has the same flag if($TAX_IN_SUM === "N") { foreach($arElement["PRICES"] as $price) { if($price["PRICE"]["TAX_IN_SUM"] !== "false") { $TAX_IN_SUM = "Y"; break; } } //Check if there is a mix of tax in sum //and correct it by recalculating all the prices if($TAX_IN_SUM === "Y") { foreach($arElement["PRICES"] as $key=>$price) { if($price["PRICE"]["TAX_IN_SUM"] !== "true") { $TAX_NAME = $price["PRICE"]["TAX_NAME"]; if(array_key_exists($TAX_NAME, $arTaxMap)) { $PRICE_WO_TAX = $this->ToFloat($price[$this->mess["IBLOCK_XML2_PRICE_FOR_ONE"]]); $PRICE = $PRICE_WO_TAX + ($PRICE_WO_TAX / 100.0 * $arTaxMap[$TAX_NAME]["RATE"]); $arElement["PRICES"][$key][$this->mess["IBLOCK_XML2_PRICE_FOR_ONE"]] = $PRICE; } } } } } if ($TAX_IN_SUM == "Y" && $arTaxMap) { $vat = current($arTaxMap); $arProduct["VAT_ID"] = $vat["ID"]; } else { foreach($arElement["PRICES"] as $price) { $TAX_NAME = $price["PRICE"]["TAX_NAME"]; if(array_key_exists($TAX_NAME, $arTaxMap)) { $arProduct["VAT_ID"] = $arTaxMap[$TAX_NAME]["ID"]; break; } } } $arProduct["VAT_INCLUDED"] = $TAX_IN_SUM; $productCache = Catalog\Model\Product::getCacheItem($arProduct['ID'], true); if (!empty($productCache)) { $productResult = Catalog\Model\Product::update( $arProduct['ID'], array( 'fields' => $arProduct, 'external_fields' => array( 'IBLOCK_ID' => $IBLOCK_ID ) ) ); } else { $productResult = Catalog\Model\Product::add( array( 'fields' => $arProduct, 'external_fields' => array( 'IBLOCK_ID' => $IBLOCK_ID ) ) ); } if ($productResult->isSuccess()) { //TODO: replace this code after upload measure ratio from 1C $iterator = \Bitrix\Catalog\MeasureRatioTable::getList(array( 'select' => array('ID'), 'filter' => array('=PRODUCT_ID' => $arElement['ID']) )); $ratioRow = $iterator->fetch(); if (empty($ratioRow)) { $ratioResult = \Bitrix\Catalog\MeasureRatioTable::add(array( 'PRODUCT_ID' => $arElement['ID'], 'RATIO' => 1, 'IS_DEFAULT' => 'Y' )); unset($ratioResult); } unset($ratioRow, $iterator); } $this->SetProductPrice($arElement["ID"], $arElement["PRICES"], $arElement["DISCOUNTS"]); \Bitrix\Iblock\PropertyIndex\Manager::updateElementIndex($IBLOCK_ID, $arElement["ID"]); } elseif( $this->bCatalog && ( (isset($arElement["STORE_AMOUNT"]) && !empty($arElement["STORE_AMOUNT"])) || isset($arElement["QUANTITY"]) ) ) { $iterator = Catalog\Model\Product::getList([ 'select' => ['ID', 'QUANTITY_RESERVED'], 'filter' => ['=ID' => $arElement['ID']] ]); $arElementTmp = $iterator->fetch(); if (!empty($arElementTmp) && is_array($arElementTmp)) { $quantityReserved = 0; if (isset($arElementTmp["QUANTITY_RESERVED"])) $quantityReserved = (float)$arElementTmp["QUANTITY_RESERVED"]; $internalFields = []; if (isset($arElement["STORE_AMOUNT"]) && !empty($arElement["STORE_AMOUNT"])) { $internalFields['QUANTITY'] = $this->countTotalQuantity($arElement["STORE_AMOUNT"]); } elseif (isset($arElement["QUANTITY"])) { $internalFields['QUANTITY'] = $arElement["QUANTITY"]; } if (!empty($internalFields)) { $internalFields['QUANTITY'] -= $quantityReserved; $internalResult = Catalog\Model\Product::update( $arElement['ID'], array( 'fields' => $internalFields, 'external_fields' => array( 'IBLOCK_ID' => $IBLOCK_ID ) ) ); if (!$internalResult->isSuccess()) { } unset($internalResult); } unset($internalFields); unset($quantityReserved); } unset($arElementTmp); unset($iterator); } } $counter["UPD"]++; return $arElement["ID"]; } function fillDefaultPropertyValues(&$arElement, $iblockProperties) { if (isset($arElement["PROPERTY_VALUES"])) { $elementProperties = &$arElement["PROPERTY_VALUES"]; foreach ($iblockProperties as $PID => $property) { if (!array_key_exists($PID, $elementProperties)) { if ($property["PROPERTY_TYPE"] == "L") { $enumDefaults = CIBlockPropertyEnum::GetList(array(), array( "PROPERTY_ID" => $PID, "DEF" => "Y", )); $i = 0; while($enum = $enumDefaults->Fetch()) { $elementProperties[$PID]["n".$i] = $enum["ID"]; $i++; } } elseif (is_array($property["DEFAULT_VALUE"]) || $property["DEFAULT_VALUE"] <> '') { $elementProperties[$PID]["n0"] = array( "VALUE" => $property["DEFAULT_VALUE"], "DESCRIPTION" => "", ); } } } } } function ConvertDiscounts($arDiscounts) { if (is_array($arDiscounts) && count($arDiscounts) > 0) { if (!array_key_exists(0, $arDiscounts)) $arDiscounts[0] = 0; ksort($arDiscounts); $keys = array_keys($arDiscounts); $cnt = count($keys); for ($i = 0; $i < $cnt; $i++) { $arDiscounts[$keys[$i]] = array( "QUANTITY_FROM" => $keys[$i] + 1, "QUANTITY_TO" => $i < $cnt ? $keys[$i + 1] : "", "PERCENT" => $arDiscounts[$keys[$i]], ); } } else { $arDiscounts = array( array( "QUANTITY_FROM" => "", "QUANTITY_TO" => "", "PERCENT" => 0, ), ); } return $arDiscounts; } /** * @param int $PRODUCT_ID * @param array $arPrices * @param bool|array $arDiscounts */ function SetProductPrice($PRODUCT_ID, $arPrices, $arDiscounts = false) { $arDBPrices = array(); $iterator = Catalog\Model\Price::getList(array( 'select' => array( 'ID', 'PRODUCT_ID', 'CATALOG_GROUP_ID', 'QUANTITY_FROM', 'QUANTITY_TO' ), 'filter' => array('=PRODUCT_ID' => $PRODUCT_ID) )); while ($row = $iterator->fetch()) { $arDBPrices[$row["CATALOG_GROUP_ID"].":".$row["QUANTITY_FROM"].":".$row["QUANTITY_TO"]] = $row["ID"]; } $arToDelete = $arDBPrices; if(!is_array($arPrices)) $arPrices = array(); foreach($arPrices as $price) { if(!isset($price[$this->mess["IBLOCK_XML2_CURRENCY"]])) $price[$this->mess["IBLOCK_XML2_CURRENCY"]] = $price["PRICE"]["CURRENCY"]; $arPrice = Array( "PRODUCT_ID" => $PRODUCT_ID, "CATALOG_GROUP_ID" => $price["PRICE"]["ID"], "^PRICE" => $this->ToFloat($price[$this->mess["IBLOCK_XML2_PRICE_FOR_ONE"]]), "CURRENCY" => $this->CheckCurrency($price[$this->mess["IBLOCK_XML2_CURRENCY"]]), ); if ( (isset($price[$this->mess["IBLOCK_XML2_QUANTITY_FROM"]]) && (string)$price[$this->mess["IBLOCK_XML2_QUANTITY_FROM"]] != '') || (isset($price[$this->mess["IBLOCK_XML2_QUANTITY_TO"]]) && (string)$price[$this->mess["IBLOCK_XML2_QUANTITY_TO"]] != '') ) { $arPrice["QUANTITY_FROM"] = $price[$this->mess["IBLOCK_XML2_QUANTITY_FROM"]]; $arPrice["QUANTITY_TO"] = $price[$this->mess["IBLOCK_XML2_QUANTITY_TO"]]; $arPrice["PRICE"] = $arPrice["^PRICE"]; unset($arPrice["^PRICE"]); if ($arPrice["QUANTITY_FROM"] === '' || $arPrice["QUANTITY_FROM"] === false || $arPrice["QUANTITY_FROM"] === '0' || $arPrice["QUANTITY_FROM"] === 0 ) $arPrice["QUANTITY_FROM"] = null; if ($arPrice["QUANTITY_TO"] === '' || $arPrice["QUANTITY_TO"] === false || $arPrice["QUANTITY_TO"] === '0' || $arPrice["QUANTITY_TO"] === 0 ) $arPrice["QUANTITY_TO"] = null; $id = $arPrice["CATALOG_GROUP_ID"].":".$arPrice["QUANTITY_FROM"].":".$arPrice["QUANTITY_TO"]; if(isset($arDBPrices[$id])) { $priceResult = Catalog\Model\Price::update($arDBPrices[$id], $arPrice); unset($arToDelete[$id]); } else { $priceResult = Catalog\Model\Price::add($arPrice); } } else { foreach($this->ConvertDiscounts($arDiscounts) as $arDiscount) { $arPrice["QUANTITY_FROM"] = $arDiscount["QUANTITY_FROM"]; $arPrice["QUANTITY_TO"] = $arDiscount["QUANTITY_TO"]; if($arDiscount["PERCENT"] > 0) $arPrice["PRICE"] = $arPrice["^PRICE"] - $arPrice["^PRICE"]/100*$arDiscount["PERCENT"]; else $arPrice["PRICE"] = $arPrice["^PRICE"]; unset($arPrice["^PRICE"]); if ($arPrice["QUANTITY_FROM"] === '' || $arPrice["QUANTITY_FROM"] === false || $arPrice["QUANTITY_FROM"] === '0' || $arPrice["QUANTITY_FROM"] === 0 ) $arPrice["QUANTITY_FROM"] = null; if ($arPrice["QUANTITY_TO"] === '' || $arPrice["QUANTITY_TO"] === false || $arPrice["QUANTITY_TO"] === '0' || $arPrice["QUANTITY_TO"] === 0 ) $arPrice["QUANTITY_TO"] = null; $id = $arPrice["CATALOG_GROUP_ID"].":".$arPrice["QUANTITY_FROM"].":".$arPrice["QUANTITY_TO"]; if(isset($arDBPrices[$id])) { $priceResult = Catalog\Model\Price::update($arDBPrices[$id], $arPrice); unset($arToDelete[$id]); } else { $priceResult = Catalog\Model\Price::add($arPrice); } } } } foreach($arToDelete as $id) { $priceResult = Catalog\Model\Price::delete($id); } } function ImportSection($xml_tree_id, $IBLOCK_ID, $parent_section_id) { /** @var CUserTypeManager $USER_FIELD_MANAGER */ global $USER_FIELD_MANAGER; /** @var CDatabase $DB */ global $DB; static $arUserFields; if($parent_section_id === false) { $arUserFields = array(); foreach($USER_FIELD_MANAGER->GetUserFields("IBLOCK_".$IBLOCK_ID."_SECTION") as $FIELD_ID => $arField) { if($arField["XML_ID"] == '') $arUserFields[$FIELD_ID] = $arField; else $arUserFields[$arField["XML_ID"]] = $arField; } } $this->next_step["section_sort"] += 10; $arSection = array( "IBLOCK_SECTION_ID" => $parent_section_id, "ACTIVE" => "Y", ); $rsS = $this->_xml_file->GetList( array("ID" => "asc"), array("PARENT_ID" => $xml_tree_id) ); $XML_SECTIONS_PARENT = false; $XML_PROPERTIES_PARENT = false; $XML_SECTION_PROPERTIES = false; $deletedStatus = false; while($arS = $rsS->Fetch()) { if(isset($arS["VALUE_CLOB"])) $arS["VALUE"] = $arS["VALUE_CLOB"]; if($arS["NAME"]==$this->mess["IBLOCK_XML2_ID"]) $arSection["XML_ID"] = $arS["VALUE"]; elseif($arS["NAME"]==$this->mess["IBLOCK_XML2_NAME"]) $arSection["NAME"] = $arS["VALUE"]; elseif($arS["NAME"]==$this->mess["IBLOCK_XML2_DESCRIPTION"]) { $arSection["DESCRIPTION"] = $arS["VALUE"]; $arSection["DESCRIPTION_TYPE"] = "html"; } elseif($arS["NAME"]==$this->mess["IBLOCK_XML2_GROUPS"]) $XML_SECTIONS_PARENT = $arS["ID"]; elseif($arS["NAME"]==$this->mess["IBLOCK_XML2_PROPERTIES_VALUES"]) $XML_PROPERTIES_PARENT = $arS["ID"]; elseif($arS["NAME"]==$this->mess["IBLOCK_XML2_BX_SORT"]) $arSection["SORT"] = intval($arS["VALUE"]); elseif($arS["NAME"]==$this->mess["IBLOCK_XML2_BX_CODE"]) $arSection["CODE"] = $arS["VALUE"]; elseif($arS["NAME"] == $this->mess["IBLOCK_XML2_BX_PICTURE"]) { if($arS["VALUE"] <> '') $arSection["PICTURE"] = $this->MakeFileArray($arS["VALUE"]); else $arSection["PICTURE"] = $this->MakeFileArray($this->_xml_file->GetAllChildrenArray($arS["ID"])); } elseif($arS["NAME"] == $this->mess["IBLOCK_XML2_BX_DETAIL_PICTURE"]) { if($arS["VALUE"] <> '') $arSection["DETAIL_PICTURE"] = $this->MakeFileArray($arS["VALUE"]); else $arSection["DETAIL_PICTURE"] = $this->MakeFileArray($this->_xml_file->GetAllChildrenArray($arS["ID"])); } elseif($arS["NAME"] == $this->mess["IBLOCK_XML2_BX_ACTIVE"]) $arSection["ACTIVE"] = ($arS["VALUE"]=="true") || intval($arS["VALUE"])? "Y": "N"; elseif($arS["NAME"] == $this->mess["IBLOCK_XML2_SECTION_PROPERTIES"]) $XML_SECTION_PROPERTIES = $arS["ID"]; elseif($arS["NAME"] == $this->mess["IBLOCK_XML2_STATUS"]) $deletedStatus = $arS["VALUE"] === $this->mess["IBLOCK_XML2_DELETED"]; elseif($arS["NAME"] == $this->mess["IBLOCK_XML2_INHERITED_TEMPLATES"]) { $arSection["IPROPERTY_TEMPLATES"] = array(); $arTemplates = $this->_xml_file->GetAllChildrenArray($arS["ID"]); foreach($arTemplates as $TEMPLATE) { $id = $TEMPLATE[$this->mess["IBLOCK_XML2_ID"]]; $template = $TEMPLATE[$this->mess["IBLOCK_XML2_VALUE"]]; if($id <> '' && $template <> '') $arSection["IPROPERTY_TEMPLATES"][$id] = $template; } } elseif($arS["NAME"] == $this->mess["IBLOCK_XML2_DELETE_MARK"]) { $arSection["ACTIVE"] = ($arS["VALUE"]=="true") || intval($arS["VALUE"])? "N": "Y"; } } if ($deletedStatus) { $obSection = new CIBlockSection; $rsSection = $obSection->GetList(array(), array( "IBLOCK_ID" => $IBLOCK_ID, "XML_ID" => $arSection["XML_ID"], ), false, array("ID")); if($arDBSection = $rsSection->Fetch()) { $obSection->Update($arDBSection["ID"], array( "ACTIVE" => "N", )); $this->_xml_file->Add(array("PARENT_ID" => 0, "LEFT_MARGIN" => $arDBSection["ID"])); } return true; } if($XML_PROPERTIES_PARENT) { $rs = $this->_xml_file->GetList( array("ID" => "asc"), array("PARENT_ID" => $XML_PROPERTIES_PARENT), array("ID") ); while($ar = $rs->Fetch()) { $arXMLProp = $this->_xml_file->GetAllChildrenArray($ar["ID"]); if( array_key_exists($this->mess["IBLOCK_XML2_ID"], $arXMLProp) && array_key_exists($arXMLProp[$this->mess["IBLOCK_XML2_ID"]], $arUserFields) ) { $arUserField = $arUserFields[$arXMLProp[$this->mess["IBLOCK_XML2_ID"]]]; unset($arXMLProp[$this->mess["IBLOCK_XML2_ID"]]); $arProp = array(); $i = 0; foreach($arXMLProp as $value) { if($arUserField["USER_TYPE"]["BASE_TYPE"] === "file") $arProp["n".($i++)] = $this->MakeFileArray($value); elseif($arUserField["USER_TYPE"]["BASE_TYPE"] === "enum") $arProp["n".($i++)] = $this->GetSectionEnumByXML_ID($arUserField["ID"], $value); else $arProp["n".($i++)] = $value; } if($arUserField["MULTIPLE"] == "N") $arSection[$arUserField["FIELD_NAME"]] = array_pop($arProp); else $arSection[$arUserField["FIELD_NAME"]] = $arProp; } } } $obSection = new CIBlockSection; $rsSection = $obSection->GetList(array(), array("IBLOCK_ID"=>$IBLOCK_ID, "XML_ID"=>$arSection["XML_ID"]), false); if($arDBSection = $rsSection->Fetch()) { if( !array_key_exists("CODE", $arSection) && is_array($this->translit_on_update) ) { $CODE = CUtil::translit($arSection["NAME"], LANGUAGE_ID, $this->translit_on_update); $CODE = $this->CheckSectionCode($IBLOCK_ID, $arDBSection["ID"], $CODE); if ($CODE !== false) $arSection["CODE"] = $CODE; } $bChanged = false; foreach($arSection as $key=>$value) { if(is_array($arDBSection[$key]) || ($arDBSection[$key] != $value)) { $bChanged = true; break; } } if($bChanged) { foreach($arUserFields as $arField1) { if($arField1["USER_TYPE"]["BASE_TYPE"] == "file") { $sectionUF = $USER_FIELD_MANAGER->GetUserFields("IBLOCK_".$IBLOCK_ID."_SECTION", $arDBSection["ID"]); foreach($sectionUF as $arField2) { if( $arField2["USER_TYPE"]["BASE_TYPE"] == "file" && isset($arSection[$arField2["FIELD_NAME"]]) ) { if($arField2["MULTIPLE"] == "Y" && is_array($arField2["VALUE"])) { foreach($arField2["VALUE"] as $old_file_id) $arSection[$arField2["FIELD_NAME"]][] = array("del"=>true,"old_id"=>$old_file_id); } elseif($arField2["MULTIPLE"] == "N" && $arField2["VALUE"] > 0) { $arSection[$arField2["FIELD_NAME"]]["old_id"] = $arField2["VALUE"]; } } } break; } } if (!isset($arSection['MODIFIED_BY']) || (int)$arSection['MODIFIED_BY'] <= 0) { if ($this->currentUserId > 0) { $arSection['MODIFIED_BY'] = $this->currentUserId; } } $res = $obSection->Update($arDBSection["ID"], $arSection); if(!$res) { $this->LAST_ERROR = $obSection->LAST_ERROR; return $this->LAST_ERROR; } } else { $strUpdate = "TIMESTAMP_X = ".$DB->CurrentTimeFunction(); if ($this->currentUserId > 0) $strUpdate .= ", MODIFIED_BY=".$this->currentUserId; $DB->Query("UPDATE b_iblock_section SET ".$strUpdate." WHERE ID=".$arDBSection["ID"]); unset($strUpdate); } $arSection["ID"] = $arDBSection["ID"]; } else { if(!array_key_exists("CODE", $arSection) && is_array($this->translit_on_add)) { $CODE = CUtil::translit($arSection["NAME"], LANGUAGE_ID, $this->translit_on_add); $CODE = $this->CheckSectionCode($IBLOCK_ID, 0, $CODE); if ($CODE !== false) $arSection["CODE"] = $CODE; } $arSection["IBLOCK_ID"] = $IBLOCK_ID; if(!isset($arSection["SORT"])) $arSection["SORT"] = $this->next_step["section_sort"]; $arSection["ID"] = $obSection->Add($arSection); if(!$arSection["ID"]) { $this->LAST_ERROR = $obSection->LAST_ERROR; return $this->LAST_ERROR; } } if($XML_SECTION_PROPERTIES) { $this->ImportSectionProperties($XML_SECTION_PROPERTIES, $IBLOCK_ID, $arSection["ID"]); } //Clear seo cache if(isset($bChanged) && $bChanged) { $ipropValues = new \Bitrix\Iblock\InheritedProperty\SectionValues($this->next_step["IBLOCK_ID"], $arSection["ID"]); $ipropValues->clearValues(); } if($arSection["ID"]) { $this->_xml_file->Add(array("PARENT_ID" => 0, "LEFT_MARGIN" => $arSection["ID"])); } if($XML_SECTIONS_PARENT) { $rs = $this->_xml_file->GetList( array("ID" => "asc"), array("PARENT_ID" => $XML_SECTIONS_PARENT), array("ID") ); while($ar = $rs->Fetch()) { $result = $this->ImportSection($ar["ID"], $IBLOCK_ID, $arSection["ID"]); if($result !== true) return $result; } } return true; } function CheckElementCode($IBLOCK_ID, $ID, $CODE) { $arCodes = array(); $rsCodeLike = CIBlockElement::GetList(array(), array( "IBLOCK_ID" => $IBLOCK_ID, "CODE" => $CODE."%", ), false, false, array("ID", "CODE")); while($ar = $rsCodeLike->Fetch()) { if ($ID == $ar["ID"]) return false; $arCodes[$ar["CODE"]] = true; } if (array_key_exists($CODE, $arCodes)) { $i = 1; while(array_key_exists($CODE."_".$i, $arCodes)) $i++; return $CODE."_".$i; } else { return $CODE; } } function CheckSectionCode($IBLOCK_ID, $ID, $CODE) { $arCodes = array(); $rsCodeLike = CIBlockSection::GetList(array(), array( "IBLOCK_ID" => $IBLOCK_ID, "CODE" => $CODE."%", ), false, array("ID", "CODE")); while($ar = $rsCodeLike->Fetch()) { if ($ID == $ar["ID"]) return false; $arCodes[$ar["CODE"]] = true; } if (array_key_exists($CODE, $arCodes)) { $i = 1; while(array_key_exists($CODE."_".$i, $arCodes)) $i++; return $CODE."_".$i; } else { return $CODE; } } function DeactivateElement($action, $start_time, $interval) { $counter = array( "DEL" => 0, "DEA" => 0, "NON" => 0, ); if(array_key_exists("bUpdateOnly", $this->next_step) && $this->next_step["bUpdateOnly"]) return $counter; if($action!="D" && $action!="A") return $counter; $bDelete = $action=="D"; //This will protect us from deactivating when next_step is lost $IBLOCK_ID = intval($this->next_step["IBLOCK_ID"]); if($IBLOCK_ID < 1) return $counter; $arFilter = array( ">ID" => $this->next_step["LAST_ID"], "IBLOCK_ID" => $IBLOCK_ID, ); if(!$bDelete) $arFilter["ACTIVE"] = "Y"; $obElement = new CIBlockElement; $rsElement = $obElement->GetList( Array("ID"=>"asc"), $arFilter, false, false, Array("ID", "ACTIVE") ); while($arElement = $rsElement->Fetch()) { $rs = $this->_xml_file->GetList( array(), array("PARENT_ID+0" => 0, "LEFT_MARGIN" => $arElement["ID"]), array("ID") ); $ar = $rs->Fetch(); if(!$ar) { if($bDelete) { $obElement->Delete($arElement["ID"]); $counter["DEL"]++; } else { $elementFields = array("ACTIVE"=>"N"); if ((string)\Bitrix\Main\Config\Option::get('iblock', 'change_user_by_group_active_modify') === 'Y') { $elementFields['MODIFIED_BY'] = $this->currentUserId; } $obElement->Update($arElement["ID"], $elementFields); $counter["DEA"]++; } } else { $counter["NON"]++; } $this->next_step["LAST_ID"] = $arElement["ID"]; if($interval > 0 && (time()-$start_time) > $interval) break; } return $counter; } /** * @param array $counters * @return int */ public function updateCounters(array $counters): int { $result = 0; if (!isset($this->next_step["DONE"])) $this->next_step["DONE"] = []; foreach ($counters as $index => $value) { if (!isset($this->next_step["DONE"][$index])) $this->next_step["DONE"][$index] = 0; $value = (int)$value; $this->next_step["DONE"][$index] += $value; $result += $value; } unset($index, $value); return $result; } /** * @param bool $description * @return array */ public static function getIblockCacheModeList(bool $description = false): array { if ($description) { return array( self::IBLOCK_CACHE_NORMAL => GetMessage('IBLOCK_XML2_IBLOCK_CACHE_MODE_NORMAL'), self::IBLOCK_CACHE_HIT => GetMessage('IBLOCK_XML2_IBLOCK_CACHE_MODE_HIT'), self::IBLOCK_CACHE_FINAL => GetMessage('IBLOCK_XML2_IBLOCK_CACHE_MODE_FINAL'), self::IBLOCK_CACHE_FREEZE => GetMessage('IBLOCK_XML2_IBLOCK_CACHE_MODE_FREEZE') ); } return array( self::IBLOCK_CACHE_NORMAL, self::IBLOCK_CACHE_HIT, self::IBLOCK_CACHE_FINAL, self::IBLOCK_CACHE_FREEZE ); } /** * @return void */ public function freezeIblockCache(): void { if ( isset($this->next_step['IBLOCK_ID']) && $this->next_step['IBLOCK_ID'] > 0 && !$this->isIblockCacheModeNormal() ) { CIBlock::disableClearTagCache(); } } /** * @return void */ public function unFreezeIblockCache(): void { if ( isset($this->next_step['IBLOCK_ID']) && $this->next_step['IBLOCK_ID'] > 0 && !$this->isIblockCacheModeNormal() ) { CIBlock::enableClearTagCache(); } } /** * @return void */ public function clearIblockCacheOnHit(): void { if ( !isset($this->next_step['IBLOCK_ID']) || $this->next_step['IBLOCK_ID'] <= 0 || !$this->isIblockCacheModeHit() ) { return; } CIBlock::clearIblockTagCache($this->next_step['IBLOCK_ID']); } /** * @return void */ public function clearIblockCacheAfterFinal(): void { if ( !isset($this->next_step['IBLOCK_ID']) || $this->next_step['IBLOCK_ID'] <= 0 || !$this->isIblockCacheModeFinal() ) { return; } CIBlock::clearIblockTagCache($this->next_step['IBLOCK_ID']); } /** * @return string */ public function getIblockCacheMode(): string { return $this->iblockCacheMode; } /** * @return bool */ public function isIblockCacheModeNormal(): bool { return $this->getIblockCacheMode() === self::IBLOCK_CACHE_NORMAL; } /** * @return bool */ public function isIblockCacheModeHit(): bool { return $this->getIblockCacheMode() === self::IBLOCK_CACHE_HIT; } /** * @return bool */ public function isIblockCacheModeFinal(): bool { return $this->getIblockCacheMode() === self::IBLOCK_CACHE_FINAL; } /** * @return bool */ public function isIblockCacheModeFreeze(): bool { return $this->getIblockCacheMode() === self::IBLOCK_CACHE_FREEZE; } /** * Returns a external codes list of warehouses. * * @return array */ protected function getStoreList(): array { $result = array(); if ($this->bCatalog) { $iterator = Catalog\StoreTable::getList(array( 'select' => array('ID', 'XML_ID') )); while ($row = $iterator->fetch()) { $result[$row['XML_ID']] = $row['ID']; } unset($row); unset($iterator); } return $result; } /** * Returns a external codes list of active warehouses. * * @return array */ protected function getActiveStores(): array { $result = array(); if ($this->bCatalog) { $iterator = Catalog\StoreTable::getList(array( 'select' => array('ID', 'XML_ID'), 'filter' => array('=ACTIVE' => 'Y') )); while ($row = $iterator->fetch()) { $result[$row['XML_ID']] = $row['ID']; } unset($row); unset($iterator); } return $result; } /** * Count total product quantity. * * @param array $stores * @return int|float */ protected function countTotalQuantity(array $stores) { $totalQuantity = 0; foreach ($stores as $xmlId => $quantity) { if (isset($this->activeStores[$xmlId])) { $totalQuantity += $quantity; } } return $totalQuantity; } } class CIBlockCMLExport { var $fp = null; var $IBLOCK_ID = false; var $bExtended = false; var $work_dir = false; var $file_dir = false; /** @var bool|array */ var $next_step = false; /** @var array */ var $arIBlock = false; var $prices = array(); var $only_price = false; var $download_files = true; var $export_as_url = false; var $PRODUCT_IBLOCK_ID = false; function Init($fp, $IBLOCK_ID, $next_step, $bExtended=false, $work_dir=false, $file_dir=false, $bCheckPermissions = true, $PRODUCT_IBLOCK_ID = false) { $this->fp = $fp; $this->IBLOCK_ID = intval($IBLOCK_ID); $this->bExtended = $bExtended; $this->work_dir = $work_dir; $this->file_dir = $file_dir; $this->next_step = $next_step; $this->only_price = false; $this->download_files = true; $this->PRODUCT_IBLOCK_ID = intval($PRODUCT_IBLOCK_ID); $arFilter = array( "ID" => $this->IBLOCK_ID, "MIN_PERMISSION" => "W", ); if(!$bCheckPermissions) $arFilter["CHECK_PERMISSIONS"] = "N"; $rsIBlock = CIBlock::GetList(array(), $arFilter); if(($this->arIBlock = $rsIBlock->Fetch()) && ($this->arIBlock["ID"]==$this->IBLOCK_ID)) { $this->next_step["catalog"] = Loader::includeModule('catalog'); if($this->next_step["catalog"]) { $rs = CCatalog::GetList(array(),array("IBLOCK_ID"=>$this->arIBlock["ID"])); if($rs->Fetch()) { $this->next_step["catalog"] = true; $this->prices = array(); foreach (Catalog\GroupTable::getTypeList() as $arPrice) { $this->prices[$arPrice["ID"]] = $arPrice["NAME"]; } } else { $this->next_step["catalog"] = false; } } return true; } else return false; } function DoNotDownloadCloudFiles() { $this->download_files = false; } function NotCatalog() { $this->next_step["catalog"] = false; } function ExportFileAsURL() { $this->export_as_url = true; } function GetIBlockXML_ID($IBLOCK_ID, $XML_ID=false) { if($XML_ID === false) { $IBLOCK_ID = intval($IBLOCK_ID); if($IBLOCK_ID>0) { $obIBlock = new CIBlock; $rsIBlock = $obIBlock->GetList(array(), array("ID"=>$IBLOCK_ID)); if($arIBlock = $rsIBlock->Fetch()) $XML_ID = $arIBlock["XML_ID"]; else return ""; } else return ""; } if($XML_ID == '') { $XML_ID = $IBLOCK_ID; $obIBlock = new CIBlock; $rsIBlock = $obIBlock->GetList(array(), array("XML_ID"=>$XML_ID)); while($rsIBlock->Fetch()) { $XML_ID = md5(uniqid(mt_rand(), true)); $rsIBlock = $obIBlock->GetList(array(), array("XML_ID"=>$XML_ID)); } $obIBlock->Update($IBLOCK_ID, array("XML_ID" => $XML_ID)); } return $XML_ID; } function GetSectionXML_ID($IBLOCK_ID, $SECTION_ID, $XML_ID = false) { if($XML_ID === false) { $rsSection = CIBlockSection::GetList(array(), array("IBLOCK_ID"=>$IBLOCK_ID, "ID"=>$SECTION_ID), false, array('ID', 'XML_ID')); if($arSection = $rsSection->Fetch()) { $XML_ID = $arSection["XML_ID"]; } unset($rsSection); } if($XML_ID == '') { $XML_ID = $SECTION_ID; $obSection = new CIBlockSection; $rsSection = $obSection->GetList(array(), array("IBLOCK_ID"=>$IBLOCK_ID, "EXTERNAL_ID"=>$XML_ID), false, array('ID')); while($rsSection->Fetch()) { $XML_ID = md5(uniqid(mt_rand(), true)); $rsSection = $obSection->GetList(array(), array("IBLOCK_ID"=>$IBLOCK_ID, "EXTERNAL_ID"=>$XML_ID), false, array('ID')); } $obSection->Update($SECTION_ID, array("XML_ID" => $XML_ID), false, false); } return $XML_ID; } function GetElementXML_ID($IBLOCK_ID, $ELEMENT_ID, $XML_ID = false) { if($XML_ID === false) { $arFilter = array( "ID" => $ELEMENT_ID, "SHOW_HISTORY"=>"Y", ); if($IBLOCK_ID > 0) $arFilter["IBLOCK_ID"] = $IBLOCK_ID; $rsElement = CIBlockElement::GetList( Array("ID"=>"asc"), $arFilter, false, false, Array("ID", "XML_ID") ); if($arElement = $rsElement->Fetch()) { $XML_ID = $arElement["XML_ID"]; } unset($rsElement); unset($arElement); } return $XML_ID; } function GetPropertyXML_ID($IBLOCK_ID, $NAME, $PROPERTY_ID, $XML_ID) { if($XML_ID == '') { $XML_ID = $PROPERTY_ID; $obProperty = new CIBlockProperty; $rsProperty = $obProperty->GetList(array(), array("IBLOCK_ID"=>$IBLOCK_ID, "XML_ID"=>$XML_ID)); while($rsProperty->Fetch()) { $XML_ID = md5(uniqid(mt_rand(), true)); $rsProperty = $obProperty->GetList(array(), array("IBLOCK_ID"=>$IBLOCK_ID, "XML_ID"=>$XML_ID)); } $obProperty->Update($PROPERTY_ID, array("NAME"=>$NAME, "XML_ID" => $XML_ID)); } return $XML_ID; } function StartExport() { fwrite($this->fp, "<"."?xml version=\"1.0\" encoding=\"".LANG_CHARSET."\"?".">\n"); fwrite($this->fp, "<".GetMessage("IBLOCK_XML2_COMMERCE_INFO")." ".GetMessage("IBLOCK_XML2_SCHEMA_VERSION")."=\"2.021\" ".GetMessage("IBLOCK_XML2_TIMESTAMP")."=\"".date("Y-m-d")."T".date("H:i:s")."\">\n"); } function ExportFile($FILE_ID) { if($this->work_dir) { $arFile = CFile::GetFileArray($FILE_ID); if($arFile) { if((!$this->download_files) && ($arFile["HANDLER_ID"] > 0)) { return array( GetMessage("IBLOCK_XML2_BX_ORIGINAL_NAME") => $arFile["ORIGINAL_NAME"], GetMessage("IBLOCK_XML2_DESCRIPTION") => $arFile["DESCRIPTION"], GetMessage("IBLOCK_XML2_BX_URL") => urldecode($arFile["SRC"]), GetMessage("IBLOCK_XML2_BX_FILE_SIZE") => $arFile["FILE_SIZE"], GetMessage("IBLOCK_XML2_BX_FILE_WIDTH") => $arFile["WIDTH"], GetMessage("IBLOCK_XML2_BX_FILE_HEIGHT") => $arFile["HEIGHT"], GetMessage("IBLOCK_XML2_BX_FILE_CONTENT_TYPE") => $arFile["CONTENT_TYPE"], ); } else { $arTempFile = CFile::MakeFileArray($FILE_ID); if(isset($arTempFile["tmp_name"]) && $arTempFile["tmp_name"] <> "") { $strFile = $arFile["SUBDIR"]."/".$arFile["FILE_NAME"]; $strNewFile = str_replace("//", "/", $this->work_dir.$this->file_dir.$strFile); CheckDirPath($strNewFile); if(@copy($arTempFile["tmp_name"], $strNewFile)) return $this->file_dir.$strFile; } } } } elseif($this->export_as_url) { $arFile = CFile::GetFileArray($FILE_ID); if($arFile) return CHTTP::URN2URI($arFile["SRC"]); } return ""; } function ExportEnum($arUserField, $value) { static $cache = array(); if (!isset($cache[$value])) { $obEnum = new CUserFieldEnum; $rsEnum = $obEnum->GetList(array(), array( "USER_FIELD_ID" => $arUserField["ID"], "ID" => $value, )); $cache[$value] = $rsEnum->Fetch(); } return $cache[$value]["XML_ID"]; } function formatXMLNode($level, $tagName, $value) { if(is_array($value)) { $xmlValue = ""; foreach($value as $k => $v) { if($k) $xmlValue .= "\n".rtrim($this->formatXMLNode($level+1, $k, $v), "\n"); } $xmlValue .= "\n".str_repeat("\t", $level); } else { $xmlValue = htmlspecialcharsbx($value); } return str_repeat("\t", $level)."<".$tagName.">".$xmlValue."</".$tagName.">\n"; } function StartExportMetadata() { $xml_id = $this->GetIBlockXML_ID($this->arIBlock["ID"], $this->arIBlock["XML_ID"]); $this->arIBlock["XML_ID"] = $xml_id; fwrite($this->fp, "\t<".GetMessage("IBLOCK_XML2_METADATA").">\n"); fwrite($this->fp, $this->formatXMLNode(2, GetMessage("IBLOCK_XML2_ID"), $xml_id)); fwrite($this->fp, $this->formatXMLNode(2, GetMessage("IBLOCK_XML2_NAME"), $this->arIBlock["NAME"])); if($this->arIBlock["DESCRIPTION"] <> '') fwrite($this->fp, $this->formatXMLNode(2, GetMessage("IBLOCK_XML2_DESCRIPTION"), FormatText($this->arIBlock["DESCRIPTION"], $this->arIBlock["DESCRIPTION_TYPE"]))); } function ExportSectionsProperties($arUserFields) { if(empty($arUserFields)) return; fwrite($this->fp, "\t\t<".GetMessage("IBLOCK_XML2_GROUPS_PROPERTIES").">\n"); foreach($arUserFields as $FIELD_ID => $arField) { fwrite($this->fp, "\t\t\t<".GetMessage("IBLOCK_XML2_PROPERTY").">\n"); fwrite($this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_ID").">".htmlspecialcharsbx($arField["XML_ID"])."</".GetMessage("IBLOCK_XML2_ID").">\n"); fwrite($this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_NAME").">".htmlspecialcharsbx($FIELD_ID)."</".GetMessage("IBLOCK_XML2_NAME").">\n"); fwrite($this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_SORT").">".htmlspecialcharsbx($arField["SORT"])."</".GetMessage("IBLOCK_XML2_SORT").">\n"); fwrite($this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_MULTIPLE").">".($arField["MULTIPLE"] == "Y"? "true": "false")."</".GetMessage("IBLOCK_XML2_MULTIPLE").">\n"); fwrite($this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_BX_PROPERTY_TYPE").">".htmlspecialcharsbx($arField["USER_TYPE_ID"])."</".GetMessage("IBLOCK_XML2_BX_PROPERTY_TYPE").">\n"); fwrite($this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_BX_IS_REQUIRED").">".($arField["MANDATORY"] == "Y"? "true": "false")."</".GetMessage("IBLOCK_XML2_BX_IS_REQUIRED").">\n"); fwrite($this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_BX_FILTER").">".($arField["SHOW_FILTER"] == "Y"? "true": "false")."</".GetMessage("IBLOCK_XML2_BX_FILTER").">\n"); fwrite($this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_BX_SHOW_IN_LIST").">".($arField["SHOW_IN_LIST"] == "Y"? "true": "false")."</".GetMessage("IBLOCK_XML2_BX_SHOW_IN_LIST").">\n"); fwrite($this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_BX_EDIT_IN_LIST").">".($arField["EDIT_IN_LIST"] == "Y"? "true": "false")."</".GetMessage("IBLOCK_XML2_BX_EDIT_IN_LIST").">\n"); fwrite($this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_BX_SEARCH").">".($arField["IS_SEARCHABLE"] == "Y"? "true": "false")."</".GetMessage("IBLOCK_XML2_BX_SEARCH").">\n"); fwrite($this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_BX_SETTINGS").">".htmlspecialcharsbx(serialize($arField["SETTINGS"]))."</".GetMessage("IBLOCK_XML2_BX_SETTINGS").">\n"); if (is_callable(array($arField["USER_TYPE"]['CLASS_NAME'], 'getlist'))) { fwrite($this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_CHOICE_VALUES").">\n"); $rsEnum = call_user_func_array( array($arField["USER_TYPE"]["CLASS_NAME"], "getlist"), array( $arField, ) ); if (is_object($rsEnum)) { while ($arEnum = $rsEnum->GetNext()) { fwrite($this->fp, "\t\t\t\t\t<".GetMessage("IBLOCK_XML2_CHOICE").">\n" .$this->formatXMLNode(6, GetMessage("IBLOCK_XML2_ID"), $arEnum["XML_ID"]) .$this->formatXMLNode(6, GetMessage("IBLOCK_XML2_VALUE"), $arEnum["VALUE"]) .$this->formatXMLNode(6, GetMessage("IBLOCK_XML2_BY_DEFAULT"), ($arEnum["DEF"] == "Y" ? "true" : "false")) .$this->formatXMLNode(6, GetMessage("IBLOCK_XML2_SORT"), intval($arEnum["SORT"])) ."\t\t\t\t\t</".GetMessage("IBLOCK_XML2_CHOICE").">\n" ); } } unset($rsEnum); fwrite($this->fp, "\t\t\t\t</".GetMessage("IBLOCK_XML2_CHOICE_VALUES").">\n"); } fwrite($this->fp, "\t\t\t</".GetMessage("IBLOCK_XML2_PROPERTY").">\n"); } fwrite($this->fp, "\t\t</".GetMessage("IBLOCK_XML2_GROUPS_PROPERTIES").">\n"); } function ExportSections(&$SECTION_MAP, $start_time, $INTERVAL, $FILTER = "", $PROPERTY_MAP = array()) { /** @var CUserTypeManager $USER_FIELD_MANAGER */ global $USER_FIELD_MANAGER; $counter = 0; if(!array_key_exists("CURRENT_DEPTH", $this->next_step)) $this->next_step["CURRENT_DEPTH"]=0; else // this makes second "step" return $counter; $arUserFields = $USER_FIELD_MANAGER->GetUserFields("IBLOCK_".$this->arIBlock["ID"]."_SECTION"); foreach($arUserFields as $FIELD_ID => $arField) if($arField["XML_ID"] == '') $arUserFields[$FIELD_ID]["XML_ID"] = $FIELD_ID; if($this->bExtended) $this->ExportSectionsProperties($arUserFields); $SECTION_MAP = array(); if($FILTER === "none") return 0; $arFilter = array( "IBLOCK_ID" => $this->arIBlock["ID"], "GLOBAL_ACTIVE" => "Y", "CHECK_PERMISSIONS" => "N", ); if($FILTER === "all") unset($arFilter["GLOBAL_ACTIVE"]); $rsSections = CIBlockSection::GetList(array("left_margin"=>"asc"), $arFilter, false, array("UF_*")); fwrite($this->fp, "\t\t<".GetMessage("IBLOCK_XML2_GROUPS").">\n"); while($arSection = $rsSections->Fetch()) { $white_space = str_repeat("\t\t", $arSection["DEPTH_LEVEL"]); $level = ($arSection["DEPTH_LEVEL"]+1)*2; while($this->next_step["CURRENT_DEPTH"] >= $arSection["DEPTH_LEVEL"]) { fwrite($this->fp, str_repeat("\t\t", $this->next_step["CURRENT_DEPTH"])."\t\t</".GetMessage("IBLOCK_XML2_GROUPS").">\n"); fwrite($this->fp, str_repeat("\t\t", $this->next_step["CURRENT_DEPTH"]-1)."\t\t\t</".GetMessage("IBLOCK_XML2_GROUP").">\n"); $this->next_step["CURRENT_DEPTH"]--; } $xml_id = $this->GetSectionXML_ID($this->arIBlock["ID"], $arSection["ID"], $arSection["XML_ID"]); $SECTION_MAP[$arSection["ID"]] = $xml_id; fwrite($this->fp, $white_space."\t<".GetMessage("IBLOCK_XML2_GROUP").">\n" .$this->formatXMLNode($level, GetMessage("IBLOCK_XML2_ID"), $xml_id) .$this->formatXMLNode($level, GetMessage("IBLOCK_XML2_NAME"), $arSection["NAME"]) ); if($arSection["DESCRIPTION"] <> '') fwrite($this->fp, $white_space."\t\t<".GetMessage("IBLOCK_XML2_DESCRIPTION").">".htmlspecialcharsbx(FormatText($arSection["DESCRIPTION"], $arSection["DESCRIPTION_TYPE"]))."</".GetMessage("IBLOCK_XML2_DESCRIPTION").">\n"); if($this->bExtended) { fwrite($this->fp, $this->formatXMLNode($level, GetMessage("IBLOCK_XML2_BX_ACTIVE"), ($arSection["ACTIVE"]=="Y"? "true": "false")) .$this->formatXMLNode($level, GetMessage("IBLOCK_XML2_BX_SORT"), intval($arSection["SORT"])) .$this->formatXMLNode($level, GetMessage("IBLOCK_XML2_BX_CODE"), $arSection["CODE"]) .$this->formatXMLNode($level, GetMessage("IBLOCK_XML2_BX_PICTURE"), $this->ExportFile($arSection["PICTURE"])) .$this->formatXMLNode($level, GetMessage("IBLOCK_XML2_BX_DETAIL_PICTURE"), $this->ExportFile($arSection["DETAIL_PICTURE"])) ); if(!empty($arUserFields)) { fwrite($this->fp, $white_space."\t\t<".GetMessage("IBLOCK_XML2_PROPERTIES_VALUES").">\n"); foreach($arUserFields as $FIELD_ID => $arField) { fwrite($this->fp, $white_space."\t\t\t<".GetMessage("IBLOCK_XML2_PROPERTY_VALUES").">\n"); fwrite($this->fp, $this->formatXMLNode($level+2, GetMessage("IBLOCK_XML2_ID"), $arField["XML_ID"])); $values = array(); if(!is_array($arSection[$FIELD_ID])) { if($arField["USER_TYPE"]["BASE_TYPE"] === "file") $values[] = $this->ExportFile($arSection[$FIELD_ID]); elseif($arField["USER_TYPE"]["BASE_TYPE"] === "enum") $values[] = $this->ExportEnum($arField, $arSection[$FIELD_ID]); else $values[] = $arSection[$FIELD_ID]; } elseif(empty($arSection[$FIELD_ID])) { $values[] = ""; } else { foreach($arSection[$FIELD_ID] as $value) { if($arField["USER_TYPE"]["BASE_TYPE"] === "file") $values[] = $this->ExportFile($value); elseif($arField["USER_TYPE"]["BASE_TYPE"] === "enum") $values[] = $this->ExportEnum($arField, $value); else $values[] = $value; } } foreach($values as $value) { fwrite($this->fp, $this->formatXMLNode($level+2, GetMessage("IBLOCK_XML2_VALUE"), $value)); } fwrite($this->fp, $white_space."\t\t\t</".GetMessage("IBLOCK_XML2_PROPERTY_VALUES").">\n"); } fwrite($this->fp, $white_space."\t\t</".GetMessage("IBLOCK_XML2_PROPERTIES_VALUES").">\n"); } $this->ExportSmartFilter($level, $this->arIBlock["ID"], $arSection["ID"], $PROPERTY_MAP); $sectionTemplates = new \Bitrix\Iblock\InheritedProperty\SectionTemplates($this->arIBlock["ID"], $arSection["ID"]); $this->exportInheritedTemplates($arSection["DEPTH_LEVEL"]*2 + 2, $sectionTemplates); } fwrite($this->fp, $white_space."\t\t<".GetMessage("IBLOCK_XML2_GROUPS").">\n"); $this->next_step["CURRENT_DEPTH"] = $arSection["DEPTH_LEVEL"]; $counter++; } while($this->next_step["CURRENT_DEPTH"] > 0) { fwrite($this->fp, str_repeat("\t\t", $this->next_step["CURRENT_DEPTH"])."\t\t</".GetMessage("IBLOCK_XML2_GROUPS").">\n"); fwrite($this->fp, str_repeat("\t\t", $this->next_step["CURRENT_DEPTH"]-1)."\t\t\t</".GetMessage("IBLOCK_XML2_GROUP").">\n"); $this->next_step["CURRENT_DEPTH"]--; } fwrite($this->fp, "\t\t</".GetMessage("IBLOCK_XML2_GROUPS").">\n"); return $counter; } function ExportProperties(&$PROPERTY_MAP) { $PROPERTY_MAP = array(); fwrite($this->fp, "\t\t<".GetMessage("IBLOCK_XML2_PROPERTIES").">\n"); if($this->bExtended) { $arElementFields = array( "CML2_ACTIVE" => GetMessage("IBLOCK_XML2_BX_ACTIVE"), "CML2_CODE" => GetMessage("IBLOCK_XML2_SYMBOL_CODE"), "CML2_SORT" => GetMessage("IBLOCK_XML2_SORT"), "CML2_ACTIVE_FROM" => GetMessage("IBLOCK_XML2_START_TIME"), "CML2_ACTIVE_TO" => GetMessage("IBLOCK_XML2_END_TIME"), "CML2_PREVIEW_TEXT" => GetMessage("IBLOCK_XML2_ANONS"), "CML2_DETAIL_TEXT" => GetMessage("IBLOCK_XML2_DETAIL"), "CML2_PREVIEW_PICTURE" => GetMessage("IBLOCK_XML2_PREVIEW_PICTURE"), ); foreach($arElementFields as $key => $value) { fwrite($this->fp, $this->formatXMLNode(3, GetMessage("IBLOCK_XML2_PROPERTY"), array( GetMessage("IBLOCK_XML2_ID") => $key, GetMessage("IBLOCK_XML2_NAME") => $value, GetMessage("IBLOCK_XML2_MULTIPLE") => "false", ))); } } $featureList = []; $iterator = Iblock\PropertyFeatureTable::getList([ 'select' => ['PROPERTY_ID', 'MODULE_ID', 'FEATURE_ID', 'IS_ENABLED'], 'filter' => [ '=PROPERTY.IBLOCK_ID' => $this->arIBlock['ID'], '=PROPERTY.ACTIVE' => 'Y' ], 'order' => ['PROPERTY_ID' => 'ASC'] ]); while ($row = $iterator->fetch()) { $id = (int)$row['PROPERTY_ID']; if (!isset($featureList[$id])) $featureList[$id] = []; $featureList[$id][] = [ 'MODULE_ID' => $row['MODULE_ID'], 'FEATURE_ID' => $row['FEATURE_ID'], 'IS_ENABLED' => $row['IS_ENABLED'] ]; unset($id); } unset($row, $iterator); $arFilter = array( "IBLOCK_ID" => $this->arIBlock["ID"], "ACTIVE" => "Y", ); $arSort = array( "sort" => "asc", ); $obProp = new CIBlockProperty(); $rsProp = $obProp->GetList($arSort, $arFilter); while($arProp = $rsProp->Fetch()) { $id = (int)$arProp["ID"]; fwrite($this->fp, "\t\t\t<".GetMessage("IBLOCK_XML2_PROPERTY").">\n"); $xml_id = $this->GetPropertyXML_ID($this->arIBlock["ID"], $arProp["NAME"], $arProp["ID"], $arProp["XML_ID"]); $PROPERTY_MAP[$arProp["ID"]] = $xml_id; $PROPERTY_MAP["~".$arProp["ID"]] = $arProp["NAME"]; fwrite($this->fp, $this->formatXMLNode(4, GetMessage("IBLOCK_XML2_ID"), $xml_id)); fwrite($this->fp, $this->formatXMLNode(4, GetMessage("IBLOCK_XML2_NAME"), $arProp["NAME"])); fwrite($this->fp, $this->formatXMLNode(4, GetMessage("IBLOCK_XML2_MULTIPLE"), ($arProp["MULTIPLE"]=="Y"? "true": "false"))); if($arProp["PROPERTY_TYPE"]=="L") { fwrite($this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_CHOICE_VALUES").">\n"); $rsEnum = CIBlockProperty::GetPropertyEnum($arProp["ID"]); while($arEnum = $rsEnum->Fetch()) { fwrite($this->fp, $this->formatXMLNode(5, GetMessage("IBLOCK_XML2_VALUE"), $arEnum["VALUE"])); if($this->bExtended) { fwrite($this->fp, "\t\t\t\t\t<".GetMessage("IBLOCK_XML2_CHOICE").">\n" .$this->formatXMLNode(6, GetMessage("IBLOCK_XML2_ID"), $arEnum["XML_ID"]) .$this->formatXMLNode(6, GetMessage("IBLOCK_XML2_VALUE"), $arEnum["VALUE"]) .$this->formatXMLNode(6, GetMessage("IBLOCK_XML2_BY_DEFAULT"), ($arEnum["DEF"]=="Y"? "true": "false")) .$this->formatXMLNode(6, GetMessage("IBLOCK_XML2_SORT"), intval($arEnum["SORT"])) ."\t\t\t\t\t</".GetMessage("IBLOCK_XML2_CHOICE").">\n" ); } } fwrite($this->fp, "\t\t\t\t</".GetMessage("IBLOCK_XML2_CHOICE_VALUES").">\n"); } if($this->bExtended) { $strUserSettings = ''; if ('' != $arProp["USER_TYPE"]) { if (!empty($arProp['USER_TYPE_SETTINGS']) && is_array($arProp['USER_TYPE_SETTINGS'])) { $strUserSettings = $this->formatXMLNode(4, GetMessage("IBLOCK_XML2_BX_USER_TYPE_SETTINGS"), serialize($arProp['USER_TYPE_SETTINGS'])); } } $propertyFeatures = ''; if (isset($featureList[$id])) { $propertyFeatures = $this->formatXMLNode( 4, GetMessage('IBLOCK_XML2_BX_PROPERTY_FEATURE_LIST'), serialize($featureList[$id]) ); } fwrite($this->fp, $this->formatXMLNode(4, GetMessage("IBLOCK_XML2_BX_SORT"), intval($arProp["SORT"])) .$this->formatXMLNode(4, GetMessage("IBLOCK_XML2_BX_CODE"), $arProp["CODE"]) .$this->formatXMLNode(4, GetMessage("IBLOCK_XML2_BX_PROPERTY_TYPE"), $arProp["PROPERTY_TYPE"]) .$this->formatXMLNode(4, GetMessage("IBLOCK_XML2_BX_ROWS"), $arProp["ROW_COUNT"]) .$this->formatXMLNode(4, GetMessage("IBLOCK_XML2_BX_COLUMNS"), $arProp["COL_COUNT"]) .$this->formatXMLNode(4, GetMessage("IBLOCK_XML2_BX_LIST_TYPE"), $arProp["LIST_TYPE"]) .$this->formatXMLNode(4, GetMessage("IBLOCK_XML2_BX_FILE_EXT"), $arProp["FILE_TYPE"]) .$this->formatXMLNode(4, GetMessage("IBLOCK_XML2_BX_FIELDS_COUNT"), $arProp["MULTIPLE_CNT"]) .$this->formatXMLNode(4, GetMessage("IBLOCK_XML2_BX_LINKED_IBLOCK"), $this->GetIBlockXML_ID($arProp["LINK_IBLOCK_ID"])) .$this->formatXMLNode(4, GetMessage("IBLOCK_XML2_BX_WITH_DESCRIPTION"), ($arProp["WITH_DESCRIPTION"]=="Y"? "true": "false")) .$this->formatXMLNode(4, GetMessage("IBLOCK_XML2_BX_SEARCH"), ($arProp["SEARCHABLE"]=="Y"? "true": "false")) .$this->formatXMLNode(4, GetMessage("IBLOCK_XML2_BX_FILTER"), ($arProp["FILTRABLE"]=="Y"? "true": "false")) .$this->formatXMLNode(4, GetMessage("IBLOCK_XML2_BX_USER_TYPE"), $arProp["USER_TYPE"]) .$this->formatXMLNode(4, GetMessage("IBLOCK_XML2_BX_IS_REQUIRED"), ($arProp["IS_REQUIRED"]=="Y"? "true": "false")) .$this->formatXMLNode(4, GetMessage("IBLOCK_XML2_BX_DEFAULT_VALUE"), serialize($arProp["DEFAULT_VALUE"])) .$this->formatXMLNode(4, GetMessage("IBLOCK_XML2_SERIALIZED"), 1) .$strUserSettings .$propertyFeatures ); } fwrite($this->fp, "\t\t\t</".GetMessage("IBLOCK_XML2_PROPERTY").">\n"); } fwrite($this->fp, "\t\t</".GetMessage("IBLOCK_XML2_PROPERTIES").">\n"); if($this->bExtended) { $catalog = false; if (Loader::includeModule("catalog")) { $catalog = CCatalogSKU::getInfoByOfferIBlock($this->arIBlock["ID"]); } if (!empty($catalog) && is_array($catalog)) { $this->ExportSmartFilter(2, $this->arIBlock["ID"], false, $PROPERTY_MAP, $catalog["PRODUCT_IBLOCK_ID"]); } else { $this->ExportSmartFilter(2, $this->arIBlock["ID"], 0, $PROPERTY_MAP); } } } function ExportSmartFilter($level, $iblockId, $sectionId, $PROPERTY_MAP, $productIblockId = 0) { $propertyLinksBySection = array(); if ($sectionId === false) { $propertyLinksBySection[0] = CIBlockSectionPropertyLink::GetArray($iblockId, 0); foreach($propertyLinksBySection[0] as $PID => $arLink) { if($arLink["INHERITED"] != "N" || !array_key_exists($PID, $PROPERTY_MAP)) { unset($propertyLinksBySection[0][$PID]); } else { if ($productIblockId > 0) { $iblock_xml_id = $this->GetIBlockXML_ID($productIblockId, CIBlock::GetArrayByID($productIblockId, "XML_ID")); $propertyLinksBySection[0][$PID]["IBLOCK_XML_ID"] = $iblock_xml_id; } } } $arFilter = array( "IBLOCK_ID" => $productIblockId? $productIblockId: $iblockId, "CHECK_PERMISSIONS" => "N", ); $rsSections = CIBlockSection::GetList(array("left_margin"=>"asc"), $arFilter, false, array("ID", "XML_ID", "IBLOCK_ID")); while($arSection = $rsSections->Fetch()) { $section_xml_id = $this->GetSectionXML_ID($arSection["IBLOCK_ID"], $arSection["ID"], $arSection["XML_ID"]); $iblock_xml_id = $this->GetIBlockXML_ID($arSection["IBLOCK_ID"], CIBlock::GetArrayByID($arSection["IBLOCK_ID"], "XML_ID")); $propertyLinksBySection[$arSection["ID"]] = CIBlockSectionPropertyLink::GetArray($iblockId, $arSection["ID"]); foreach($propertyLinksBySection[$arSection["ID"]] as $PID => $arLink) { if($arLink["INHERITED"] != "N" || !array_key_exists($PID, $PROPERTY_MAP)) { unset($propertyLinksBySection[$arSection["ID"]][$PID]); } else { $propertyLinksBySection[$arSection["ID"]][$PID]["IBLOCK_XML_ID"] = $iblock_xml_id; $propertyLinksBySection[$arSection["ID"]][$PID]["SECTION_XML_ID"] = $section_xml_id; } } } } else { $propertyLinksBySection[$sectionId] = CIBlockSectionPropertyLink::GetArray($iblockId, $sectionId); foreach($propertyLinksBySection[$sectionId] as $PID => $arLink) { if($arLink["INHERITED"] != "N" || !array_key_exists($PID, $PROPERTY_MAP)) unset($propertyLinksBySection[$sectionId][$PID]); } } $first = true; foreach ($propertyLinksBySection as $arPropLink) { if(!empty($arPropLink)) { if ($first) { fwrite($this->fp, str_repeat("\t", $level)."<".GetMessage("IBLOCK_XML2_SECTION_PROPERTIES").">\n"); $first = false; } foreach($arPropLink as $PID => $arLink) { $xmlLink = array( GetMessage("IBLOCK_XML2_ID") => $PROPERTY_MAP[$PID], GetMessage("IBLOCK_XML2_SMART_FILTER") => ($arLink["SMART_FILTER"] == "Y"? "true": "false"), GetMessage("IBLOCK_XML2_SMART_FILTER_DISPLAY_TYPE") => $arLink["DISPLAY_TYPE"], GetMessage("IBLOCK_XML2_SMART_FILTER_DISPLAY_EXPANDED") => ($arLink["DISPLAY_EXPANDED"] == "Y"? "true": "false"), GetMessage("IBLOCK_XML2_SMART_FILTER_HINT") => $arLink["FILTER_HINT"], ); if (isset($arLink["IBLOCK_XML_ID"])) { $xmlLink[GetMessage("IBLOCK_XML2_BX_LINKED_IBLOCK")] = $arLink["IBLOCK_XML_ID"]; } if (isset($arLink["SECTION_XML_ID"])) { $xmlLink[GetMessage("IBLOCK_XML2_GROUP")] = $arLink["SECTION_XML_ID"]; } fwrite($this->fp, $this->formatXMLNode($level+1, GetMessage("IBLOCK_XML2_PROPERTY"), $xmlLink)); } } } if (!$first) { fwrite($this->fp, str_repeat("\t", $level)."</".GetMessage("IBLOCK_XML2_SECTION_PROPERTIES").">\n"); } } function ExportPrices() { if($this->next_step["catalog"]) { $priceTypes = CCatalogGroup::GetListArray(); if (!empty($priceTypes)) { fwrite($this->fp, "\t\t<".GetMessage("IBLOCK_XML2_PRICE_TYPES").">\n"); foreach ($priceTypes as $arPrice) { fwrite($this->fp, $this->formatXMLNode(3, GetMessage("IBLOCK_XML2_PRICE_TYPE"), array( GetMessage("IBLOCK_XML2_ID") => $arPrice["NAME"], GetMessage("IBLOCK_XML2_NAME") => $arPrice["NAME"], ))); } unset($arPrice); fwrite($this->fp, "\t\t</".GetMessage("IBLOCK_XML2_PRICE_TYPES").">\n"); } unset($priceTypes); } } function EndExportMetadata() { fwrite($this->fp, "\t</".GetMessage("IBLOCK_XML2_METADATA").">\n"); } function StartExportCatalog($with_metadata = true, $changes_only = false) { if($this->next_step["catalog"]) fwrite($this->fp, "\t<".GetMessage("IBLOCK_XML2_OFFER_LIST").">\n"); else fwrite($this->fp, "\t<".GetMessage("IBLOCK_XML2_CATALOG").">\n"); if($this->PRODUCT_IBLOCK_ID) $xml_id = $this->GetIBlockXML_ID($this->PRODUCT_IBLOCK_ID, CIBlock::GetArrayByID($this->PRODUCT_IBLOCK_ID, "XML_ID")); else $xml_id = $this->GetIBlockXML_ID($this->arIBlock["ID"], $this->arIBlock["XML_ID"]); $this->arIBlock["XML_ID"] = $xml_id; fwrite($this->fp, $this->formatXMLNode(2, GetMessage("IBLOCK_XML2_ID"), $xml_id)); if($with_metadata) { fwrite($this->fp, $this->formatXMLNode(2, GetMessage("IBLOCK_XML2_METADATA_ID"), $xml_id)); fwrite($this->fp, $this->formatXMLNode(2, GetMessage("IBLOCK_XML2_NAME"), $this->arIBlock["NAME"])); if($this->arIBlock["DESCRIPTION"] <> '') fwrite($this->fp, $this->formatXMLNode(2, GetMessage("IBLOCK_XML2_DESCRIPTION"), FormatText($this->arIBlock["DESCRIPTION"], $this->arIBlock["DESCRIPTION_TYPE"]))); if($this->bExtended) { fwrite($this->fp, $this->formatXMLNode(2, GetMessage("IBLOCK_XML2_BX_CODE"), $this->arIBlock["CODE"]) .$this->formatXMLNode(2, GetMessage("IBLOCK_XML2_BX_API_CODE"), (string)$this->arIBlock["API_CODE"]) .$this->formatXMLNode(2, GetMessage("IBLOCK_XML2_BX_SORT"), intval($this->arIBlock["SORT"])) .$this->formatXMLNode(2, GetMessage("IBLOCK_XML2_BX_LIST_URL"), $this->arIBlock["LIST_PAGE_URL"]) .$this->formatXMLNode(2, GetMessage("IBLOCK_XML2_BX_DETAIL_URL"), $this->arIBlock["DETAIL_PAGE_URL"]) .$this->formatXMLNode(2, GetMessage("IBLOCK_XML2_BX_SECTION_URL"), $this->arIBlock["SECTION_PAGE_URL"]) .$this->formatXMLNode(2, GetMessage("IBLOCK_XML2_BX_CANONICAL_URL"), $this->arIBlock["CANONICAL_PAGE_URL"]) .$this->formatXMLNode(2, GetMessage("IBLOCK_XML2_BX_PICTURE"), $this->ExportFile($this->arIBlock["PICTURE"])) .$this->formatXMLNode(2, GetMessage("IBLOCK_XML2_BX_INDEX_ELEMENTS"), ($this->arIBlock["INDEX_ELEMENT"]=="Y"? "true": "false")) .$this->formatXMLNode(2, GetMessage("IBLOCK_XML2_BX_INDEX_SECTIONS"), ($this->arIBlock["INDEX_SECTION"]=="Y"? "true": "false")) .$this->formatXMLNode(2, GetMessage("IBLOCK_XML2_BX_WORKFLOW"), ($this->arIBlock["WORKFLOW"]=="Y"? "true": "false")) ); fwrite($this->fp, "\t\t<".GetMessage("IBLOCK_XML2_LABELS").">\n"); $arLabels = CIBlock::GetMessages($this->arIBlock["ID"]); foreach($arLabels as $id => $label) { fwrite($this->fp, $this->formatXMLNode(3, GetMessage("IBLOCK_XML2_LABEL"), array( GetMessage("IBLOCK_XML2_ID") => $id, GetMessage("IBLOCK_XML2_VALUE") => $label, ))); } fwrite($this->fp, "\t\t</".GetMessage("IBLOCK_XML2_LABELS").">\n"); $iblockTemplates = new \Bitrix\Iblock\InheritedProperty\IblockTemplates($this->arIBlock["ID"]); $this->exportInheritedTemplates(2, $iblockTemplates); } } if($with_metadata || $this->only_price) { $this->ExportPrices(); } if($changes_only) fwrite($this->fp, $this->formatXMLNode(2, GetMessage("IBLOCK_XML2_UPDATE_ONLY"), "true")); if($this->next_step["catalog"]) fwrite($this->fp, "\t\t<".GetMessage("IBLOCK_XML2_OFFERS").">\n"); else fwrite($this->fp, "\t\t<".GetMessage("IBLOCK_XML2_POSITIONS").">\n"); } function ExportPropertyValue($xml_id, $value, $type = null) { fwrite($this->fp, $this->formatXMLNode(5, GetMessage("IBLOCK_XML2_PROPERTY_VALUES"), array( GetMessage("IBLOCK_XML2_ID") => $xml_id, GetMessage("IBLOCK_XML2_VALUE") => $value, (isset($type)? GetMessage("IBLOCK_XML2_TYPE"): "") => $type, ))); } function exportInheritedTemplates($level, \Bitrix\Iblock\InheritedProperty\BaseTemplate $template) { $templates = $template->get(); if (!empty($templates)) { $ws = str_repeat("\t", $level); fwrite($this->fp, $ws."<".GetMessage("IBLOCK_XML2_INHERITED_TEMPLATES").">\n"); foreach ($templates as $CODE => $TEMPLATE) { fwrite($this->fp, $ws."\t<".GetMessage("IBLOCK_XML2_TEMPLATE").">\n"); fwrite($this->fp, $ws."\t\t<".GetMessage("IBLOCK_XML2_ID").">".htmlspecialcharsbx($CODE)."</".GetMessage("IBLOCK_XML2_ID").">\n"); fwrite($this->fp, $ws."\t\t<".GetMessage("IBLOCK_XML2_VALUE").">".htmlspecialcharsbx($TEMPLATE["TEMPLATE"])."</".GetMessage("IBLOCK_XML2_VALUE").">\n"); fwrite($this->fp, $ws."\t</".GetMessage("IBLOCK_XML2_TEMPLATE").">\n"); } fwrite($this->fp, $ws."</".GetMessage("IBLOCK_XML2_INHERITED_TEMPLATES").">\n"); } } /** * @param array $arElement * @param array $arFilter * @return array */ function preparePropertiesValues($arElement, $arFilter=array("ACTIVE"=>"Y")) { $arPropOrder = array( "sort" => "asc", "id" => "asc", "enum_sort" => "asc", "value_id" => "asc", ); $rsProps = CIBlockElement::GetProperty($this->arIBlock["ID"], $arElement["ID"], $arPropOrder, $arFilter); $arProps = array(); while($arProp = $rsProps->Fetch()) { $pid = $arProp["ID"]; if(!array_key_exists($pid, $arProps)) $arProps[$pid] = array( "PROPERTY_TYPE" => $arProp["PROPERTY_TYPE"], "LINK_IBLOCK_ID" => $arProp["LINK_IBLOCK_ID"], "VALUES" => array(), ); if($arProp["PROPERTY_TYPE"] == "L") $arProps[$pid]["VALUES"][] = array( "VALUE" => $arProp["VALUE_ENUM"], "DESCRIPTION" => $arProp["DESCRIPTION"], "VALUE_ENUM_ID" => $arProp["VALUE"], ); else $arProps[$pid]["VALUES"][] = array( "VALUE" => $arProp["VALUE"], "DESCRIPTION" => $arProp["DESCRIPTION"], "VALUE_ENUM_ID" => $arProp["VALUE_ENUM_ID"], ); } return $arProps; } function exportElementProperties($arElement, $PROPERTY_MAP) { if($this->bExtended) { $this->ExportPropertyValue("CML2_ACTIVE", ($arElement["ACTIVE"]=="Y"? "true": "false")); $this->ExportPropertyValue("CML2_CODE", $arElement["CODE"]); $this->ExportPropertyValue("CML2_SORT", intval($arElement["SORT"])); $this->ExportPropertyValue("CML2_ACTIVE_FROM", CDatabase::FormatDate($arElement["ACTIVE_FROM"], CLang::GetDateFormat("FULL"), "YYYY-MM-DD HH:MI:SS")); $this->ExportPropertyValue("CML2_ACTIVE_TO", CDatabase::FormatDate($arElement["ACTIVE_TO"], CLang::GetDateFormat("FULL"), "YYYY-MM-DD HH:MI:SS")); $this->ExportPropertyValue("CML2_PREVIEW_TEXT", $arElement["PREVIEW_TEXT"], $arElement["PREVIEW_TEXT_TYPE"]); $this->ExportPropertyValue("CML2_DETAIL_TEXT", $arElement["DETAIL_TEXT"], $arElement["DETAIL_TEXT_TYPE"]); $this->ExportPropertyValue("CML2_PREVIEW_PICTURE", $this->ExportFile($arElement["PREVIEW_PICTURE"])); } $arProps = $this->preparePropertiesValues($arElement); foreach($arProps as $pid => $arProp) { $bEmpty = true; if($this->next_step["catalog"] && !$this->bExtended) fwrite($this->fp, "\t\t\t\t\t<".GetMessage("IBLOCK_XML2_ITEM_ATTRIBUTE").">\n"); else fwrite($this->fp, "\t\t\t\t\t<".GetMessage("IBLOCK_XML2_PROPERTY_VALUES").">\n"); if($this->next_step["catalog"] && !$this->bExtended) fwrite($this->fp, "\t\t\t\t\t\t<".GetMessage("IBLOCK_XML2_NAME").">".htmlspecialcharsbx($PROPERTY_MAP["~".$pid])."</".GetMessage("IBLOCK_XML2_NAME").">\n"); else fwrite($this->fp, "\t\t\t\t\t\t<".GetMessage("IBLOCK_XML2_ID").">".htmlspecialcharsbx($PROPERTY_MAP[$pid])."</".GetMessage("IBLOCK_XML2_ID").">\n"); foreach($arProp["VALUES"] as $arValue) { $value = $arValue["VALUE"]; if(is_array($value) || (string)$value != '') { $bEmpty = false; $bSerialized = false; $this->preparePropertyValue($arProp, $arValue, $value, $bSerialized); fwrite($this->fp, $this->formatXMLNode(6, GetMessage("IBLOCK_XML2_VALUE"), $value)); if($this->bExtended) { fwrite($this->fp, "\t\t\t\t\t\t<".GetMessage("IBLOCK_XML2_PROPERTY_VALUE").">\n"); if($bSerialized) fwrite($this->fp, "\t\t\t\t\t\t\t<".GetMessage("IBLOCK_XML2_SERIALIZED").">true</".GetMessage("IBLOCK_XML2_SERIALIZED").">\n"); fwrite($this->fp, $this->formatXMLNode(7, GetMessage("IBLOCK_XML2_VALUE"), $value)); fwrite($this->fp, "\t\t\t\t\t\t\t<".GetMessage("IBLOCK_XML2_DESCRIPTION").">".htmlspecialcharsbx($arValue["DESCRIPTION"])."</".GetMessage("IBLOCK_XML2_DESCRIPTION").">\n"); fwrite($this->fp, "\t\t\t\t\t\t</".GetMessage("IBLOCK_XML2_PROPERTY_VALUE").">\n"); } } } if($bEmpty) fwrite($this->fp, "\t\t\t\t\t\t<".GetMessage("IBLOCK_XML2_VALUE")."></".GetMessage("IBLOCK_XML2_VALUE").">\n"); if($this->next_step["catalog"] && !$this->bExtended) fwrite($this->fp, "\t\t\t\t\t</".GetMessage("IBLOCK_XML2_ITEM_ATTRIBUTE").">\n"); else fwrite($this->fp, "\t\t\t\t\t</".GetMessage("IBLOCK_XML2_PROPERTY_VALUES").">\n"); } } function preparePropertyValue($arProp, $arValue, &$value, &$bSerialized) { if($this->bExtended) { if($arProp["PROPERTY_TYPE"]=="L") { $value = CIBlockPropertyEnum::GetByID($arValue["VALUE_ENUM_ID"]); $value = $value["XML_ID"]; } elseif($arProp["PROPERTY_TYPE"]=="F") { $value = $this->ExportFile($value); } elseif($arProp["PROPERTY_TYPE"]=="G") { $value = $this->GetSectionXML_ID($arProp["LINK_IBLOCK_ID"], $value); } elseif($arProp["PROPERTY_TYPE"]=="E") { $value = $this->GetElementXML_ID($arProp["LINK_IBLOCK_ID"], $value); } if(is_array($value) && $arProp["PROPERTY_TYPE"]!=="F") { $bSerialized = true; $value = serialize($value); } } } function exportElementFields($arElement, $SECTION_MAP) { fwrite($this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_NAME").">".htmlspecialcharsbx($arElement["NAME"])."</".GetMessage("IBLOCK_XML2_NAME").">\n"); if($this->bExtended) fwrite($this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_BX_TAGS").">".htmlspecialcharsbx($arElement["TAGS"])."</".GetMessage("IBLOCK_XML2_BX_TAGS").">\n"); $arSections = array(); $rsSections = CIBlockElement::GetElementGroups($arElement["ID"], true); while($arSection = $rsSections->Fetch()) if(array_key_exists($arSection["ID"], $SECTION_MAP)) $arSections[] = $SECTION_MAP[$arSection["ID"]]; fwrite($this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_GROUPS").">\n"); foreach($arSections as $xml_id) fwrite($this->fp, "\t\t\t\t\t<".GetMessage("IBLOCK_XML2_ID").">".htmlspecialcharsbx($xml_id)."</".GetMessage("IBLOCK_XML2_ID").">\n"); fwrite($this->fp, "\t\t\t\t</".GetMessage("IBLOCK_XML2_GROUPS").">\n"); if(!$this->bExtended) fwrite($this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_DESCRIPTION").">".htmlspecialcharsbx(FormatText($arElement["DETAIL_TEXT"], $arElement["DETAIL_TEXT_TYPE"]))."</".GetMessage("IBLOCK_XML2_DESCRIPTION").">\n"); fwrite($this->fp, $this->formatXMLNode(4, GetMessage("IBLOCK_XML2_PICTURE"), $this->ExportFile($arElement["DETAIL_PICTURE"]))); } function aliasXmlId($xml_id) { return ''; } function exportElement($arElement, $SECTION_MAP, $PROPERTY_MAP) { if($arElement["XML_ID"] <> '') $xml_id = $arElement["XML_ID"]; else $xml_id = $arElement["ID"]; if($this->PRODUCT_IBLOCK_ID > 0) { $arPropOrder = array( "sort" => "asc", "id" => "asc", "enum_sort" => "asc", "value_id" => "asc", ); $rsLink = CIBlockElement::GetProperty($this->arIBlock["ID"], $arElement["ID"], $arPropOrder, array("ACTIVE"=>"Y", "CODE" => "CML2_LINK")); $arLink = $rsLink->Fetch(); if(is_array($arLink) && !is_array($arLink["VALUE"]) && $arLink["VALUE"] > 0) { $parent_xml_id = $this->GetElementXML_ID($this->PRODUCT_IBLOCK_ID, $arLink["VALUE"]); if ($parent_xml_id === $xml_id) $xml_id = $parent_xml_id; else { [$productXmlId, $offerXmlId] = explode("#", $xml_id, 2); if ($productXmlId !== $parent_xml_id) $xml_id = $parent_xml_id."#".$xml_id; } } } fwrite($this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_ID").">".htmlspecialcharsbx($xml_id)."</".GetMessage("IBLOCK_XML2_ID").">\n"); if(($aliasXmlId = $this->aliasXmlId($xml_id))>0) fwrite($this->fp, $aliasXmlId); if(!$this->only_price) { $this->exportElementFields($arElement, $SECTION_MAP); if($this->next_step["catalog"] && !$this->bExtended) fwrite($this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_ITEM_ATTRIBUTES").">\n"); else fwrite($this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_PROPERTIES_VALUES").">\n"); $this->exportElementProperties($arElement, $PROPERTY_MAP); if($this->next_step["catalog"] && !$this->bExtended) fwrite($this->fp, "\t\t\t\t</".GetMessage("IBLOCK_XML2_ITEM_ATTRIBUTES").">\n"); else fwrite($this->fp, "\t\t\t\t</".GetMessage("IBLOCK_XML2_PROPERTIES_VALUES").">\n"); if($this->bExtended) { $elementTemplates = new \Bitrix\Iblock\InheritedProperty\ElementTemplates($this->arIBlock["ID"], $arElement["ID"]); $this->exportInheritedTemplates(4, $elementTemplates); } } if($this->next_step["catalog"]) { static $measure = null; if (!isset($measure)) { $measure = array(); $rsBaseUnit = CCatalogMeasure::GetList(array(), array()); while($arIDUnit = $rsBaseUnit->Fetch()) $measure[$arIDUnit["ID"]] = $arIDUnit["CODE"]; } static $systemFieldTypes = null; if (!isset($systemFieldTypes)) { $systemFieldTypes = []; if (Product\SystemField\MarkingCodeGroup::isAllowed()) { $systemFieldTypes[Product\SystemField\MarkingCodeGroup::FIELD_ID] = array_fill_keys( Product\SystemField\MarkingCodeGroup::getAllowedProductTypeList(), true ); } if (Product\SystemField\ProductMapping::isAllowed()) { $systemFieldTypes[Product\SystemField\ProductMapping::FIELD_ID] = array_fill_keys( Product\SystemField\ProductMapping::getAllowedProductTypeList(), true ); } } //TODO: change this code after refactoring product system fields $selectFields = ['ID', 'MEASURE', 'QUANTITY', 'TYPE', 'WIDTH', 'LENGTH', 'HEIGHT']; $productSystemFields = Catalog\Product\SystemField::getExportSelectFields(); $selectFields = array_merge($selectFields, $productSystemFields); $iterator = Catalog\ProductTable::getList([ 'select' => $selectFields, 'filter' => ['=ID' => $arElement['ID']] ]); $row = $iterator->fetch(); unset($iterator); if (!empty($row) && is_array($row)) { Product\SystemField::prepareRow($row, Product\SystemField::OPERATION_EXPORT); $row['TYPE'] = (int)$row['TYPE']; if ( isset($systemFieldTypes[Product\SystemField\MarkingCodeGroup::FIELD_ID]) && isset($systemFieldTypes[Product\SystemField\MarkingCodeGroup::FIELD_ID][$row['TYPE']]) ) { fwrite( $this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_MARKING_CODE_GROUP").">" .htmlspecialcharsbx((string)$row[Product\SystemField\MarkingCodeGroup::FIELD_ID]) ."</".GetMessage("IBLOCK_XML2_MARKING_CODE_GROUP").">\n" ); } if ( isset($systemFieldTypes[Product\SystemField\ProductMapping::FIELD_ID]) && isset($systemFieldTypes[Product\SystemField\ProductMapping::FIELD_ID][$row['TYPE']]) ) { fwrite( $this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_PRODUCT_MAPPING").">\n" ); if ( !empty($row[Product\SystemField\ProductMapping::FIELD_ID]) && is_array($row[Product\SystemField\ProductMapping::FIELD_ID]) ) { foreach ($row[Product\SystemField\ProductMapping::FIELD_ID] as $value) { fwrite( $this->fp, "\t\t\t\t\t<".GetMessage('IBLOCK_XML2_ID').">" .htmlspecialcharsbx($value) ."</".GetMessage('IBLOCK_XML2_ID').">\n" ); } } fwrite( $this->fp, "\t\t\t\t</".GetMessage("IBLOCK_XML2_PRODUCT_MAPPING").">\n" ); } if ( $row['TYPE'] == Catalog\ProductTable::TYPE_PRODUCT || $row['TYPE'] == Catalog\ProductTable::TYPE_SET || $row['TYPE'] == Catalog\ProductTable::TYPE_OFFER || ( $row['TYPE'] == Catalog\ProductTable::TYPE_SKU && Main\Config\Option::get('catalog', 'show_catalog_tab_with_offers') === 'Y' ) ) { $row['MEASURE'] = (int)$row['MEASURE']; $xmlMeasure = GetMessage("IBLOCK_XML2_PCS"); if ($row["MEASURE"] > 0 && isset($measure[$row["MEASURE"]])) $xmlMeasure = $measure[$row["MEASURE"]]; $arPrices = []; $rsPrices = Catalog\PriceTable::getList([ 'select' => ['ID', 'CATALOG_GROUP_ID', 'PRICE', 'CURRENCY', 'QUANTITY_FROM', 'QUANTITY_TO'], 'filter' => ['=PRODUCT_ID' => $arElement['ID']] ]); while($arPrice = $rsPrices->fetch()) { $arPrices[] = [ GetMessage("IBLOCK_XML2_PRICE_TYPE_ID") => $this->prices[$arPrice["CATALOG_GROUP_ID"]], GetMessage("IBLOCK_XML2_PRICE_FOR_ONE") => $arPrice["PRICE"], GetMessage("IBLOCK_XML2_CURRENCY") => $arPrice["CURRENCY"], GetMessage("IBLOCK_XML2_MEASURE") => $xmlMeasure, GetMessage("IBLOCK_XML2_QUANTITY_FROM") => $arPrice["QUANTITY_FROM"], GetMessage("IBLOCK_XML2_QUANTITY_TO") => $arPrice["QUANTITY_TO"], ]; } unset($arPrice); unset($rsPrices); if (!empty($arPrices)) { fwrite($this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_PRICES").">\n"); foreach($arPrices as $arPrice) { fwrite($this->fp, "\t\t\t\t\t<".GetMessage("IBLOCK_XML2_PRICE").">\n"); foreach($arPrice as $key=>$value) { fwrite($this->fp, "\t\t\t\t\t\t<".$key.">".htmlspecialcharsbx($value)."</".$key.">\n"); } fwrite($this->fp, "\t\t\t\t\t</".GetMessage("IBLOCK_XML2_PRICE").">\n"); } fwrite($this->fp, "\t\t\t\t</".GetMessage("IBLOCK_XML2_PRICES").">\n"); } unset($arPrices); if ($row['TYPE'] != Catalog\ProductTable::TYPE_SET) { fwrite( $this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_AMOUNT").">" .htmlspecialcharsbx($row["QUANTITY"]) ."</".GetMessage("IBLOCK_XML2_AMOUNT").">\n" ); } fwrite( $this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_BASE_UNIT").">" .htmlspecialcharsbx($xmlMeasure) ."</".GetMessage("IBLOCK_XML2_BASE_UNIT").">\n" ); fwrite( $this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_WIDTH").">" .htmlspecialcharsbx($row["WIDTH"]) ."</".GetMessage("IBLOCK_XML2_WIDTH").">\n" ); fwrite( $this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_LENGTH").">" .htmlspecialcharsbx($row["LENGTH"]) ."</".GetMessage("IBLOCK_XML2_LENGTH").">\n" ); fwrite( $this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_HEIGHT").">" .htmlspecialcharsbx($row["HEIGHT"]) ."</".GetMessage("IBLOCK_XML2_HEIGHT").">\n" ); } } unset($row); } } function ExportElements($PROPERTY_MAP, $SECTION_MAP, $start_time, $INTERVAL, $counter_limit = 0, $arElementFilter = false) { $counter = 0; $arSelect = array( "ID", "IBLOCK_ID", "XML_ID", "ACTIVE", "CODE", "NAME", "PREVIEW_TEXT", "PREVIEW_TEXT_TYPE", "ACTIVE_FROM", "ACTIVE_TO", "SORT", "TAGS", "DETAIL_TEXT", "DETAIL_TEXT_TYPE", "PREVIEW_PICTURE", "DETAIL_PICTURE", ); if(is_array($arElementFilter)) { $arFilter = $arElementFilter; } else { if($arElementFilter === "none") return 0; $arFilter = array ( "IBLOCK_ID"=> $this->arIBlock["ID"], "ACTIVE" => "Y", ">ID" => $this->next_step["LAST_ID"], ); if($arElementFilter === "all") unset($arFilter["ACTIVE"]); } $arOrder = array( "ID" => "ASC", ); $rsElements = CIBlockElement::GetList($arOrder, $arFilter, false, false, $arSelect); while($arElement = $rsElements->Fetch()) { if($this->next_step["catalog"]) fwrite($this->fp, "\t\t\t<".GetMessage("IBLOCK_XML2_OFFER").">\n"); else fwrite($this->fp, "\t\t\t<".GetMessage("IBLOCK_XML2_POSITION").">\n"); $this->exportElement($arElement, $SECTION_MAP, $PROPERTY_MAP); if($this->next_step["catalog"]) fwrite($this->fp, "\t\t\t</".GetMessage("IBLOCK_XML2_OFFER").">\n"); else fwrite($this->fp, "\t\t\t</".GetMessage("IBLOCK_XML2_POSITION").">\n"); $this->next_step["LAST_ID"] = $arElement["ID"]; $counter++; if($INTERVAL > 0 && (time()-$start_time) > $INTERVAL) break; if($counter_limit > 0 && ($counter >= $counter_limit)) break; } return $counter; } function EndExportCatalog() { if($this->next_step["catalog"]) { fwrite($this->fp, "\t\t</".GetMessage("IBLOCK_XML2_OFFERS").">\n"); fwrite($this->fp, "\t</".GetMessage("IBLOCK_XML2_OFFER_LIST").">\n"); } else { fwrite($this->fp, "\t\t</".GetMessage("IBLOCK_XML2_POSITIONS").">\n"); fwrite($this->fp, "\t</".GetMessage("IBLOCK_XML2_CATALOG").">\n"); } } function ExportProductSet($elementId, $elementXml) { $arSetItems = CCatalogProductSet::getAllSetsByProduct($elementId, CCatalogProductSet::TYPE_GROUP); if (is_array($arSetItems) && !empty($arSetItems)) { fwrite($this->fp, "\t\t<".GetMessage("IBLOCK_XML2_PRODUCT_SETS").">\n"); fwrite($this->fp, "\t\t\t<".GetMessage("IBLOCK_XML2_ID").">".htmlspecialcharsbx($elementXml)."</".GetMessage("IBLOCK_XML2_ID").">\n"); foreach ($arSetItems as $arOneSet) { fwrite($this->fp, "\t\t\t<".GetMessage("IBLOCK_XML2_PRODUCT_SET").">\n"); if (is_array($arOneSet["ITEMS"]) && !empty($arOneSet["ITEMS"])) { foreach ($arOneSet["ITEMS"] as $setItem) { $xmlId = $this->GetElementXML_ID($this->arIBlock["ID"], $setItem["ITEM_ID"]); if ($xmlId !== false) { fwrite($this->fp, "\t\t\t\t<".GetMessage("IBLOCK_XML2_PRODUCT_SET_ITEM").">\n"); fwrite($this->fp, "\t\t\t\t\t<".GetMessage("IBLOCK_XML2_VALUE").">".htmlspecialcharsbx($xmlId)."</".GetMessage("IBLOCK_XML2_VALUE").">\n"); fwrite($this->fp, "\t\t\t\t\t<".GetMessage("IBLOCK_XML2_AMOUNT").">".intval($setItem["QUANTITY"])."</".GetMessage("IBLOCK_XML2_AMOUNT").">\n"); fwrite($this->fp, "\t\t\t\t\t<".GetMessage("IBLOCK_XML2_SORT").">".intval($setItem["SORT"])."</".GetMessage("IBLOCK_XML2_SORT").">\n"); fwrite($this->fp, "\t\t\t\t</".GetMessage("IBLOCK_XML2_PRODUCT_SET_ITEM").">\n"); } } } fwrite($this->fp, "\t\t\t</".GetMessage("IBLOCK_XML2_PRODUCT_SET").">\n"); } fwrite($this->fp, "\t\t</".GetMessage("IBLOCK_XML2_PRODUCT_SETS").">\n"); } } function ExportProductSets() { if ($this->next_step["catalog"] && $this->bExtended) { unset($this->next_step["FILTER"][">ID"]); $rsElements = CIBlockElement::GetList(array(), $this->next_step["FILTER"], false, false, array("ID", "XML_ID")); fwrite($this->fp, "\t<".GetMessage("IBLOCK_XML2_PRODUCTS_SETS").">\n"); while($arElement = $rsElements->Fetch()) { if (CCatalogProductSet::isProductHaveSet($arElement["ID"], CCatalogProductSet::TYPE_GROUP)) { if($arElement["XML_ID"] <> '') $xml_id = $arElement["XML_ID"]; else $xml_id = $arElement["ID"]; $this->ExportProductSet($arElement["ID"], $xml_id); } } fwrite($this->fp, "\t</".GetMessage("IBLOCK_XML2_PRODUCTS_SETS").">\n"); } } function EndExport() { fwrite($this->fp, "</".GetMessage("IBLOCK_XML2_COMMERCE_INFO").">\n"); } } /* GetMessage("IBLOCK_XML2_COEFF") GetMessage("IBLOCK_XML2_OWNER") GetMessage("IBLOCK_XML2_TITLE") GetMessage("IBLOCK_XML2_VALUES_TYPE") GetMessage("IBLOCK_XML2_VIEW") */