• Модуль: catalog
  • Путь к файлу: ~/bitrix/modules/catalog/lib/product/catalogprovider.php
  • Класс: BitrixCatalogProductCatalogProvider
  • Вызов: CatalogProvider::getBundleItems
public function getBundleItems(array $products)
	{
		$result = new SaleResult();

		$resultList = array();

		$productIdList = array();
		static $proxyCatalogProductSet = array();
		static $proxyCatalogSkuData = array();
		$bundleItemList = array();

		$bundleIndex = array();

		foreach ($products as $productId => $productData)
		{
			$proxyCatalogProductSetKey = $productId."|".static::BUNDLE_TYPE;
			if (!empty($proxyCatalogProductSet[$proxyCatalogProductSetKey]) && is_array($proxyCatalogProductSet[$proxyCatalogProductSetKey]))
			{
				$childItemList = $proxyCatalogProductSet[$proxyCatalogProductSetKey];
			}
			else
			{
				$childItemList = CCatalogProductSet::getAllSetsByProduct($productId, static::BUNDLE_TYPE);
				if (!empty($childItemList) && is_array($childItemList))
				{
					$proxyCatalogProductSet[$proxyCatalogProductSetKey] = $childItemList;
				}
			}

			if (!empty($childItemList))
			{
				$bundleItemList = $childItemList + $bundleItemList;
				$bundleItemListIds = array_keys($childItemList);
				$bundleItemId = reset($bundleItemListIds);
				unset($bundleItemListIds);
				$bundleIndex[$bundleItemId] = $productId;
			}
		}

		$childIdList = array();

		if (empty($bundleItemList))
			return $result;

		$bundleChildList = array();
		$childProducts = array();
		$productIndexList = array();
		foreach ($bundleItemList as $parentItemid => $bundleItemData)
		{
			$productId = $bundleIndex[$parentItemid];
			foreach ($bundleItemData["ITEMS"] as $childItemid => $item)
			{
				if (!isset($childIdList[$item['ITEM_ID']]))
					$childIdList[$item['ITEM_ID']] = true;

				$bundleChildList[$item['ITEM_ID']] = $item;
				$childProducts[$item['ITEM_ID']] = array(
					'ITEM_CODE' => $item['ITEM_ID'],
					'PRODUCT_ID' => $item['ITEM_ID'],
					Base::FLAT_QUANTITY_LIST => [$item['ITEM_ID'] => $item['QUANTITY']],
					'BUNDLE_CHILD' => true,
				);

				$productIndexList[$item['ITEM_ID']] = array(
					'PRODUCT_ID' => $productId,
					'PARENT_ID' => $parentItemid,
					'CHILD_ID' => $childItemid
				);
			}
		}

		$r = $this->getProductData($childProducts);
		if ($r->isSuccess())
		{
			$resultData = $r->getData();
			if (
				!empty($resultData[Base::SUMMMARY_PRODUCT_LIST])
				&& is_array($resultData[Base::SUMMMARY_PRODUCT_LIST])
			)
			{
				$resultDataList = $resultData[Base::SUMMMARY_PRODUCT_LIST];
				foreach ($resultDataList as $itemCode => $itemData)
				{
					$item = $bundleChildList[$itemCode];
					if (array_key_exists('QUANTITY_TRACE', $itemData))
						unset($itemData['QUANTITY_TRACE']);

					$itemData["PRODUCT_ID"] = $item["ITEM_ID"];
					$itemData["MODULE"] = 'catalog';
					$itemData["PRODUCT_PROVIDER_CLASS"] = Basket::getDefaultProviderName();

					$productIdList[] = $item["ITEM_ID"];

					$itemData["PROPS"] = array();

					if (!empty($proxyCatalogSkuData[$item["ITEM_ID"]]) && is_array($proxyCatalogSkuData[$item["ITEM_ID"]]))
					{
						$parentSkuData = $proxyCatalogSkuData[$item["ITEM_ID"]];
					}
					else
					{
						$parentSkuData = CCatalogSku::GetProductInfo($item["ITEM_ID"]);
						if ($parentSkuData)
						{
							$proxyCatalogSkuData[$item["ITEM_ID"]] = $parentSkuData;
						}
					}

					if (!empty($parentSkuData))
					{
						$childDataList = array();
						$childIdGetList = array();

						$iblockPropertyDataList = array();
						$iblockPropertyIdList = array();

						$propsSku = array();

						foreach ($childIdList as $childId => $parentValue)
						{
							$productData = static::getHitCache(self::CACHE_ELEMENT_SHORT_DATA, $item["ITEM_ID"]);
							if (!empty($productData))
							{
								$childDataList[$childId] = $productData;
								if (!isset($iblockPropertyIdList[$productData['IBLOCK_ID']]))
								{
									$iblockPropertyIdList[$productData['IBLOCK_ID']] = true;
								}
							}
							else
							{
								$childIdGetList[] = $childId;
							}
						}

						if (!empty($childIdGetList))
						{
							$iterator = IblockElementTable::getList([
								'select' => [
									'ID',
									'IBLOCK_ID',
									'NAME',
									'IBLOCK_SECTION_ID',
								],
								'filter' => CIBlockElement::getPublicElementsOrmFilter(['@ID' => $childIdGetList]),
							]);
							while ($productData = $iterator->fetch())
							{
								static::setHitCache(self::CACHE_ELEMENT_SHORT_DATA, $productData["ID"], $productData);
								$childDataList[$productData["ID"]] = $productData;

								if (!isset($iblockPropertyIdList[$productData['IBLOCK_ID']]))
								{
									$iblockPropertyIdList[$productData['IBLOCK_ID']] = true;
								}
							}
						}

						foreach ($iblockPropertyIdList as $iblockPropertyId => $iblockPropertyValue)
						{
							if ($propsSku = static::getHitCache('IBLOCK_PROPERTY', $iblockPropertyId))
							{
								$iblockPropertyDataList[$iblockPropertyId] = $propsSku;
							}
							else
							{
								$dbOfferProperties = CIBlock::GetProperties($iblockPropertyId, array(), array("!XML_ID" => "CML2_LINK"));
								while($offerProperties = $dbOfferProperties->Fetch())
								{
									$propsSku[] = $offerProperties["CODE"];
								}
								static::setHitCache('IBLOCK_PROPERTY', $iblockPropertyId, $propsSku);
							}
						}

						$propSkuHash = (!empty($propsSku)) ? md5(join('|', $propsSku)): md5($item["ITEM_ID"]);

						$proxyProductPropertyKey = $item["ITEM_ID"]."_".$parentSkuData["IBLOCK_ID"]."_".$propSkuHash;

						$productProperties = static::getHitCache('PRODUCT_PROPERTY', $proxyProductPropertyKey);
						if (empty($productProperties))
						{
							$productProperties = CIBlockPriceTools::GetOfferProperties(
								$item["ITEM_ID"],
								$parentSkuData["IBLOCK_ID"],
								$propsSku
							);

							static::setHitCache('PRODUCT_PROPERTY', $proxyProductPropertyKey, $productProperties);
						}

						if (!empty($productProperties))
						{
							foreach ($productProperties as $propData)
							{
								$itemData["PROPS"][] = array(
									"NAME" => $propData["NAME"],
									"CODE" => $propData["CODE"],
									"VALUE" => $propData["VALUE"],
									"SORT" => $propData["SORT"]
								);
							}
						}

					}

					$parentProductIndexData = $productIndexList[$itemCode];

					$priceData = array();
					if (!empty($itemData['PRICE_LIST']))
					{
						$priceData = reset($itemData['PRICE_LIST']);
						unset($itemData['PRICE_LIST']);
					}

					if (array_key_exists('PRODUCT', $itemData))
					{
						unset($itemData['PRODUCT']);
					}

					$bundleItemList[$parentProductIndexData['PARENT_ID']]["ITEMS"][$parentProductIndexData['CHILD_ID']] = array_merge($item,  $itemData, $priceData);
				}
			}
		}

		$elementList = static::getHitCache('IBLOCK_ELEMENT_LIST', $productId);
		if (empty($elementList))
		{
			$productRes = CIBlockElement::GetList(
				array(),
				array('ID' => $productIdList),
				false,
				false,
				array("ID", "IBLOCK_ID", "IBLOCK_SECTION_ID", "PREVIEW_PICTURE", "DETAIL_PICTURE", "IBLOCK_TYPE_ID", "XML_ID")
			);
			while ($productData = $productRes->GetNext())
			{
				$elementList[$productData['ID']] = $productData;
			}

			if (!empty($elementList) && is_array($elementList))
			{
				static::setHitCache('IBLOCK_ELEMENT_LIST', $productId, $elementList);
			}
		}

		if (!empty($elementList) && is_array($elementList))
		{
			foreach ($bundleItemList as $bundleParentId => $bundleItemData)
			{
				foreach ($bundleItemData["ITEMS"] as $bundleChildId => $item)
				{
					if (!$elementList[$item["ITEM_ID"]])
						continue;

					$elementData = $elementList[$item["ITEM_ID"]];

					$properties = array();
					$strIBlockXmlID = (string)CIBlock::GetArrayByID($elementData['IBLOCK_ID'], 'XML_ID');
					if ($strIBlockXmlID != "")
					{
						$properties[] = array(
							"NAME" => "Catalog XML_ID",
							"CODE" => "CATALOG.XML_ID",
							"VALUE" => $strIBlockXmlID
						);

						$elementData['CATALOG_XML_ID'] = $strIBlockXmlID;

					}

					if (!empty($proxyCatalogSkuData[$item["ITEM_ID"]]) && strpos($elementData["XML_ID"], '#') === false)
					{
						$parentSkuData = $proxyCatalogSkuData[$item["ITEM_ID"]];
						if (!empty($proxyParentData[$parentSkuData['ID']]) && is_array($proxyParentData[$parentSkuData['ID']]))
						{
							$parentData = $proxyParentData[$parentSkuData['ID']];
						}
						else
						{
							$parentIterator = IblockElementTable::getList(
								array(
									'select' => array('ID', 'XML_ID'),
									'filter' => array('ID' => $parentSkuData['ID'])
								)
							);

							$parentData = $parentIterator->fetch();
							if (!empty($parentData))
							{
								$proxyParentData[$parentSkuData['ID']] = $parentData;
							}

							unset($parentIterator);
						}

						$elementData["XML_ID"] = $parentData['XML_ID'].'#'.$elementData["XML_ID"];
						unset($parentData);
					}

					$properties[] = array(
						"NAME" => "Product XML_ID",
						"CODE" => "PRODUCT.XML_ID",
						"VALUE" => $elementData["XML_ID"]
					);

					$bundleItemData = $bundleItemList[$bundleParentId]["ITEMS"][$bundleChildId];

					$bundleItemProps = array();
					if (is_array($elementData["PROPS"]) && !empty($elementData["PROPS"]))
					{
						$bundleItemProps = $elementData["PROPS"];
					}

					if (!empty($properties))
					{
						$bundleItemProps = $bundleItemProps + $properties;
					}

					$bundleItemList[$bundleParentId]["ITEMS"][$bundleChildId] = $bundleItemData + array(
							'IBLOCK_ID' => $elementData["IBLOCK_ID"],
							'IBLOCK_SECTION_ID' => $elementData["IBLOCK_SECTION_ID"],
							'PREVIEW_PICTURE' => $elementData["PREVIEW_PICTURE"],
							'DETAIL_PICTURE' => $elementData["DETAIL_PICTURE"],

							'CATALOG_XML_ID' => $elementData["CATALOG_XML_ID"],
							'PRODUCT_XML_ID' => $elementData["XML_ID"],
						);

					$bundleItemList[$bundleParentId]["ITEMS"][$bundleChildId]['PROPS'] = $bundleItemProps;
				}
			}

		}

		foreach(GetModuleEvents("sale", "OnGetSetItems", true) as $eventData)
		{
			ExecuteModuleEventEx($eventData, array(&$bundleItemList));
		}

		if (!empty($bundleItemList))
		{
			foreach ($bundleItemList as $bundleParentId => $bundleData)
			{
				if (empty($bundleIndex[$bundleParentId]))
					continue;

				$productId = $bundleIndex[$bundleParentId];

				$resultList[$productId] = $bundleData;
			}

			$result->setData(
				array(
					'BUNDLE_LIST' => $resultList
				)
			);
		}

		return $result;
	}