• Модуль: iblock
  • Путь к файлу: ~/bitrix/modules/iblock/classes/general/comp_pricetools.php
  • Класс: CIBlockPriceTools
  • Вызов: CIBlockPriceTools::GetOffersArray
static function GetOffersArray($arFilter, $arElementID, $arOrder, $arSelectFields, $arSelectProperties, $limit, $arPrices, $vat_include, $arCurrencyParams = array(), $USER_ID = 0, $LID = SITE_ID)
{
	global $USER;

	$arResult = array();

	$boolCheckPermissions = false;
	$boolHideNotAvailable = false;
	$showPriceCount = false;
	$customFilter = false;
	$IBLOCK_ID = 0;

	if (!empty($arFilter) && is_array($arFilter))
	{
		if (isset($arFilter['IBLOCK_ID']))
			$IBLOCK_ID = $arFilter['IBLOCK_ID'];
		if (isset($arFilter['HIDE_NOT_AVAILABLE']))
			$boolHideNotAvailable = ($arFilter['HIDE_NOT_AVAILABLE'] === 'Y');
		if (isset($arFilter['CHECK_PERMISSIONS']))
			$boolCheckPermissions = ($arFilter['CHECK_PERMISSIONS'] === 'Y');
		if (isset($arFilter['SHOW_PRICE_COUNT']))
		{
			$showPriceCount = (int)$arFilter['SHOW_PRICE_COUNT'];
			if ($showPriceCount <= 0)
				$showPriceCount = false;
		}

		if (isset($arFilter['CUSTOM_FILTER']))
		{
			$customFilter = $arFilter['CUSTOM_FILTER'];
		}
	}
	else
	{
		$IBLOCK_ID = $arFilter;
	}

	if (self::$needDiscountCache === null)
	{
		if(BitrixMainConfigOption::get('sale', 'use_sale_discount_only') === 'Y')
		{
			self::$needDiscountCache = false;
		}
		else
		{
			$pricesAllow = CIBlockPriceTools::GetAllowCatalogPrices($arPrices);
			if (empty($pricesAllow))
			{
				self::$needDiscountCache = false;
			}
			else
			{
				$USER_ID = (int)$USER_ID;
				$userGroups = array(2);
				if ($USER_ID > 0)
					$userGroups = CUser::GetUserGroup($USER_ID);
				elseif (isset($USER) && $USER instanceof CUser)
					$userGroups = $USER->GetUserGroupArray();
				self::$needDiscountCache = CIBlockPriceTools::SetCatalogDiscountCache($pricesAllow, $userGroups);
				unset($userGroups);
			}
			unset($pricesAllow);
		}
	}

	$arOffersIBlock = CIBlockPriceTools::GetOffersIBlock($IBLOCK_ID);
	if($arOffersIBlock)
	{
		$arDefaultMeasure = CCatalogMeasure::getDefaultMeasure(true, true);

		$limit = (int)$limit;
		if (0 > $limit)
			$limit = 0;

		if (!isset($arOrder["ID"]))
			$arOrder["ID"] = "DESC";

		$intOfferIBlockID = $arOffersIBlock["OFFERS_IBLOCK_ID"];

		$productProperty = 'PROPERTY_'.$arOffersIBlock['OFFERS_PROPERTY_ID'];
		$productPropertyValue = $productProperty.'_VALUE';

		$propertyList = array();
		if (!empty($arSelectProperties))
		{
			$selectProperties = array_fill_keys($arSelectProperties, true);
			$propertyIterator = IblockPropertyTable::getList(array(
				'select' => array('ID', 'CODE'),
				'filter' => array('=IBLOCK_ID' => $intOfferIBlockID, '=ACTIVE' => 'Y'),
				'order' => array('SORT' => 'ASC', 'ID' => 'ASC')
			));
			while ($property = $propertyIterator->fetch())
			{
				$code = (string)$property['CODE'];
				if ($code == '')
					$code = $property['ID'];
				if (!isset($selectProperties[$code]))
					continue;
				$propertyList[] = $code;
				unset($code);
			}
			unset($property, $propertyIterator);
			unset($selectProperties);
		}

		$arFilter = array(
			"IBLOCK_ID" => $intOfferIBlockID,
			$productProperty => $arElementID,
			"ACTIVE" => "Y",
			"ACTIVE_DATE" => "Y",
		);

		if (!empty($customFilter))
		{
			$arFilter[] = $customFilter;
		}

		if ($boolHideNotAvailable)
			$arFilter['CATALOG_AVAILABLE'] = 'Y';
		if ($boolCheckPermissions)
		{
			$arFilter['CHECK_PERMISSIONS'] = "Y";
			$arFilter['MIN_PERMISSION'] = "R";
		}

		$arSelect = array(
			"ID" => 1,
			"IBLOCK_ID" => 1,
			$productProperty => 1,
			"CATALOG_QUANTITY" => 1
		);
		//if(!$arParams["USE_PRICE_COUNT"])
		{
			foreach($arPrices as $value)
			{
				if (!$value['CAN_VIEW'] && !$value['CAN_BUY'])
					continue;
				$arSelect[$value["SELECT"]] = 1;
				if ($showPriceCount !== false)
				{
					$arFilter['CATALOG_SHOP_QUANTITY_'.$value['ID']] = $showPriceCount;
				}
			}
		}

		if (!empty($arSelectFields))
		{
			foreach ($arSelectFields as $code)
				$arSelect[$code] = 1; //mark to select
			unset($code);
		}
		$checkFields = array();
		foreach (array_keys($arOrder) as $code)
		{
			$code = mb_strtoupper($code);
			$arSelect[$code] = 1;
			if ($code == 'ID' || $code == 'CATALOG_AVAILABLE')
				continue;
			$checkFields[] = $code;
		}
		unset($code);

		if (!isset($arSelect['PREVIEW_PICTURE']))
			$arSelect['PREVIEW_PICTURE'] = 1;
		if (!isset($arSelect['DETAIL_PICTURE']))
			$arSelect['DETAIL_PICTURE'] = 1;

		$arOfferIDs = array();
		$arMeasureMap = array();
		$intKey = 0;
		$arOffersPerElement = array();
		$arOffersLink = array();
		$extPrices = array();
		$rsOffers = CIBlockElement::GetList($arOrder, $arFilter, false, false, array_keys($arSelect));
		while($arOffer = $rsOffers->GetNext())
		{
			$arOffer['ID'] = (int)$arOffer['ID'];
			$element_id = (int)$arOffer[$productPropertyValue];
			//No more than limit offers per element
			if ($limit > 0)
			{
				$arOffersPerElement[$element_id] ??= 0;
				$arOffersPerElement[$element_id]++;
				if($arOffersPerElement[$element_id] > $limit)
					continue;
			}

			if($element_id > 0)
			{
				$arOffer['SORT_HASH'] = 'ID';
				if (!empty($checkFields))
				{
					$checkValues = '';
					foreach ($checkFields as $code)
						$checkValues .= (isset($arOffer[$code]) ? $arOffer[$code] : '').'|';
					unset($code);
					if ($checkValues != '')
						$arOffer['SORT_HASH'] = md5($checkValues);
					unset($checkValues);
				}
				$arOffer["LINK_ELEMENT_ID"] = $element_id;
				$arOffer["PROPERTIES"] = array();
				$arOffer["DISPLAY_PROPERTIES"] = array();

				IblockComponentTools::getFieldImageData(
					$arOffer,
					array('PREVIEW_PICTURE', 'DETAIL_PICTURE'),
					IblockComponentTools::IPROPERTY_ENTITY_ELEMENT,
					''
				);

				$arOffer['CHECK_QUANTITY'] = ('Y' == $arOffer['CATALOG_QUANTITY_TRACE'] && 'N' == $arOffer['CATALOG_CAN_BUY_ZERO']);
				$arOffer['CATALOG_TYPE'] = CCatalogProduct::TYPE_OFFER;
				$arOffer['CATALOG_MEASURE_NAME'] = $arDefaultMeasure['SYMBOL_RUS'];
				$arOffer['~CATALOG_MEASURE_NAME'] = $arDefaultMeasure['SYMBOL_RUS'];
				$arOffer["CATALOG_MEASURE_RATIO"] = 1;
				if (!isset($arOffer['CATALOG_MEASURE']))
					$arOffer['CATALOG_MEASURE'] = 0;
				$arOffer['CATALOG_MEASURE'] = (int)$arOffer['CATALOG_MEASURE'];
				if (0 > $arOffer['CATALOG_MEASURE'])
					$arOffer['CATALOG_MEASURE'] = 0;
				if (0 < $arOffer['CATALOG_MEASURE'])
				{
					if (!isset($arMeasureMap[$arOffer['CATALOG_MEASURE']]))
						$arMeasureMap[$arOffer['CATALOG_MEASURE']] = array();
					$arMeasureMap[$arOffer['CATALOG_MEASURE']][] = $intKey;
				}

				$arOfferIDs[] = $arOffer['ID'];
				$arResult[$intKey] = $arOffer;
				if (!isset($arOffersLink[$arOffer['ID']]))
				{
					$arOffersLink[$arOffer['ID']] = &$arResult[$intKey];
				}
				else
				{
					if (!isset($extPrices[$arOffer['ID']]))
					{
						$extPrices[$arOffer['ID']] = array();
					}
					$extPrices[$arOffer['ID']][] = &$arResult[$intKey];
				}
				$intKey++;
			}
		}
		if (!empty($arOfferIDs))
		{
			$rsRatios = CCatalogMeasureRatio::getList(
				array(),
				array('@PRODUCT_ID' => $arOfferIDs),
				false,
				false,
				array('PRODUCT_ID', 'RATIO')
			);
			while ($arRatio = $rsRatios->Fetch())
			{
				$arRatio['PRODUCT_ID'] = (int)$arRatio['PRODUCT_ID'];
				if (isset($arOffersLink[$arRatio['PRODUCT_ID']]))
				{
					$intRatio = (int)$arRatio['RATIO'];
					$dblRatio = (float)$arRatio['RATIO'];
					$mxRatio = ($dblRatio > $intRatio ? $dblRatio : $intRatio);
					if (CATALOG_VALUE_EPSILON > abs($mxRatio))
						$mxRatio = 1;
					elseif (0 > $mxRatio)
						$mxRatio = 1;
					$arOffersLink[$arRatio['PRODUCT_ID']]['CATALOG_MEASURE_RATIO'] = $mxRatio;
				}
			}

			if (!empty($propertyList))
			{
				CIBlockElement::GetPropertyValuesArray($arOffersLink, $intOfferIBlockID, $arFilter);
				foreach ($arResult as &$arOffer)
				{
					if (self::$needDiscountCache)
						CCatalogDiscount::SetProductPropertiesCache($arOffer['ID'], $arOffer["PROPERTIES"]);
					if (BitrixMainConfigOption::get('sale', 'use_sale_discount_only') === 'Y')
						CatalogDiscountDiscountManager::setProductPropertiesCache($arOffer['ID'], $arOffer["PROPERTIES"]);

					foreach ($propertyList as $pid)
					{
						if (!isset($arOffer["PROPERTIES"][$pid]))
							continue;
						$prop = &$arOffer["PROPERTIES"][$pid];
						$boolArr = is_array($prop["VALUE"]);
						if(
							($boolArr && !empty($prop["VALUE"])) ||
							(!$boolArr && (string)$prop["VALUE"] !== '')
						)
						{
							$arOffer["DISPLAY_PROPERTIES"][$pid] = CIBlockFormatProperties::GetDisplayValue($arOffer, $prop);
						}
						unset($boolArr, $prop);
					}
					unset($pid);
				}
				unset($arOffer);
			}

			if (!empty($extPrices))
			{
				foreach ($extPrices as $origID => $prices)
				{
					foreach ($prices as $oneRow)
					{
						$oneRow['PROPERTIES'] = $arOffersLink[$origID]['PROPERTIES'];
						$oneRow['DISPLAY_PROPERTIES'] = $arOffersLink[$origID]['DISPLAY_PROPERTIES'];
						$oneRow['CATALOG_MEASURE_RATIO'] = $arOffersLink[$origID]['CATALOG_MEASURE_RATIO'];
					}
				}
			}
			if (self::$needDiscountCache)
			{
				CCatalogDiscount::SetProductSectionsCache($arOfferIDs);
				CCatalogDiscount::SetDiscountProductCache($arOfferIDs, array('IBLOCK_ID' => $intOfferIBlockID, 'GET_BY_ID' => 'Y'));
			}
			if (BitrixMainConfigOption::get('sale', 'use_sale_discount_only') === 'Y')
			{
				$pricesAllow = CIBlockPriceTools::GetAllowCatalogPrices($arPrices);
				if (!empty($pricesAllow))
				{
					$USER_ID = (int)$USER_ID;
					$userGroups = array(2);
					if ($USER_ID > 0)
						$userGroups = CUser::GetUserGroup($USER_ID);
					elseif (isset($USER) && $USER instanceof CUser)
						$userGroups = $USER->GetUserGroupArray();
					CatalogDiscountDiscountManager::preloadPriceData($arOfferIDs, $pricesAllow);
					CatalogDiscountDiscountManager::preloadProductDataToExtendOrder($arOfferIDs, $userGroups);
					unset($userGroups);
				}
				unset($pricesAllow);
			}
			foreach ($arResult as &$arOffer)
			{
				$arOffer['CATALOG_QUANTITY'] = (
					0 < $arOffer['CATALOG_QUANTITY'] && is_float($arOffer['CATALOG_MEASURE_RATIO'])
					? (float)$arOffer['CATALOG_QUANTITY']
					: (int)$arOffer['CATALOG_QUANTITY']
				);
				$arOffer['MIN_PRICE'] = false;
				$arOffer["PRICES"] = CIBlockPriceTools::GetItemPrices($arOffersIBlock["OFFERS_IBLOCK_ID"], $arPrices, $arOffer, $vat_include, $arCurrencyParams, $USER_ID, $LID);
				if (!empty($arOffer["PRICES"]))
				{
					foreach ($arOffer['PRICES'] as &$arOnePrice)
					{
						if ($arOnePrice['MIN_PRICE'] == 'Y')
						{
							$arOffer['MIN_PRICE'] = $arOnePrice;
							break;
						}
					}
					unset($arOnePrice);
				}
				$arOffer["CAN_BUY"] = CIBlockPriceTools::CanBuy($arOffersIBlock["OFFERS_IBLOCK_ID"], $arPrices, $arOffer);
			}
			if (isset($arOffer))
				unset($arOffer);
		}
		if (!empty($arMeasureMap))
		{
			$rsMeasures = CCatalogMeasure::getList(
				array(),
				array('@ID' => array_keys($arMeasureMap)),
				false,
				false,
				array('ID', 'SYMBOL_RUS')
			);
			while ($arMeasure = $rsMeasures->GetNext())
			{
				$arMeasure['ID'] = (int)$arMeasure['ID'];
				if (isset($arMeasureMap[$arMeasure['ID']]) && !empty($arMeasureMap[$arMeasure['ID']]))
				{
					foreach ($arMeasureMap[$arMeasure['ID']] as $intOneKey)
					{
						$arResult[$intOneKey]['CATALOG_MEASURE_NAME'] = $arMeasure['SYMBOL_RUS'];
						$arResult[$intOneKey]['~CATALOG_MEASURE_NAME'] = $arMeasure['~SYMBOL_RUS'];
					}
					unset($intOneKey);
				}
			}
		}
	}

	return $arResult;
}