diff --git a/intaro.intarocrm/classes/general/ICMLLoader.php b/intaro.intarocrm/classes/general/ICMLLoader.php index af3ea5ac..eeb111bb 100644 --- a/intaro.intarocrm/classes/general/ICMLLoader.php +++ b/intaro.intarocrm/classes/general/ICMLLoader.php @@ -14,19 +14,29 @@ class ICMLLoader { protected $fp; protected $mainSection = 1000000; - + protected $pageSize = 500; + + protected $isLogged = false; + protected $logFile = '/bitrix/catalog_export/i_crm_load_log.txt'; + protected $fpLog; + public function Load() { global $USER; if(!isset($USER)) $USER = new CUser; - - if (count($this->iblocks) < count($this->articleProperties)) - return false; + + $this->isLogged = true; + $this->PrepareSettings(); + + $this->fp = $this->PrepareFile($this->filename); - $this->PrepareFile(); + if ($this->isLogged) { + $this->fpLog = $this->PrepareFile($this->logFile); + $this->WriteLog("Start Loading"); + } $this->PreWriteCatalog(); @@ -40,11 +50,18 @@ class ICMLLoader { $this->PostWriteCatalog(); - $this->CloseFile(); + if ($this->isLogged) { + $this->WriteLog("Loading was ended successfully (peek memory usage: " . memory_get_peak_usage() . ")"); + } + + $this->CloseFile($this->fp); + $this->CloseFile($this->fpLog); + + return true; } - + protected function PrepareSettings() { foreach ($this->propertiesSKU as $iblock => $arr) { @@ -58,7 +75,7 @@ class ICMLLoader { } } } - + protected function PrepareValue($text) { $newText = $this->application->ConvertCharset($text, LANG_CHARSET, $this->encoding); @@ -67,15 +84,15 @@ class ICMLLoader { return $newText; } - protected function PrepareFile() + protected function PrepareFile($filename) { - $fullFilename = $_SERVER["DOCUMENT_ROOT"] . $this->filename; + $fullFilename = $_SERVER["DOCUMENT_ROOT"] . $filename; CheckDirPath($fullFilename); - if (!$this->fp = @fopen($fullFilename, "w")) - return false; + if ($fp = @fopen($fullFilename, "w")) + return $fp; else - return true; + return false; } protected function PreWriteCatalog() @@ -112,6 +129,12 @@ class ICMLLoader { { @fwrite($this->fp, $offers); } + + protected function WriteLog($text) + { + if ($this->isLogged) + @fwrite($this->fpLog, Date("Y:m:d H:i:s") . ": " . $text . "\n"); + } protected function PostWriteCatalog() { @@ -119,9 +142,9 @@ class ICMLLoader { \n"); } - protected function CloseFile() + protected function CloseFile($fp) { - @fclose($this->fp); + @fclose($fp); } @@ -132,9 +155,7 @@ class ICMLLoader { { $filter = Array( "IBLOCK_ID" => $id, - "ACTIVE" => "Y", - "IBLOCK_ACTIVE" => "Y", - "GLOBAL_ACTIVE" => "Y" + ); $dbRes = CIBlockSection::GetList(array("left_margin" => "asc"), $filter); @@ -176,6 +197,7 @@ class ICMLLoader { { foreach ($this->iblocks as $key => $id) { + // Get Info by infoblocks $iblock['IBLOCK_DB'] = CIBlock::GetByID($id)->Fetch(); $iblockOffer = CCatalogSKU::GetInfoByProductIBlock($id); @@ -192,190 +214,261 @@ class ICMLLoader { "DETAIL_TEXT", "DETAIL_PICTURE", "LANG_DIR", - "DETAIL_PAGE_URL" + "DETAIL_PAGE_URL", + "CATALOG_GROUP_1" ); - foreach ($this->propertiesProduct[$id] as $key => $propProduct) { - if ($this->propertiesProduct[$id][$key] != "") - $arSelect[] = "PROPERTY_" . $propProduct; - } - + // Set selected properties + foreach ($this->propertiesProduct[$id] as $key => $propProduct) { + if ($this->propertiesProduct[$id][$key] != "") { + $arSelect[] = "PROPERTY_" . $propProduct; + $arSelect[] = "PROPERTY_" . $propProduct . ".NAME"; + } + } + + + // Set filter $filter = Array ( "IBLOCK_ID" => $id, - "ACTIVE_DATE" => "Y", - "ACTIVE" => "Y", "INCLUDE_SUBSECTIONS" => "Y" ); - $count = 0; - $dbResProducts = CIBlockElement::GetList(array(), $filter, false, false, $arSelect); - $stringOffers = ""; - while ($product = $dbResProducts->GetNextElement()) { - $product = $product->GetFields(); + $order = Array( + "id" + ); + + // Counter of pagenumber + $count = 1; + $isThisTheEnd = false; + + // Cycle page to page + while (!$isThisTheEnd) { - // Get properties of product - $resPropertiesProduct = Array(); - foreach ($this->propertiesProduct[$id] as $key => $propProduct) { - $resPropertiesProduct[$key] = ""; - if ($propProduct != "") { - $propDesc = CIBlockProperty::GetByID($propProduct, $id)->GetNext(); + $arNavStatParams = Array( - if ($propDesc['PROPERTY_TYPE'] == 'E') { - $el = CIBlockElement::GetById($product["PROPERTY_" . $propProduct . "_VALUE"])->Fetch(); - $resPropertiesProduct[$key] = $el['NAME']; - } else { - $resPropertiesProduct[$key] = $product["PROPERTY_" . $propProduct . "_VALUE"]; + "iNumPage" => $count, + "nPageSize" => $this->pageSize, + ); + + // Get products on this page + $dbResProducts = CIBlockElement::GetList($order, $filter, false, $arNavStatParams, $arSelect); + + // It's last page + if ($dbResProducts->NavPageCount == $count) { + $isThisTheEnd = true; + } + + $pictures = array(); + $products = array(); + while ($product = $dbResProducts->Fetch()) { + + // Compile products to array + $products[$product['ID']] = $product; + + $detailPicture = intval($product["DETAIL_PICTURE"]); + $previewPicture = intval($product["PREVIEW_PICTURE"]); + + if ($detailPicture > 0 || $previewPicture > 0) + { + $picture = $detailPicture; + if ($picture <= 0) { + $picture = $previewPicture; + } + + // Link pictureID and productID + $pictures[$picture] = $product['ID']; + } + } + unset($product, $dbResProducts); + unset($detailPicture, $previewPicture, $picture); + + $pictureIDs = array_keys($pictures); + + // Get pathes of pictures + $dbFiles = CFile::GetList(Array(), Array("@ID" => implode(',', $pictureIDs))); + while($file = $dbFiles->Fetch()) { + + // Link picture to product + $products[$pictures[$file['ID']]]['PICTURE'] = "http://" . + $iblock['IBLOCK_DB']['SERVER_NAME'] . + '/upload/' . $file['SUBDIR'] . + '/' . $file['FILE_NAME'] ; + } + unset($pictures); + + + if (!empty($iblockOffer['IBLOCK_ID'])) { + + + $productIDs = array_keys($products); + + $arSelectOffer = Array ( + 'ID', + "NAME", + "DETAIL_TEXT", + "DETAIL_PAGE_URL", + "DETAIL_PICTURE", + 'PROPERTY_' . $iblockOffer['SKU_PROPERTY_ID'], + "CATALOG_GROUP_1" + ); + $arFilterOffer = Array ( + 'IBLOCK_ID' => $iblockOffer['IBLOCK_ID'], + 'PROPERTY_' . $iblockOffer['SKU_PROPERTY_ID'] => $productIDs + ); + + // Set selected properties + foreach ($this->propertiesSKU[$id] as $key => $propSKU) { + if ($this->propertiesSKU[$id][$key] != "") { + $arSelectOffer[] = "PROPERTY_" . $propSKU; + $arSelectOffer[] = "PROPERTY_" . $propSKU . ".NAME"; + } + } + + // Get all offers for products on this page + $dbResOffers = CIBlockElement::GetList(array(), $arFilterOffer, false, false, $arSelectOffer); + + while ($offer = $dbResOffers->Fetch()) { + + // Link offers to products + $products[$offer['PROPERTY_' . $iblockOffer['SKU_PROPERTY_ID'] . '_VALUE']]['offers'][$offer['ID']] = $offer; + } + unset($offer, $dbResOffers); + } + + + + $stringOffers = ""; + foreach ($products as $product) { + + // Get properties of product + $resPropertiesProduct = Array(); + foreach ($this->propertiesProduct[$id] as $key => $propProduct) { + $resPropertiesProduct[$key] = ""; + + if ($propProduct != "") { + + if (isset ($product["PROPERTY_" . $propProduct . "_NAME"])) + $resPropertiesProduct[$key] = $product["PROPERTY_" . $propProduct . "_NAME"]; + else + $resPropertiesProduct[$key] = $product["PROPERTY_" . $propProduct . "_VALUE"]; } } - } - - // Get categories of product - $categories = Array(); - $dbResCategories = CIBlockElement::GetElementGroups($product['ID'], true); - while ($arResCategory = $dbResCategories->Fetch()) { - $categories[$arResCategory["ID"]] = array( - 'ID' => $arResCategory["ID"], - 'NAME' => $arResCategory["NAME"], - ); - } - if (count($categories) == 0) { - $catId = $this->mainSection + $id; - $categories[$catId] = $allCategories[$catId]; - } - - - $existOffer = false; - if (!empty($iblockOffer['IBLOCK_ID'])) { - - $arFilterOffer = Array ( - 'IBLOCK_ID' => $iblockOffer['IBLOCK_ID'], - 'PROPERTY_' . $iblockOffer['SKU_PROPERTY_ID'] => $product["ID"] + // Get categories of product + $categories = Array(); + $dbResCategories = CIBlockElement::GetElementGroups($product['ID'], true); + while ($arResCategory = $dbResCategories->Fetch()) { + $categories[$arResCategory["ID"]] = array( + 'ID' => $arResCategory["ID"], + 'NAME' => $arResCategory["NAME"], ); - $arSelectOffer = Array ( - 'ID', - "NAME", - "DETAIL_TEXT", - "DETAIL_PAGE_URL", - "DETAIL_PICTURE" - ); - - foreach ($this->propertiesSKU[$id] as $key => $propSKU) { - if ($this->propertiesSKU[$id][$key] != "") - $arSelectOffer[] = "PROPERTY_" . $propSKU; + } + if (count($categories) == 0) { + + $catId = $this->mainSection + $id; + $categories[$catId] = $allCategories[$catId]; } - $rsOffers = CIBlockElement::GetList(array(), $arFilterOffer, false, false, $arSelectOffer); - while ($arOffer = $rsOffers->GetNext()) { - $offer = CCatalogProduct::GetByID($arOffer['ID']); - $arOffer['QUANTITY'] = $offer["QUANTITY"]; - - $arOffer['PRODUCT_ID'] = $product["ID"]; - $arOffer['DETAIL_PAGE_URL'] = $product["DETAIL_PAGE_URL"]; - $arOffer['DETAIL_PICTURE'] = $product["DETAIL_PICTURE"]; - $arOffer['PREVIEW_PICTURE'] = $product["PREVIEW_PICTURE"]; - $arOffer['PRODUCT_NAME'] = $product["NAME"]; + $existOffer = false; + if (!empty($iblockOffer['IBLOCK_ID'])) { - // Get properties of offer - - foreach ($this->propertiesSKU[$id] as $key => $propSKU) { - if ($propSKU != "") { - $propDesc = CIBlockProperty::GetByID($propSKU,$arOffer['ID'])->GetNext(); + foreach ($product['offers'] as $offer) { - if ($propDesc['PROPERTY_TYPE'] == 'E') { - $el = CIBlockElement::GetById($product["PROPERTY_" . $propSKU . "_VALUE"])->Fetch(); - $arOffer[$key] = $el['NAME']; - } else { - $arOffer[$key] = $arOffer["PROPERTY_" . $propSKU . "_VALUE"]; + $offer['PRODUCT_ID'] = $product["ID"]; + $offer['DETAIL_PAGE_URL'] = $product["DETAIL_PAGE_URL"]; + $offer['PICTURE'] = $product["PICTURE"]; + $offer['PRODUCT_NAME'] = $product["NAME"]; + $offer['PRICE'] = $offer['CATALOG_PRICE_1']; + $offer['QUANTITY'] = $offer["CATALOG_QUANTITY"]; + + // Get properties of product + + foreach ($this->propertiesSKU[$id] as $key => $propSKU) { + + if ($propSKU != "") { + + if (isset ($product["PROPERTY_" . $propSKU . "_NAME"])) + $offer[$key] = $product["PROPERTY_" . $propSKU . "_NAME"]; + else + $offer[$key] = $product["PROPERTY_" . $propSKU . "_VALUE"]; } } + + foreach ($resPropertiesProduct as $key => $propProduct) { + if ($this->propertiesProduct[$id][$key] != "" && !isset($offer[$key])) + $offer[$key] = $propProduct; + } + + $stringOffers .= $this->BuildOffer($offer, $categories, $iblock, $allCategories); + $existOffer = true; } - + } + if (!$existOffer) { + + $product['PRODUCT_ID'] = $product["ID"]; + $product['PRODUCT_NAME'] = $product["NAME"]; + $product['PRICE'] = $product['CATALOG_PRICE_1']; + $product['QUANTITY'] = $product["CATALOG_QUANTITY"]; + foreach ($resPropertiesProduct as $key => $propProduct) { if ($this->propertiesProduct[$id][$key] != "") - $arOffer[$key] = $propProduct; + $product[$key] = $propProduct; } - - $dbPrice = GetCatalogProductPrice($arOffer["ID"],1); - $arOffer['PRICE'] = $dbPrice['PRICE']; - $stringOffers .= $this->BuildOffer($arOffer, $categories, $iblock); - $existOffer = true; - } - } - if (!$existOffer) { - - $offer = CCatalogProduct::GetByID($product['ID']); - $product['QUANTITY'] = $offer["QUANTITY"]; - - $product['PRODUCT_ID'] = $product["ID"]; - $product['PRODUCT_NAME'] = $product["NAME"]; - - foreach ($resPropertiesProduct as $key => $propProduct) { - if ($this->propertiesProduct[$id][$key] != "") - $product[$key] = $propProduct; + $stringOffers .= $this->BuildOffer($product, $categories, $iblock, $allCategories); } - $dbPrice = GetCatalogProductPrice($product["ID"],1); - $product['PRICE'] = $dbPrice['PRICE']; - - $stringOffers .= $this->BuildOffer($product, $categories, $iblock); - } - - $count++; - if ($count == 1000) { - $this->WriteOffers($stringOffers); - $stringOffers = ""; - } - + } + unset($products); + + if ($this->isLogged) + $this->WriteLog(($this->pageSize * $count) . " product(s) has been loaded from " . $id . " IB (memory usage: " . memory_get_usage() . ")"); + $count++; + if ($stringOffers != "") { + $this->WriteOffers($stringOffers); + $stringOffers = ""; + } } - - if ($stringOffers != "") { - $this->WriteOffers($stringOffers); - $stringOffers = ""; - } - } } - protected function BuildOffer($arOffer, $categories, $iblock) + protected function BuildOffer($arOffer, $categories, $iblock, &$allCategories) { $offer = ""; $offer .= "PrepareValue($arOffer["ID"]) . "\" ". "productId=\"" . $this->PrepareValue($arOffer["PRODUCT_ID"]) . "\" ". "quantity=\"" . $this->PrepareValue(DoubleVal($arOffer['QUANTITY'])) . "\">\n"; + $keys = array_keys($categories); + if (strpos($arOffer['DETAIL_PAGE_URL'], "#SECTION_PATH#") !== false) { + if (count($categories) != 0) { + + $category = $allCategories[$keys[0]]; + $path = $category['CODE']; + + if(intval($category["IBLOCK_SECTION_ID"] ) != 0) { + while (true) { + $category = $allCategories[$category['IBLOCK_SECTION_ID']]; + $path = $category['CODE'] . '/' . $path; + if(intval($category["IBLOCK_SECTION_ID"] ) == 0) + break; + } + } + + } + $arOffer['DETAIL_PAGE_URL'] = str_replace("#SECTION_PATH#", $path, $arOffer['DETAIL_PAGE_URL']); + } + + $offer .= "" . $this->PrepareValue($arOffer["PICTURE"]) . "\n"; $offer .= "http://" . $this->PrepareValue($iblock['IBLOCK_DB']['SERVER_NAME']) . $this->PrepareValue($arOffer['DETAIL_PAGE_URL']) . "\n"; $offer .= "" . $this->PrepareValue($arOffer['PRICE']) . "\n"; foreach ($categories as $category) $offer .= "" . $category['ID'] . "\n"; - $detailPicture = intval($arOffer["DETAIL_PICTURE"]); - $previewPicture = intval($arOffer["PREVIEW_PICTURE"]); - - if ($detailPicture > 0 || $previewPicture > 0) - { - $picture = $detailPicture; - if ($picture <= 0) { - $picture = $previewPicture; - } - - if ($arFile = CFile::GetFileArray($picture)) - { - if(substr($arFile["SRC"], 0, 1) == "/") - $strFile = "http://" . $this->PrepareValue($iblock['IBLOCK_DB']['SERVER_NAME']) . implode("/", array_map("rawurlencode", explode("/", $arFile["SRC"]))); - elseif(preg_match("/^(http|https):\\/\\/(.*?)\\/(.*)\$/", $arFile["SRC"], $match)) - $strFile = "http://" . $this->PrepareValue($match[2]) . '/' . implode("/", array_map("rawurlencode", explode("/", $this->PrepareValue($match[3])))); - else - $strFile = $arFile["SRC"]; - $offer .= "" . $this->PrepareValue($strFile) . "\n"; - } - } - $offer .= "" . $this->PrepareValue($arOffer["NAME"]) . "\n"; $offer .= "" . $this->PrepareValue($arOffer["EXTERNAL_ID"]) . "\n"; @@ -385,7 +478,7 @@ class ICMLLoader { if ($propProduct != "" && $arOffer[$key] != null) $offer .= "<" . $key . ">" . $this->PrepareValue($arOffer[$key]) . "\n"; } - + $offer.= "\n"; return $offer; }