• Модуль: iblock
  • Путь к файлу: ~/bitrix/modules/iblock/lib/component/elementlist.php
  • Класс: BitrixIblockComponentElementList
  • Вызов: ElementList::sortItemsByTemplateVariants
protected function sortItemsByTemplateVariants()
{
	$rows = array();
	$variantsMap = static::getTemplateVariantsMap();
	$isBigData = $this->getAction() === 'bigDataLoad';

	if ($this->arParams['ENLARGE_PRODUCT'] === 'PROP')
	{
		$enlargedIndexMap = $this->getEnlargedIndexMap();
	}

	if (!empty($this->arParams['PRODUCT_ROW_VARIANTS']))
	{
		$showItems = false;

		foreach ($this->arParams['PRODUCT_ROW_VARIANTS'] as $variant)
		{
			if (
				(!$isBigData && !$variant['BIG_DATA'])
				|| ($isBigData && $variant['BIG_DATA'])
			)
			{
				$showItems = true;
				break;
			}
		}
	}
	else
	{
		$showItems = true;
	}

	if ($showItems)
	{
		$variantParam = false;
		$itemsCounter = 0;
		$itemsLength = count($this->arResult['ITEMS']);

		while (($itemsRemaining = $itemsLength - $itemsCounter) > 0)
		{
			if ($variantParam === false)
			{
				$variantParam = reset($this->arParams['PRODUCT_ROW_VARIANTS']);
			}

			//	skip big_data rows on initial load and not_big_data rows on deferred load
			if (!empty($variantParam))
			{
				if (
					$isBigData && !$variantParam['BIG_DATA']
					|| !$isBigData && $variantParam['BIG_DATA']
				)
				{
					$variantParam = next($this->arParams['PRODUCT_ROW_VARIANTS']);
					// if last variant is not suitable - should reset again
					if ($variantParam === false)
					{
						$variantParam = reset($this->arParams['PRODUCT_ROW_VARIANTS']);
					}

					if ($variantParam === false)
						break;
					else
						continue;
				}
			}

			if (
				$variantParam === false
				|| !isset($variantsMap[$variantParam['VARIANT']])
				|| ($variantsMap[$variantParam['VARIANT']]['SHOW_ONLY_FULL'] && $variantsMap[$variantParam['VARIANT']]['COUNT'] > $itemsRemaining)
			)
			{
				// default variant
				$variant = $variantsMap[self::getDefaultVariantId()];
			}
			else
			{
				$variant = $variantsMap[$variantParam['VARIANT']];
			}

			// sorting by property $arResult['ITEMS'] for proper elements enlarge
			if ($this->arParams['ENLARGE_PRODUCT'] === 'PROP' && $variant['ENLARGED_POS'] !== false)
			{
				if (!empty($enlargedIndexMap))
				{
					$overallPos = $itemsCounter + $variant['ENLARGED_POS'];
					$overallPosKey = array_search($overallPos, $enlargedIndexMap);
					if ($overallPosKey === false)
					{
						$closestPos = false;
						$closestPosKey = false;
						$enlargedPosInRange = array_intersect($enlargedIndexMap , range($itemsCounter, $itemsCounter + $variant['COUNT']));

						if (!empty($enlargedPosInRange))
						{
							foreach ($enlargedPosInRange as $key => $posInRange)
							{
								if ($closestPos === false || abs($overallPos - $closestPos) > abs($posInRange - $overallPos))
								{
									$closestPos = $posInRange;
									$closestPosKey = $key;
								}
							}

							$temporary = array($this->arResult['ITEMS'][$closestPos]);
							unset($this->arResult['ITEMS'][$closestPos], $enlargedIndexMap[$closestPosKey]);
							array_splice($this->arResult['ITEMS'], $overallPos, 0, $temporary);
						}
					}
					else
					{
						unset($enlargedIndexMap[$overallPosKey]);
					}
				}
			}

			$rows[] = $variant;
			$itemsCounter += $variant['COUNT'];
			$variantParam = next($this->arParams['PRODUCT_ROW_VARIANTS']);
		}
	}

	$this->arResult['ITEM_ROWS'] = $rows;
}