3namespace Bitrix\Iblock\Component;
10use Bitrix\Main\Web\Json;
11use Bitrix\Main\Type\Collection;
21 private $multiIblockMode =
false;
22 private $paginationMode =
false;
35 $this->multiIblockMode = (bool)$state;
47 return (
bool)$this->multiIblockMode;
59 $this->paginationMode = (bool)$state;
71 return (
bool)$this->paginationMode;
87 $this->makeMagicWithPageNavigation();
90 if (isset(
$params[
'ELEMENT_COUNT']))
96 if (isset(
$params[
'PREDICT_ELEMENT_COUNT']) &&
$params[
'PREDICT_ELEMENT_COUNT'] ===
'Y' && !empty(
$params[
'PRODUCT_ROW_VARIANTS']))
98 $isBigData = $this->request->get(
'bigData') ===
'Y';
99 $params[
'PRODUCT_ROW_VARIANTS'] = static::parseJsonParameter(
$params[
'PRODUCT_ROW_VARIANTS']);
100 $params[
'PAGE_ELEMENT_COUNT'] = static::predictElementCountByVariants(
$params[
'PRODUCT_ROW_VARIANTS'], $isBigData);
103 $params[
'PAGE_ELEMENT_COUNT'] = (int)(
$params[
'PAGE_ELEMENT_COUNT'] ?? 0);
105 $params[
'LINE_ELEMENT_COUNT'] = (int)(
$params[
'LINE_ELEMENT_COUNT'] ?? 3);
107 $params[
'INCLUDE_SUBSECTIONS'] ??=
'';
109 $params[
'INCLUDE_SUBSECTIONS'],
117 $params[
'INCLUDE_SUBSECTIONS'] =
'Y';
120 $params[
'HIDE_NOT_AVAILABLE'] ??=
'';
121 if (
$params[
'HIDE_NOT_AVAILABLE'] !==
'Y' &&
$params[
'HIDE_NOT_AVAILABLE'] !==
'L')
123 $params[
'HIDE_NOT_AVAILABLE'] =
'N';
126 $params[
'HIDE_NOT_AVAILABLE_OFFERS'] ??=
'';
127 if (
$params[
'HIDE_NOT_AVAILABLE_OFFERS'] !==
'Y' &&
$params[
'HIDE_NOT_AVAILABLE_OFFERS'] !==
'L')
129 $params[
'HIDE_NOT_AVAILABLE_OFFERS'] =
'N';
132 $params[
'FILTER_NAME'] = trim((
string)(
$params[
'FILTER_NAME'] ??
''));
134 if (isset(
$params[
'GLOBAL_FILTER']))
136 $this->globalFilter =
$params[
'GLOBAL_FILTER'];
142 && preg_match(self::PARAM_TITLE_MASK,
$params[
'FILTER_NAME'])
150 if (isset($this->globalFilter[
'FACET_OPTIONS']) &&
count($this->globalFilter) == 1)
152 unset($this->globalFilter[
'FACET_OPTIONS']);
156 $this->arResult[
'ORIGINAL_PARAMETERS'][
'GLOBAL_FILTER'] = $this->globalFilter;
159 $productMappingFilter = [];
165 $productMappingFilter = Catalog\Product\SystemField\ProductMapping::getExtendedFilterByArea(
173 && !empty($this->globalFilter)
174 && array_diff_assoc($this->globalFilter, $productMappingFilter)
182 [
'ORDER' =>
'ELEMENT_SORT_FIELD',
'DIRECTION' =>
'ELEMENT_SORT_ORDER'],
183 [
'ORDER' =>
'SORT',
'DIRECTION' =>
'asc']
188 [
'ORDER' =>
'ELEMENT_SORT_FIELD2',
'DIRECTION' =>
'ELEMENT_SORT_ORDER2'],
189 [
'ORDER' =>
'ID',
'DIRECTION' =>
'desc']
192 $params[
'PAGER_BASE_LINK_ENABLE'] = (string)(
$params[
'PAGER_BASE_LINK_ENABLE'] ??
'');
194 $params[
'PAGER_TEMPLATE'] = (string)(
$params[
'PAGER_TEMPLATE'] ??
'');
195 $params[
'PAGER_PARAMS_NAME'] = trim((
string)(
$params[
'PAGER_PARAMS_NAME'] ??
''));
197 $params[
'PAGER_PARAMS_NAME'] !==
''
198 && preg_match(self::PARAM_TITLE_MASK,
$params[
'PAGER_PARAMS_NAME'])
203 if (!is_array($this->pagerParameters))
205 $this->pagerParameters = [];
232 $params[
'CALCULATE_SKU_MIN_PRICE'] = (isset(
$params[
'CALCULATE_SKU_MIN_PRICE']) &&
$params[
'CALCULATE_SKU_MIN_PRICE'] ===
'Y');
245 $order = (isset($orderRow[
'ORDER']) ? trim($orderRow[
'ORDER']) :
'');
246 $direction = (isset($orderRow[
'DIRECTION']) ? trim($orderRow[
'DIRECTION']) :
'');
281 $result = ($product[
'PRODUCT_IBLOCK_ID'] == $this->arParams[
'IBLOCK_ID']);
289 $templateVariantsMap = static::getTemplateVariantsMap();
291 if (!empty($variants))
293 foreach ($variants as $variant)
295 foreach ($templateVariantsMap as $variantInfo)
297 if ((
int)$variantInfo[
'VARIANT'] === (
int)$variant[
'VARIANT'])
300 ($isBigData && $variant[
'BIG_DATA'])
301 || (!$isBigData && !$variant[
'BIG_DATA'])
304 $count += (int)$variantInfo[
'COUNT'];
316 private function makeMagicWithPageNavigation()
318 if ($this->request->isAjaxRequest())
320 foreach ($this->request->getPostList() as
$name => $value)
322 if (preg_match(
'%^PAGEN_(\d+)$%',
$name, $m))
325 $NavNum = (int)$m[1] - 1;
334 $params[
'DISPLAY_TOP_PAGER'] = isset(
$params[
'DISPLAY_TOP_PAGER']) &&
$params[
'DISPLAY_TOP_PAGER'] ===
'Y';
335 $params[
'DISPLAY_BOTTOM_PAGER'] = !isset(
$params[
'DISPLAY_BOTTOM_PAGER']) ||
$params[
'DISPLAY_BOTTOM_PAGER'] !==
'N';
342 $params[
'PAGER_SHOW_ALWAYS'] = isset(
$params[
'PAGER_SHOW_ALWAYS']) &&
$params[
'PAGER_SHOW_ALWAYS'] ===
'Y';
344 $params[
'PAGER_DESC_NUMBERING'] = isset(
$params[
'PAGER_DESC_NUMBERING']) &&
$params[
'PAGER_DESC_NUMBERING'] ===
'Y';
345 $params[
'PAGER_DESC_NUMBERING_CACHE_TIME'] = (int)
$params[
'PAGER_DESC_NUMBERING_CACHE_TIME'];
347 $params[
'LOAD_ON_SCROLL'] = isset(
$params[
'LOAD_ON_SCROLL']) &&
$params[
'LOAD_ON_SCROLL'] ===
'Y' ?
'Y' :
'N';
348 $params[
'MESS_BTN_LAZY_LOAD'] = isset(
$params[
'MESS_BTN_LAZY_LOAD']) ? trim(
$params[
'MESS_BTN_LAZY_LOAD']) :
'';
353 $params[
'PAGER_SHOW_ALWAYS'] =
false;
354 $params[
'PAGER_SHOW_ALL'] =
false;
355 $params[
'LOAD_ON_SCROLL'] =
'N';
357 if (
$params[
'LAZY_LOAD'] ===
'Y' &&
$params[
'LOAD_ON_SCROLL'] ===
'Y')
359 $params[
'DEFERRED_LOAD'] = isset(
$params[
'DEFERRED_LOAD']) &&
$params[
'DEFERRED_LOAD'] ===
'Y' ?
'Y' :
'N';
363 $params[
'DEFERRED_LOAD'] =
'N';
378 $this->storage[
'IBLOCK_PARAMS'] = $parameters;
398 if (preg_match(
'/^PROPERTY_CODE_(\d+)$/',
$name, $match))
418 elseif (preg_match(
'/^CART_PROPERTIES_(\d+)$/',
$name, $match))
428 if ($v ==
'' || $v ===
'-')
437 elseif (preg_match(
'/^OFFER_TREE_PROPS_(\d+)$/',
$name, $match))
447 if ($v ==
'' || $v ===
'-')
457 elseif (preg_match(
'/^SHOW_PRODUCTS_(\d+)$/',
$name, $match))
473 $parameters =
array();
475 if (!empty(
$params[
'SHOW_PRODUCTS']))
484 'CART_PROPERTIES' => (!$usePropertyFeatures && isset(
$params[
'CART_PROPERTIES'][
$iblockId])
493 $parameters[
$iblockId][
'OFFERS_FIELD_CODE'] =
array(
'ID',
'CODE',
'NAME',
'SORT',
'PREVIEW_PICTURE',
'DETAIL_PICTURE');
495 $parameters[
$iblockId][
'OFFERS_CART_PROPERTIES'] = (!$usePropertyFeatures && isset(
$params[
'CART_PROPERTIES'][
$catalog[
'IBLOCK_ID']])
499 $parameters[
$iblockId][
'OFFERS_TREE_PROPS'] = (!$usePropertyFeatures && isset(
$params[
'OFFER_TREE_PROPS'][
$catalog[
'IBLOCK_ID']])
520 if (!isset(
$params[
'PROPERTY_CODE']) || !is_array(
$params[
'PROPERTY_CODE']))
525 foreach (
$params[
'PROPERTY_CODE'] as
$k => $v)
533 if (!isset(
$params[
'OFFERS_FIELD_CODE']))
542 foreach (
$params[
'OFFERS_FIELD_CODE'] as
$key => $value)
550 if (!isset(
$params[
'OFFERS_PROPERTY_CODE']))
559 foreach (
$params[
'OFFERS_PROPERTY_CODE'] as
$key => $value)
567 $cartProperties = [];
568 $offersCartProperties = [];
569 $offersTreeProperties = [];
570 if (!$usePropertyFeatures)
572 if (!isset(
$params[
'PRODUCT_PROPERTIES']) || !is_array(
$params[
'PRODUCT_PROPERTIES']))
577 foreach (
$params[
'PRODUCT_PROPERTIES'] as
$k => $v)
581 unset(
$params[
'PRODUCT_PROPERTIES'][
$k]);
584 $cartProperties =
$params[
'PRODUCT_PROPERTIES'];
586 if (!isset(
$params[
'OFFERS_CART_PROPERTIES']) || !is_array(
$params[
'OFFERS_CART_PROPERTIES']))
591 foreach (
$params[
'OFFERS_CART_PROPERTIES'] as
$i => $pid)
595 unset(
$params[
'OFFERS_CART_PROPERTIES'][
$i]);
598 $offersCartProperties =
$params[
'OFFERS_CART_PROPERTIES'];
600 if (!isset(
$params[
'OFFER_TREE_PROPS']))
609 foreach (
$params[
'OFFER_TREE_PROPS'] as
$key => $value)
611 $value = (string)$value;
612 if ($value ==
'' || $value ===
'-')
618 if (empty(
$params[
'OFFER_TREE_PROPS']) && !empty(
$params[
'OFFERS_CART_PROPERTIES']))
621 foreach (
$params[
'OFFER_TREE_PROPS'] as
$key => $value)
629 $offersTreeProperties =
$params[
'OFFER_TREE_PROPS'];
634 'PROPERTY_CODE' =>
$params[
'PROPERTY_CODE'],
635 'CART_PROPERTIES' => $cartProperties,
636 'OFFERS_FIELD_CODE' =>
$params[
'OFFERS_FIELD_CODE'],
637 'OFFERS_PROPERTY_CODE' =>
$params[
'OFFERS_PROPERTY_CODE'],
638 'OFFERS_CART_PROPERTIES' => $offersCartProperties,
639 'OFFERS_TREE_PROPS' => $offersTreeProperties
654 return parent::getProductIds();
663 isset($this->arParams[
'LAZY_LOAD'])
664 && $this->arParams[
'LAZY_LOAD'] ===
'Y'
665 && isset($this->arParams[
'LOAD_ON_SCROLL'])
666 && $this->arParams[
'LOAD_ON_SCROLL'] ===
'Y'
667 && isset($this->arParams[
'DEFERRED_LOAD'])
668 && $this->arParams[
'DEFERRED_LOAD'] ===
'Y'
684 $regexpLinks =
'/(<a\s[^>]*?>.*?<\/a>)/isu';
685 $regexpParams =
'/([\w\-]+)\s*=\s*([\"\'])(.*?)\2/isu';
687 $this->checkPcreLimit(
$data);
688 $preparedData = preg_split($regexpLinks,
$data, -1, PREG_SPLIT_DELIM_CAPTURE);
690 $dataCount =
count($preparedData);
694 $ignoreAttributes =
array(
704 $dataChanged =
false;
706 for (
$i = 1;
$i < $dataCount;
$i += 2)
708 if (!preg_match(
'/^<a\s([^>]*?)>(.*?)<\/a>$/isu', $preparedData[
$i], $match))
713 if (!preg_match_all($regexpParams,
$params, $linkParams))
716 $strAdditional =
' ';
720 foreach ($linkParams[0] as
$key => $value)
725 $paramName = mb_strtolower($linkParams[1][
$key]);
727 if ($paramName ===
'href')
731 elseif (isset($ignoreAttributes[$paramName]))
738 $strAdditional .= $value.
' ';
742 if ($urlKey >= 0 && !$ignoreLink)
745 $url = str_replace($search,
'',
$url);
747 if ($this->isAjaxURL(
$url))
751 $pos = mb_strpos(
$url,
'#');
754 $realUrl = mb_substr($realUrl, 0, $pos);
757 $realUrl .= mb_strpos(
$url,
'?') ===
false ?
'?' :
'&';
758 $realUrl .= $addParam;
760 $preparedData[
$i] =
\CAjax::GetLinkEx($realUrl,
$url, $match[2],
'comp_'.$this->arParams[
'AJAX_ID'], $strAdditional);
769 $data = implode(
'', $preparedData);
773 private function checkPcreLimit(
$data)
775 $pcreBacktrackLimit = (int)ini_get(
'pcre.backtrack_limit');
776 $textLen = strlen(
$data);
779 if ($pcreBacktrackLimit > 0 && $pcreBacktrackLimit < $textLen)
781 @ini_set(
'pcre.backtrack_limit', $textLen);
782 $pcreBacktrackLimit = intval(ini_get(
'pcre.backtrack_limit'));
785 return $pcreBacktrackLimit >= $textLen;
788 private function isAjaxURL(
$url)
790 if (preg_match(
'/^(#|mailto:|javascript:|callto:)/',
$url))
793 if (mb_strpos(
$url,
'://') !==
false)
796 $url = preg_replace(
'/#.*/',
'',
$url);
798 if (mb_strpos(
$url,
'?') !==
false)
803 if (mb_substr(
$url, -4) !=
'.php')
805 if (mb_substr(
$url, -1) !=
'/')
813 $currentUrl = $this->arParams[
'CURRENT_BASE_PAGE'];
815 if (mb_strpos($currentUrl,
'?') !==
false)
817 $currentUrl = mb_substr($currentUrl, 0, mb_strpos($currentUrl,
'?'));
820 if (mb_substr($currentUrl, -4) !=
'.php')
822 if (mb_substr($currentUrl, -1) !=
'/')
827 $currentUrl .=
'index.php';
830 $currentUrlDirName = dirname($currentUrl);
831 $currentUrlBaseName = basename($currentUrl);
832 $dirName = dirname(
$url);
835 ($dirName == $currentUrlDirName || $dirName ==
'' || $dirName ==
'.')
836 && basename(
$url) == $currentUrlBaseName
847 parent::initQueryFields();
853 $this->storage[
'SUB_FILTER'] =
array();
858 && $this->offerIblockExist($this->arParams[
'IBLOCK_ID'])
861 $catalogFilter =
array();
862 foreach ($this->globalFilter as
$key => $value)
867 if (
$key ===
'=PRODUCT_UF_PRODUCT_MAPPING')
871 $catalogFilter[
$key] = $value;
872 unset($this->globalFilter[
$key]);
876 $iblock = $this->storage[
'CATALOGS'][$this->arParams[
'IBLOCK_ID']];
877 $offersFilterExists = !empty($this->globalFilter[
'OFFERS']) && is_array($this->globalFilter[
'OFFERS']);
879 if ($offersFilterExists)
881 $this->storage[
'SUB_FILTER'] = array_merge($this->globalFilter[
'OFFERS'], $catalogFilter);
882 $this->storage[
'SUB_FILTER'][
'IBLOCK_ID'] =
$iblock[
'IBLOCK_ID'];
883 $this->storage[
'SUB_FILTER'][
'ACTIVE_DATE'] =
'Y';
884 $this->storage[
'SUB_FILTER'][
'ACTIVE'] =
'Y';
886 if ($this->arParams[
'HIDE_NOT_AVAILABLE'] ===
'Y')
888 $this->storage[
'SUB_FILTER'][
'AVAILABLE'] =
'Y';
891 $this->filterFields[
'=ID'] = \CIBlockElement::SubQuery(
892 'PROPERTY_'.
$iblock[
'SKU_PROPERTY_ID'],
893 $this->storage[
'SUB_FILTER']
896 elseif (!empty($catalogFilter))
898 $this->storage[
'SUB_FILTER'] = $catalogFilter;
899 $this->storage[
'SUB_FILTER'][
'IBLOCK_ID'] =
$iblock[
'IBLOCK_ID'];
900 $this->storage[
'SUB_FILTER'][
'ACTIVE_DATE'] =
'Y';
901 $this->storage[
'SUB_FILTER'][
'ACTIVE'] =
'Y';
903 $this->filterFields[] =
array(
905 array($catalogFilter),
906 '=ID' => \CIBlockElement::SubQuery(
907 'PROPERTY_'.
$iblock[
'SKU_PROPERTY_ID'],
908 $this->storage[
'SUB_FILTER']
917 $iblockElements =
array();
919 if (!empty($elementIterator))
921 while ($element = $elementIterator->GetNext())
923 $this->processElement($element);
924 $iblockElements[$element[
'ID']] = $element;
928 return $iblockElements;
933 if (!empty($iblockElements))
935 $iblockParams = $this->storage[
'IBLOCK_PARAMS'][
$iblock];
936 $propertyCodes = $iblockParams[
'PROPERTY_CODE'];
937 $productProperties = $iblockParams[
'CART_PROPERTIES'];
938 $getPropertyCodes = !empty($propertyCodes);
939 $getProductProperties = $this->arParams[
'ADD_PROPERTIES_TO_BASKET'] ===
'Y' && !empty($productProperties);
940 $getIblockProperties = $getPropertyCodes || $getProductProperties;
942 if ($getIblockProperties || ($this->useCatalog && $this->useDiscountCache))
945 'ID' => array_keys($iblockElements),
948 \CIBlockElement::GetPropertyValuesArray($iblockElements,
$iblock, $propFilter);
950 if ($getPropertyCodes)
952 $propertyList = $this->getPropertyList(
$iblock, $propertyCodes);
955 foreach ($iblockElements as &$element)
957 if ($this->useCatalog && $this->useDiscountCache)
959 if ($this->storage[
'USE_SALE_DISCOUNTS'])
962 \CCatalogDiscount::SetProductPropertiesCache($element[
'ID'], $element[
'PROPERTIES']);
965 if ($getIblockProperties)
967 if (!empty($propertyList))
969 foreach ($propertyList as $pid)
971 if (!isset($element[
'PROPERTIES'][$pid]))
974 $prop =& $element[
'PROPERTIES'][$pid];
975 $isArr = is_array($prop[
'VALUE']);
977 ($isArr && !empty($prop[
'VALUE']))
978 || (!$isArr && (
string)$prop[
'VALUE'] !==
'')
982 $element[
'DISPLAY_PROPERTIES'][$pid] = \CIBlockFormatProperties::GetDisplayValue($element, $prop);
989 if ($getProductProperties)
995 $element[
'PROPERTIES']
998 if (!empty($element[
'PRODUCT_PROPERTIES']))
1018 if ($this->arParams[
'HIDE_NOT_AVAILABLE'] ===
'Y')
1023 if (!empty($this->arParams[
'CUSTOM_FILTER']))
1028 if (!empty($this->arParams[
'FILTER_IDS']))
1039 if (empty($sortFields))
1043 $this->isIblockCatalog
1046 || (!$this->
isMultiIblockMode() && $this->offerIblockExist($this->arParams[
'IBLOCK_ID']))
1049 && $this->arParams[
'HIDE_NOT_AVAILABLE'] ===
'L'
1052 $sortFields[
'AVAILABLE'] =
'desc,nulls';
1055 $field = strtoupper($this->arParams[
'ELEMENT_SORT_FIELD']);
1056 if (!isset($sortFields[$field]))
1058 $sortFields[$field] = $this->arParams[
'ELEMENT_SORT_ORDER'];
1061 $field = strtoupper($this->arParams[
'ELEMENT_SORT_FIELD2']);
1062 if (!isset($sortFields[$field]))
1064 $sortFields[$field] = $this->arParams[
'ELEMENT_SORT_ORDER2'];
1067 if (!isset($sortFields[
'ID']))
1069 $sortFields[
'ID'] =
'DESC';
1080 if (!empty($this->arParams[
'CUSTOM_ELEMENT_SORT']) && is_array($this->arParams[
'CUSTOM_ELEMENT_SORT']))
1082 foreach ($this->arParams[
'CUSTOM_ELEMENT_SORT'] as $field => $value)
1084 $field = strtoupper($field);
1089 if ($field ===
'ID' && !empty($value) && is_array($value))
1091 Collection::normalizeArrayValuesByInt($value,
false);
1099 if (!is_string($value))
1103 if (!preg_match(self::SORT_ORDER_MASK, $value))
1111 unset($field, $value);
1120 if (is_array($this->navParams) && isset($this->navParams[
'nTopCount']) && $this->navParams[
'nTopCount'] == 0)
1125 $elementIterator = parent::getElementList(
$iblockId, $products);
1132 return $elementIterator;
1137 $navComponentParameters =
array();
1139 if ($this->arParams[
'PAGER_BASE_LINK_ENABLE'] ===
'Y')
1141 $pagerBaseLink = trim($this->arParams[
'PAGER_BASE_LINK']) ?: $this->arResult[
'SECTION_PAGE_URL'];
1143 if ($this->pagerParameters && isset($this->pagerParameters[
'BASE_LINK']))
1145 $pagerBaseLink = $this->pagerParameters[
'BASE_LINK'];
1146 unset($this->pagerParameters[
'BASE_LINK']);
1149 $navComponentParameters[
'BASE_LINK'] =
\CHTTP::urlAddParams($pagerBaseLink, $this->pagerParameters,
array(
'encode' =>
true));
1155 'PAGEN_'.$elementIterator->NavNum,
1156 'SIZEN_'.$elementIterator->NavNum,
1157 'SHOWALL_'.$elementIterator->NavNum,
1160 'bitrix_include_areas'
1162 $navComponentParameters[
'BASE_LINK'] =
$uri->getUri();
1166 $navComponentObject,
1167 $this->arParams[
'PAGER_TITLE'],
1168 $this->arParams[
'PAGER_TEMPLATE'],
1169 $this->arParams[
'PAGER_SHOW_ALWAYS'],
1171 $navComponentParameters
1173 $this->arResult[
'NAV_CACHED_DATA'] =
null;
1174 $this->arResult[
'NAV_RESULT'] = $elementIterator;
1175 $this->arResult[
'NAV_PARAM'] = $navComponentParameters;
1180 if (empty($offers) || empty($this->storage[
'CATALOGS'][
$iblockId]))
1182 $uniqueSortHash =
array();
1183 $filteredOffers =
array();
1184 $filteredElements =
array();
1190 $this->storage[
'SUB_FILTER'][
'=PROPERTY_'.$catalog[
'SKU_PROPERTY_ID']] = array_keys($this->elementLinks);
1194 $this->storage[
'SUB_FILTER']
1199 foreach ($offers as &$offer)
1201 $elementId = $offer[
'LINK_ELEMENT_ID'];
1203 if (!isset($this->elementLinks[$elementId]))
1206 if (!isset($uniqueSortHash[$elementId]))
1208 $uniqueSortHash[$elementId] =
array();
1211 $uniqueSortHash[$elementId][$offer[
'SORT_HASH']] =
true;
1213 if ($this->elementLinks[$elementId][
'OFFER_ID_SELECTED'] == 0 && $offer[
'CAN_BUY'])
1215 if (isset($filteredOffers[$elementId]))
1217 if (isset($filteredOffers[$elementId][$offer[
'ID']]))
1219 $this->elementLinks[$elementId][
'OFFER_ID_SELECTED'] = $offer[
'ID'];
1220 $filteredElements[$elementId] =
true;
1223 elseif (isset($filteredByProperty[$elementId]))
1225 if (isset($filteredByProperty[$elementId][$offer[
'ID']]))
1227 $this->elementLinks[$elementId][
'OFFER_ID_SELECTED'] = $offer[
'ID'];
1228 $filteredElements[$elementId] =
true;
1233 $this->elementLinks[$elementId][
'OFFER_ID_SELECTED'] = $offer[
'ID'];
1239 if (!empty($filteredOffers))
1241 $this->arResult[
'FILTERED_OFFERS_ID'] =
array();
1244 foreach ($this->elementLinks as &$element)
1246 if (isset($filteredOffers[$element[
'ID']]))
1248 $this->arResult[
'FILTERED_OFFERS_ID'][$element[
'ID']] = $filteredOffers[$element[
'ID']];
1251 if ($element[
'OFFER_ID_SELECTED'] == 0 || isset($filteredElements[$element[
'ID']]))
1254 if (
count($uniqueSortHash[$element[
'ID']]) < 2)
1256 $element[
'OFFER_ID_SELECTED'] = 0;
1264 if (empty($this->storage[
'CATALOGS'][
$iblockId]))
1277 '=PROPERTY_'.
$catalog[
'SKU_PROPERTY_ID'] => array_keys($this->elementLinks),
1294 foreach ($level as $prop)
1296 if (is_array($prop))
1300 elseif ($prop instanceOf \CIBlockElement)
1302 $checkLogic =
false;
1309 $filter[
'LOGIC'] = $level[
'LOGIC'];
1319 $this->globalFilter,
1320 $this->productIdMap,
1321 $this->arParams[
'CACHE_GROUPS'] ===
'N' ?
false : $this->getUserGroupsCacheId(),
1323 $this->pagerParameters
1329 return '/'.$this->getSiteId().$this->getRelativePath();
1334 parent::makeOutputResult();
1335 $this->arResult[
'PRICES'] = $this->storage[
'PRICES'];
1336 $this->arResult[
'ITEMS'] = $this->elements;
1337 $this->arResult[
'ELEMENTS'] = array_keys($this->elementLinks);
1354 parent::deferredLoadAction();
1359 $this->arParams[
'~PRODUCT_ROW_VARIANTS'] = $this->arParams[
'~DEFERRED_PRODUCT_ROW_VARIANTS'];
1360 $this->arParams[
'PRODUCT_ROW_VARIANTS'] = static::parseJsonParameter($this->arParams[
'~PRODUCT_ROW_VARIANTS']);
1362 if (isset($this->arParams[
'PREDICT_ELEMENT_COUNT']) && $this->arParams[
'PREDICT_ELEMENT_COUNT'] ===
'Y')
1364 $this->arParams[
'PAGE_ELEMENT_COUNT'] = static::predictElementCountByVariants($this->arParams[
'PRODUCT_ROW_VARIANTS']);
1368 $this->arParams[
'PAGE_ELEMENT_COUNT'] = $this->arParams[
'DEFERRED_PAGE_ELEMENT_COUNT'];
1371 $this->arParams[
'PAGE_ELEMENT_COUNT'] = (int)$this->arParams[
'PAGE_ELEMENT_COUNT'];
1382 $this->arParams[
'PAGE_ELEMENT_COUNT'] > 0
1384 $this->arParams[
'DISPLAY_TOP_PAGER']
1385 || $this->arParams[
'DISPLAY_BOTTOM_PAGER']
1386 || $this->arParams[
'LAZY_LOAD'] ===
'Y'
1390 $this->navParams =
array(
1391 'nPageSize' => $this->arParams[
'PAGE_ELEMENT_COUNT'],
1392 'bDescPageNumbering' => $this->arParams[
'PAGER_DESC_NUMBERING'],
1393 'bShowAll' => $this->arParams[
'PAGER_SHOW_ALL']
1395 $this->navigation = \CDBResult::GetNavParams($this->navParams);
1397 if ($this->navigation[
'PAGEN'] == 0 && $this->arParams[
'PAGER_DESC_NUMBERING_CACHE_TIME'] > 0)
1399 $this->arParams[
'CACHE_TIME'] = $this->arParams[
'PAGER_DESC_NUMBERING_CACHE_TIME'];
1404 $this->navParams =
array(
1405 'nTopCount' => $this->arParams[
'PAGE_ELEMENT_COUNT'],
1406 'bDescPageNumbering' => $this->arParams[
'PAGER_DESC_NUMBERING'],
1408 $this->navigation =
false;
1413 $this->navParams =
array(
'nTopCount' => $this->arParams[
'PAGE_ELEMENT_COUNT']);
1414 $this->navigation =
false;
1420 parent::prepareTemplateParams();
1423 if (
$params[
'LINE_ELEMENT_COUNT'] < 2)
1425 $params[
'LINE_ELEMENT_COUNT'] = 2;
1428 if (
$params[
'LINE_ELEMENT_COUNT'] > 5)
1430 $params[
'LINE_ELEMENT_COUNT'] = 5;
1433 if (
$params[
'ADD_TO_BASKET_ACTION'] !=
'BUY')
1435 $params[
'ADD_TO_BASKET_ACTION'] =
'ADD';
1439 (empty(
$params[
'PRODUCT_ROW_VARIANTS']) || !is_array(
$params[
'PRODUCT_ROW_VARIANTS']))
1440 && isset(
$params[
'~PRODUCT_ROW_VARIANTS'])
1443 $params[
'PRODUCT_ROW_VARIANTS'] = static::parseJsonParameter(
$params[
'~PRODUCT_ROW_VARIANTS']);
1446 if (empty(
$params[
'PRODUCT_ROW_VARIANTS']))
1448 $params[
'PRODUCT_ROW_VARIANTS'] = static::predictRowVariants(
$params[
'LINE_ELEMENT_COUNT'],
$params[
'PAGE_ELEMENT_COUNT']);
1451 if (empty(
$params[
'PRODUCT_BLOCKS_ORDER']))
1453 $params[
'PRODUCT_BLOCKS_ORDER'] =
'price,props,sku,quantityLimit,quantity,buttons';
1456 if (is_string(
$params[
'PRODUCT_BLOCKS_ORDER']))
1458 $params[
'PRODUCT_BLOCKS_ORDER'] = explode(
',',
$params[
'PRODUCT_BLOCKS_ORDER']);
1461 $params[
'PRODUCT_DISPLAY_MODE'] = isset(
$params[
'PRODUCT_DISPLAY_MODE']) &&
$params[
'PRODUCT_DISPLAY_MODE'] ===
'Y' ?
'Y' :
'N';
1477 if (!empty($jsonString) && is_string($jsonString))
1481 $parameter = Json::decode(str_replace(
"'",
'"', $jsonString));
1505 if (preg_match(
'/^ADDITIONAL_PICT_PROP_(\d+)$/',
$name, $match))
1517 elseif (preg_match(
'/^LABEL_PROP_(\d+)$/',
$name, $match))
1541 elseif (preg_match(
'/^LABEL_PROP_MOBILE_(\d+)$/',
$name, $match))
1566 elseif (preg_match(
'/^PROPERTY_CODE_MOBILE_(\d+)$/',
$name, $match))
1591 elseif (preg_match(
'/^ENLARGE_PROP_(\d+)$/',
$name, $match))
1605 if (!empty(
$params[
'SHOW_PRODUCTS']))
1611 if (!isset($this->storage[
'IBLOCK_PARAMS'][
$iblockId]) || !is_array($this->storage[
'IBLOCK_PARAMS'][
$iblockId]))
1627 $this->storage[
'IBLOCK_PARAMS'][
$iblockId][
'OFFERS_ADD_PICT_PROP'] =
$params[
'ADDITIONAL_PICT_PROP'][
$catalog[
'IBLOCK_ID']] ??
'';
1631 unset($usePropertyFeatures);
1643 if (
$params[
'ADD_PICT_PROP'] ===
'-')
1645 $params[
'ADD_PICT_PROP'] =
'';
1648 if (!isset(
$params[
'LABEL_PROP']) || !is_array(
$params[
'LABEL_PROP']))
1653 if (!isset(
$params[
'LABEL_PROP_MOBILE']) || !is_array(
$params[
'LABEL_PROP_MOBILE']))
1658 if (!empty(
$params[
'LABEL_PROP_MOBILE']))
1660 $params[
'LABEL_PROP_MOBILE'] = array_flip(
$params[
'LABEL_PROP_MOBILE']);
1663 if (!isset(
$params[
'PROPERTY_CODE_MOBILE']) || !is_array(
$params[
'PROPERTY_CODE_MOBILE']))
1668 if (!empty(
$params[
'PROPERTY_CODE_MOBILE']))
1670 $params[
'PROPERTY_CODE_MOBILE'] = array_flip(
$params[
'PROPERTY_CODE_MOBILE']);
1674 if (
$params[
'ENLARGE_PROP'] ===
'-')
1679 $params[
'OFFER_ADD_PICT_PROP'] = isset(
$params[
'OFFER_ADD_PICT_PROP']) ? trim(
$params[
'OFFER_ADD_PICT_PROP']) :
'';
1680 if (
$params[
'OFFER_ADD_PICT_PROP'] ===
'-')
1682 $params[
'OFFER_ADD_PICT_PROP'] =
'';
1685 if (!isset($this->storage[
'IBLOCK_PARAMS'][
$params[
'IBLOCK_ID']]) || !is_array($this->storage[
'IBLOCK_PARAMS'][
$params[
'IBLOCK_ID']]))
1687 $this->storage[
'IBLOCK_PARAMS'][
$params[
'IBLOCK_ID']] =
array();
1690 $this->storage[
'IBLOCK_PARAMS'][
$params[
'IBLOCK_ID']][
'ADD_PICT_PROP'] =
$params[
'ADD_PICT_PROP'];
1691 $this->storage[
'IBLOCK_PARAMS'][
$params[
'IBLOCK_ID']][
'LABEL_PROP'] =
$params[
'LABEL_PROP'];
1692 $this->storage[
'IBLOCK_PARAMS'][
$params[
'IBLOCK_ID']][
'LABEL_PROP_MOBILE'] =
$params[
'LABEL_PROP_MOBILE'];
1693 $this->storage[
'IBLOCK_PARAMS'][
$params[
'IBLOCK_ID']][
'PROPERTY_CODE_MOBILE'] =
$params[
'PROPERTY_CODE_MOBILE'];
1694 $this->storage[
'IBLOCK_PARAMS'][
$params[
'IBLOCK_ID']][
'ENLARGE_PROP'] =
$params[
'ENLARGE_PROP'];
1695 $this->storage[
'IBLOCK_PARAMS'][
$params[
'IBLOCK_ID']][
'OFFERS_ADD_PICT_PROP'] =
$params[
'OFFER_ADD_PICT_PROP'];
1696 unset($skuTreeProperties);
1702 $templateVariantsMap = static::getTemplateVariantsMap();
1704 if (!empty($templateVariantsMap))
1706 foreach ($templateVariantsMap as
$key => $variant)
1708 if (isset($variant[
'DEFAULT']) && $variant[
'DEFAULT'] ===
'Y')
1710 $variantId = $variant[
'VARIANT'];
1721 if ($pageElementCount <= 0)
1726 $templateVariantsMap = static::getTemplateVariantsMap();
1728 if (empty($templateVariantsMap))
1735 foreach ($templateVariantsMap as
$key => $variant)
1737 if ($variant[
'COUNT'] == $lineElementCount && $variant[
'ENLARGED_POS'] ===
false)
1746 ceil($pageElementCount / $templateVariantsMap[$variantId][
'COUNT']),
1747 array(
'VARIANT' => $variantId,
'BIG_DATA' =>
false)
1751 protected function checkTemplateTheme()
1753 parent::checkTemplateTheme();
1757 if (isset($this->arResult[
'NAV_PARAM']) && is_array($this->arResult[
'NAV_PARAM']))
1759 $this->arResult[
'NAV_PARAM'][
'TEMPLATE_THEME'] = $this->arParams[
'TEMPLATE_THEME'];
1762 if (!empty($this->arResult[
'NAV_RESULT']) && empty($this->arResult[
'NAV_STRING']))
1765 $this->arResult[
'NAV_STRING'] = $this->arResult[
'NAV_RESULT']->GetPageNavStringEx(
1766 $navComponentObject,
1767 $this->arParams[
'PAGER_TITLE'],
1768 $this->arParams[
'PAGER_TEMPLATE'],
1769 $this->arParams[
'PAGER_SHOW_ALWAYS'],
1771 $this->arResult[
'NAV_PARAM']
1779 $defaultParams = parent::getTemplateDefaultParams();
1780 $defaultParams[
'PRODUCT_BLOCKS_ORDER'] =
'price,props,sku,quantity,buttons';
1781 $defaultParams[
'PRODUCT_ROW_VARIANTS'] =
array();
1782 $defaultParams[
'PROPERTY_CODE_MOBILE'] =
array();
1783 $defaultParams[
'SHOW_SLIDER'] =
'Y';
1784 $defaultParams[
'SLIDER_INTERVAL'] = 3000;
1785 $defaultParams[
'ENLARGE_PRODUCT'] =
'STRICT';
1786 $defaultParams[
'ENLARGE_PROP'] =
'';
1787 $defaultParams[
'ADD_TO_BASKET_ACTION'] =
'ADD';
1788 $defaultParams[
'MESS_BTN_LAZY_LOAD'] =
'';
1790 return $defaultParams;
1795 $this->arResult[
'CURRENCIES'] = $this->getTemplateCurrencies();
1797 if (!empty($this->arResult[
'ITEMS']))
1799 $this->arResult[
'DEFAULT_PICTURE'] = $this->getTemplateEmptyPreview();
1805 $this->arResult[
'BIG_DATA'] = [];
1806 if ($this->request->getRequestMethod() ===
'GET')
1818 $variantsMap = static::getTemplateVariantsMap();
1819 $isBigData = $this->getAction() ===
'bigDataLoad';
1821 if ($this->arParams[
'ENLARGE_PRODUCT'] ===
'PROP')
1826 if (!empty($this->arParams[
'PRODUCT_ROW_VARIANTS']))
1830 foreach ($this->arParams[
'PRODUCT_ROW_VARIANTS'] as $variant)
1833 (!$isBigData && !$variant[
'BIG_DATA'])
1834 || ($isBigData && $variant[
'BIG_DATA'])
1849 $variantParam =
false;
1851 $itemsLength =
count($this->arResult[
'ITEMS']);
1853 while (($itemsRemaining = $itemsLength - $itemsCounter) > 0)
1855 if ($variantParam ===
false)
1857 $variantParam = reset($this->arParams[
'PRODUCT_ROW_VARIANTS']);
1861 if (!empty($variantParam))
1864 $isBigData && !$variantParam[
'BIG_DATA']
1865 || !$isBigData && $variantParam[
'BIG_DATA']
1868 $variantParam = next($this->arParams[
'PRODUCT_ROW_VARIANTS']);
1870 if ($variantParam ===
false)
1872 $variantParam = reset($this->arParams[
'PRODUCT_ROW_VARIANTS']);
1875 if ($variantParam ===
false)
1882 $variantKey =
false;
1883 if (isset($variantParam[
'VARIANT']) && is_scalar($variantParam[
'VARIANT']))
1885 $variantKey = $variantParam[
'VARIANT'];
1886 if (!is_string($variantKey) && !is_int($variantKey))
1888 $variantKey =
false;
1892 $variantKey ===
false
1893 || !isset($variantsMap[$variantKey])
1894 || ($variantsMap[$variantKey][
'SHOW_ONLY_FULL'] && $variantsMap[$variantKey][
'COUNT'] > $itemsRemaining)
1902 $variant = $variantsMap[$variantParam[
'VARIANT']];
1906 if ($this->arParams[
'ENLARGE_PRODUCT'] ===
'PROP' && $variant[
'ENLARGED_POS'] !==
false)
1908 if (!empty($enlargedIndexMap))
1910 $overallPos = $itemsCounter + $variant[
'ENLARGED_POS'];
1911 $overallPosKey = array_search($overallPos, $enlargedIndexMap);
1912 if ($overallPosKey ===
false)
1914 $closestPos =
false;
1915 $closestPosKey =
false;
1916 $enlargedPosInRange = array_intersect($enlargedIndexMap , range($itemsCounter, $itemsCounter + $variant[
'COUNT']));
1918 if (!empty($enlargedPosInRange))
1920 foreach ($enlargedPosInRange as
$key => $posInRange)
1922 if ($closestPos ===
false || abs($overallPos - $closestPos) > abs($posInRange - $overallPos))
1924 $closestPos = $posInRange;
1925 $closestPosKey =
$key;
1930 unset($this->arResult[
'ITEMS'][$closestPos], $enlargedIndexMap[$closestPosKey]);
1931 array_splice($this->arResult[
'ITEMS'], $overallPos, 0,
$temporary);
1936 unset($enlargedIndexMap[$overallPosKey]);
1942 $itemsCounter += $variant[
'COUNT'];
1943 $variantParam = next($this->arParams[
'PRODUCT_ROW_VARIANTS']);
1947 $this->arResult[
'ITEM_ROWS'] =
$rows;
1967 $variantsMap = static::getTemplateVariantsMap();
1969 if (!empty($this->arParams[
'PRODUCT_ROW_VARIANTS']))
1971 foreach ($this->arParams[
'PRODUCT_ROW_VARIANTS'] as
$key => $row)
1973 if ($row[
'BIG_DATA'])
1977 if (isset($variantsMap[$row[
'VARIANT']]))
1979 $count += (int)$variantsMap[$row[
'VARIANT']][
'COUNT'];
1988 if (!empty($this->elements))
1990 foreach ($this->elements as $element)
1992 $shownIds[] = $element[
'ID'];
2000 'rowsRange' => $rowsRange,
2001 'shownIds' => $shownIds,
2003 'cookiePrefix' => \COption::GetOptionString(
'main',
'cookie_name',
'BITRIX_SM'),
2005 'serverTime' =>
$count > 0 ? time() : 0,
2007 'params' => $this->getBigDataServiceRequestParams(($this->arParams[
'RCM_TYPE'] ??
''))
2014 $enlargedIndexMap =
array();
2016 foreach ($this->arResult[
'ITEMS'] as
$key => $item)
2018 if ($item[
'ENLARGED'] ===
'Y')
2020 $enlargedIndexMap[] =
$key;
2024 return $enlargedIndexMap;
2034 'CLASS' =>
'product-item-list-col-1',
2036 'ENLARGED_POS' =>
false,
2037 'SHOW_ONLY_FULL' =>
false,
2045 'CLASS' =>
'product-item-list-col-2',
2047 'ENLARGED_POS' =>
false,
2048 'SHOW_ONLY_FULL' =>
false,
2056 'CLASS' =>
'product-item-list-col-3',
2058 'ENLARGED_POS' =>
false,
2059 'SHOW_ONLY_FULL' =>
false,
2067 'CLASS' =>
'product-item-list-col-4',
2069 'ENLARGED_POS' =>
false,
2070 'SHOW_ONLY_FULL' =>
false,
2078 'CLASS' =>
'product-item-list-col-1-4',
2080 'ENLARGED_POS' => 0,
2081 'SHOW_ONLY_FULL' =>
false,
2089 'CLASS' =>
'product-item-list-col-4-1',
2091 'ENLARGED_POS' => 4,
2092 'SHOW_ONLY_FULL' =>
true,
2100 'CLASS' =>
'product-item-list-col-6',
2102 'ENLARGED_POS' =>
false,
2103 'SHOW_ONLY_FULL' =>
false,
2111 'CLASS' =>
'product-item-list-col-1-6',
2113 'ENLARGED_POS' => 0,
2114 'SHOW_ONLY_FULL' =>
false,
2122 'CLASS' =>
'product-item-list-col-6-1',
2124 'ENLARGED_POS' => 6,
2125 'SHOW_ONLY_FULL' =>
true,
2133 'CLASS' =>
'product-item-line-list',
2135 'ENLARGED_POS' =>
false,
2136 'SHOW_ONLY_FULL' =>
false,
2145 $skuPropList =
array();
2147 if ($this->arResult[
'MODULES'][
'catalog'] && !empty($this->storage[
'IBLOCK_PARAMS']))
2149 $elementIndex = array_keys($this->elements);
2151 foreach ($this->storage[
'IBLOCK_PARAMS'] as
$iblockId => $iblockParams)
2154 $sku = \CCatalogSku::GetInfoByProductIBlock(
$iblockId);
2155 $boolSku = !empty($sku) && is_array($sku);
2157 if ($boolSku && !empty($iblockParams[
'OFFERS_TREE_PROPS']) && $this->arParams[
'PRODUCT_DISPLAY_MODE'] ===
'Y')
2161 $iblockParams[
'OFFERS_TREE_PROPS'],
2163 'PICT' => $this->arResult[
'DEFAULT_PICTURE'],
2170 if (!empty($this->productWithOffers[
$iblockId]))
2172 $skuPropIds =
array();
2173 foreach ($skuPropList[
$iblockId] as $property)
2175 $skuPropIds[$property[
'CODE']] =
array(
2176 'ID' => $property[
'ID'],
2177 'CODE' => $property[
'CODE'],
2178 'PROPERTY_TYPE' => $property[
'PROPERTY_TYPE'],
2179 'USER_TYPE' => $property[
'USER_TYPE']
2184 $needValues =
array();
2185 foreach ($elementIndex as $index)
2187 if ($this->elements[$index][
'IBLOCK_ID'] !=
$iblockId)
2189 if ($this->elements[$index][
'PRODUCT'][
'TYPE'] !=
Catalog\ProductTable::TYPE_SKU)
2191 if (empty($this->elements[$index][
'OFFERS']))
2193 foreach ($this->elements[$index][
'OFFERS'] as $offer)
2195 foreach ($skuPropIds as $property)
2197 if (isset($offer[
'DISPLAY_PROPERTIES'][$property[
'CODE']]))
2199 if (!isset($needValues[$property[
'ID']]))
2200 $needValues[$property[
'ID']] =
array();
2202 ? $offer[
'DISPLAY_PROPERTIES'][$property[
'CODE']][
'VALUE_ENUM_ID']
2203 : $offer[
'DISPLAY_PROPERTIES'][$property[
'CODE']][
'VALUE']
2205 $needValues[$property[
'ID']][$valueId] = $valueId;
2215 if (!empty($needValues))
2216 \CIBlockPriceTools::getTreePropertyValues($skuPropList[
$iblockId], $needValues);
2224 $this->arParams[
'PRODUCT_DISPLAY_MODE'] =
'N';
2230 return $skuPropList;
2235 $enableCompatible = $this->isEnableCompatible();
2238 $iblockParams = $this->storage[
'IBLOCK_PARAMS'][$item[
'IBLOCK_ID']];
2240 if (!isset($item[
'CATALOG_QUANTITY']))
2242 $item[
'CATALOG_QUANTITY'] = 0;
2245 $item[
'CATALOG_QUANTITY'] = $item[
'CATALOG_QUANTITY'] > 0 && is_float($item[
'ITEM_MEASURE_RATIOS'][$item[
'ITEM_MEASURE_RATIO_SELECTED']][
'RATIO'])
2246 ? (float)$item[
'CATALOG_QUANTITY']
2247 : (int)$item[
'CATALOG_QUANTITY'];
2249 $item[
'CATALOG'] =
false;
2250 $item[
'CATALOG_SUBSCRIPTION'] = ($item[
'CATALOG_SUBSCRIPTION'] ??
'') ===
'Y' ?
'Y' :
'N';
2252 $item[
'BIG_DATA'] = $this->getAction() ===
'bigDataLoad';
2255 $item[
'LABEL_PROP_MOBILE'] = $iblockParams[
'LABEL_PROP_MOBILE'];
2256 $item[
'PROPERTY_CODE_MOBILE'] = $iblockParams[
'PROPERTY_CODE_MOBILE'];
2257 static::checkEnlargedData($item, $iblockParams[
'ENLARGE_PROP']);
2259 if ($this->arParams[
'SHOW_SLIDER'] ===
'Y')
2261 $this->editTemplateProductSlider($item, $item[
'IBLOCK_ID'], 5,
true,
array($this->arResult[
'DEFAULT_PICTURE']));
2265 $this->editTemplateCatalogInfo($item);
2267 if ($item[
'CATALOG'] && !empty($item[
'OFFERS']))
2269 if ($this->arParams[
'PRODUCT_DISPLAY_MODE'] ===
'Y')
2275 if ($this->arParams[
'CALCULATE_SKU_MIN_PRICE'] || $this->arParams[
'PRODUCT_DISPLAY_MODE'] !==
'Y')
2278 if ($this->arResult[
'MODULES'][
'catalog'] && !isset($this->arResult[
'CONVERT_CURRENCY'][
'CURRENCY_ID']))
2280 $baseCurrency = Currency\CurrencyManager::getBaseCurrency();
2283 $currency = $this->arResult[
'CONVERT_CURRENCY'][
'CURRENCY_ID'] ?? $baseCurrency;
2285 $item[
'ITEM_START_PRICE'] =
null;
2286 $item[
'ITEM_START_PRICE_SELECTED'] =
null;
2287 if ($enableCompatible)
2288 $item[
'MIN_PRICE'] =
false;
2291 $minPriceIndex =
null;
2292 foreach (array_keys($item[
'OFFERS']) as $index)
2294 if (!$item[
'OFFERS'][$index][
'CAN_BUY'] || $item[
'OFFERS'][$index][
'ITEM_PRICE_SELECTED'] ===
null)
2297 $currentPrice = $item[
'OFFERS'][$index][
'ITEM_PRICES'][$item[
'OFFERS'][$index][
'ITEM_PRICE_SELECTED']];
2298 if ($currentPrice[
'CURRENCY'] !=
$currency)
2301 $currentPrice[
'RATIO_PRICE'],
2302 $currentPrice[
'CURRENCY'],
2308 $priceScale = $currentPrice[
'RATIO_PRICE'];
2310 if ($minPrice ===
null || $minPrice > $priceScale)
2312 $minPrice = $priceScale;
2313 $minPriceIndex = $index;
2315 unset($priceScale, $currentPrice);
2319 if ($minPriceIndex !==
null)
2321 $minOffer = $item[
'OFFERS'][$minPriceIndex];
2322 $item[
'ITEM_START_PRICE_SELECTED'] = $minPriceIndex;
2323 $item[
'ITEM_START_PRICE'] = $minOffer[
'ITEM_PRICES'][$minOffer[
'ITEM_PRICE_SELECTED']];
2324 if ($enableCompatible)
2326 $item[
'MIN_PRICE'] =
array(
2327 'CATALOG_MEASURE_RATIO' => $minOffer[
'ITEM_MEASURE_RATIOS'][$minOffer[
'ITEM_MEASURE_RATIO_SELECTED']][
'RATIO'],
2328 'CATALOG_MEASURE' => $minOffer[
'ITEM_MEASURE'][
'ID'],
2329 'CATALOG_MEASURE_NAME' => $minOffer[
'ITEM_MEASURE'][
'TITLE'],
2330 '~CATALOG_MEASURE_NAME' => $minOffer[
'ITEM_MEASURE'][
'~TITLE'],
2331 'VALUE' => $item[
'ITEM_START_PRICE'][
'RATIO_BASE_PRICE'],
2332 'DISCOUNT_VALUE' => $item[
'ITEM_START_PRICE'][
'RATIO_PRICE'],
2333 'PRINT_VALUE' => $item[
'ITEM_START_PRICE'][
'PRINT_RATIO_BASE_PRICE'],
2334 'PRINT_DISCOUNT_VALUE' => $item[
'ITEM_START_PRICE'][
'PRINT_RATIO_PRICE'],
2335 'DISCOUNT_DIFF' => $item[
'ITEM_START_PRICE'][
'RATIO_DISCOUNT'],
2336 'PRINT_DISCOUNT_DIFF' => $item[
'ITEM_START_PRICE'][
'PRINT_RATIO_DISCOUNT'],
2337 'DISCOUNT_DIFF_PERCENT' => $item[
'ITEM_START_PRICE'][
'PERCENT'],
2338 'CURRENCY' => $item[
'ITEM_START_PRICE'][
'CURRENCY']
2343 unset($minPriceIndex, $minPrice);
2350 $this->arResult[
'MODULES'][
'catalog']
2353 $item[
'CATALOG_TYPE'] ==
Catalog\ProductTable::TYPE_PRODUCT
2354 || $item[
'CATALOG_TYPE'] ==
Catalog\ProductTable::TYPE_SET
2358 if ($enableCompatible)
2360 if ($item[
'ITEM_PRICE_SELECTED'] ===
null)
2362 $item[
'RATIO_PRICE'] =
null;
2363 $item[
'MIN_BASIS_PRICE'] =
null;
2367 $itemPrice = $item[
'ITEM_PRICES'][$item[
'ITEM_PRICE_SELECTED']];
2368 $item[
'RATIO_PRICE'] =
array(
2369 'VALUE' => $itemPrice[
'RATIO_BASE_PRICE'],
2370 'DISCOUNT_VALUE' => $itemPrice[
'RATIO_PRICE'],
2371 'PRINT_VALUE' => $itemPrice[
'PRINT_RATIO_BASE_PRICE'],
2372 'PRINT_DISCOUNT_VALUE' => $itemPrice[
'PRINT_RATIO_PRICE'],
2373 'DISCOUNT_DIFF' => $itemPrice[
'RATIO_DISCOUNT'],
2374 'PRINT_DISCOUNT_DIFF' => $itemPrice[
'PRINT_RATIO_DISCOUNT'],
2375 'DISCOUNT_DIFF_PERCENT' => $itemPrice[
'PERCENT'],
2376 'CURRENCY' => $itemPrice[
'CURRENCY']
2378 $item[
'MIN_BASIS_PRICE'] =
array(
2379 'VALUE' => $itemPrice[
'BASE_PRICE'],
2380 'DISCOUNT_VALUE' => $itemPrice[
'PRICE'],
2381 'PRINT_VALUE' => $itemPrice[
'PRINT_BASE_PRICE'],
2382 'PRINT_DISCOUNT_VALUE' => $itemPrice[
'PRINT_PRICE'],
2383 'DISCOUNT_DIFF' => $itemPrice[
'DISCOUNT'],
2384 'PRINT_DISCOUNT_DIFF' => $itemPrice[
'PRINT_DISCOUNT'],
2385 'DISCOUNT_DIFF_PERCENT' => $itemPrice[
'PERCENT'],
2386 'CURRENCY' => $itemPrice[
'CURRENCY']
2393 if (!empty($item[
'DISPLAY_PROPERTIES']))
2395 foreach ($item[
'DISPLAY_PROPERTIES'] as $propKey => $displayProp)
2398 if ($displayProp[
'PROPERTY_TYPE'] ===
'F')
2400 unset($item[
'DISPLAY_PROPERTIES'][$propKey]);
2406 $item[
'LAST_ELEMENT'] =
'N';
2415 $iblockParams = $this->storage[
'IBLOCK_PARAMS'][$item[
'IBLOCK_ID']];
2418 if (empty($productPictures[
'PICT']))
2420 $productPictures[
'PICT'] = $this->arResult[
'DEFAULT_PICTURE'];
2423 if (empty($productPictures[
'SECOND_PICT']))
2425 $productPictures[
'SECOND_PICT'] = $productPictures[
'PICT'];
2428 $item[
'PREVIEW_PICTURE'] = $productPictures[
'PICT'];
2429 $item[
'PREVIEW_PICTURE_SECOND'] = $productPictures[
'SECOND_PICT'];
2430 $item[
'SECOND_PICT'] =
true;
2431 $item[
'PRODUCT_PREVIEW'] = $productPictures[
'PICT'];
2432 $item[
'PRODUCT_PREVIEW_SECOND'] = $productPictures[
'SECOND_PICT'];
2438 $boolSkuDisplayProperties =
false;
2441 foreach ($item[
'OFFERS'] as $offerKey => $offer)
2443 if ($item[
'OFFER_ID_SELECTED'] > 0)
2445 $foundOffer = ($item[
'OFFER_ID_SELECTED'] == $offer[
'ID']);
2449 $foundOffer = $offer[
'CAN_BUY'];
2452 if ($foundOffer && $intSelected == -1)
2454 $intSelected = $offerKey;
2460 if (!empty($offer[
'DISPLAY_PROPERTIES']))
2462 $boolSkuDisplayProperties =
true;
2463 $skuProps =
array();
2464 foreach ($offer[
'DISPLAY_PROPERTIES'] as $oneProp)
2466 if ($oneProp[
'PROPERTY_TYPE'] ===
'F')
2469 $skuProps[] =
array(
2470 'CODE' => $oneProp[
'CODE'],
2471 'NAME' => $oneProp[
'NAME'],
2472 'VALUE' => $oneProp[
'DISPLAY_VALUE']
2478 $ratioSelectedIndex = $offer[
'ITEM_MEASURE_RATIO_SELECTED'];
2480 'ID' => $offer[
'ID'],
2481 'NAME' => ($offer[
'~NAME'] ??
''),
2482 'TREE' => $offer[
'TREE'],
2483 'DISPLAY_PROPERTIES' => $skuProps,
2486 'PRICE' => ($offer[
'RATIO_PRICE'] ?? $offer[
'MIN_PRICE'] ?? 0),
2487 'BASIS_PRICE' => ($offer[
'MIN_PRICE'] ?? 0),
2490 'ITEM_PRICE_MODE' => $offer[
'ITEM_PRICE_MODE'],
2491 'ITEM_PRICES' => $offer[
'ITEM_PRICES'],
2492 'ITEM_PRICE_SELECTED' => $offer[
'ITEM_PRICE_SELECTED'],
2493 'ITEM_QUANTITY_RANGES' => $offer[
'ITEM_QUANTITY_RANGES'],
2494 'ITEM_QUANTITY_RANGE_SELECTED' => $offer[
'ITEM_QUANTITY_RANGE_SELECTED'],
2495 'ITEM_MEASURE_RATIOS' => $offer[
'ITEM_MEASURE_RATIOS'],
2496 'ITEM_MEASURE_RATIO_SELECTED' => $ratioSelectedIndex,
2497 'SECOND_PICT' => $offer[
'SECOND_PICT'],
2498 'OWNER_PICT' => $offer[
'OWNER_PICT'],
2499 'PREVIEW_PICTURE' => $offer[
'PREVIEW_PICTURE'],
2500 'PREVIEW_PICTURE_SECOND' => $offer[
'PREVIEW_PICTURE_SECOND'],
2501 'CHECK_QUANTITY' => $offer[
'CHECK_QUANTITY'],
2502 'MAX_QUANTITY' => $offer[
'PRODUCT'][
'QUANTITY'],
2503 'STEP_QUANTITY' => $offer[
'ITEM_MEASURE_RATIOS'][$ratioSelectedIndex][
'RATIO'],
2504 'QUANTITY_FLOAT' => is_float($offer[
'ITEM_MEASURE_RATIOS'][$ratioSelectedIndex][
'RATIO']),
2505 'MEASURE' => $offer[
'ITEM_MEASURE'][
'TITLE'],
2506 'CAN_BUY' => $offer[
'CAN_BUY'],
2507 'CATALOG_SUBSCRIBE' => $offer[
'PRODUCT'][
'SUBSCRIBE']
2509 unset($ratioSelectedIndex);
2511 if (isset($offer[
'MORE_PHOTO_COUNT']) && $offer[
'MORE_PHOTO_COUNT'] > 0)
2513 $oneRow[
'MORE_PHOTO'] = $offer[
'MORE_PHOTO'];
2514 $oneRow[
'MORE_PHOTO_COUNT'] = $offer[
'MORE_PHOTO_COUNT'];
2517 $matrix[$offerKey] = $oneRow;
2520 if ($intSelected == -1)
2525 if (!$matrix[$intSelected][
'OWNER_PICT'])
2527 $item[
'PREVIEW_PICTURE'] = $matrix[$intSelected][
'PREVIEW_PICTURE'];
2528 $item[
'PREVIEW_PICTURE_SECOND'] = $matrix[$intSelected][
'PREVIEW_PICTURE_SECOND'];
2531 $item[
'JS_OFFERS'] = $matrix;
2532 $item[
'OFFERS_SELECTED'] = $intSelected;
2533 $item[
'OFFERS_PROPS_DISPLAY'] = $boolSkuDisplayProperties;
2539 $newOffers =
array();
2541 $item[
'OFFERS_PROP'] =
false;
2542 $item[
'SKU_TREE_VALUES'] =
array();
2544 $iblockParams = $this->storage[
'IBLOCK_PARAMS'][$item[
'IBLOCK_ID']];
2546 if (isset($this->arResult[
'SKU_PROPS'][$item[
'IBLOCK_ID']]))
2548 $skuPropList = $this->arResult[
'SKU_PROPS'][$item[
'IBLOCK_ID']];
2550 $skuPropIds = array_keys($skuPropList);
2551 $matrixFields = array_fill_keys($skuPropIds,
false);
2553 foreach ($item[
'OFFERS'] as $offerKey => $offer)
2555 $offer[
'ID'] = (int)$offer[
'ID'];
2557 if (isset($double[$offer[
'ID']]))
2561 foreach ($skuPropIds as
$code)
2563 $row[
$code] = $this->getTemplatePropCell(
$code, $offer, $matrixFields, $skuPropList);
2566 $matrix[$offerKey] = $row;
2571 if ($this->arParams[
'SHOW_SLIDER'] ===
'Y')
2573 $this->editTemplateOfferSlider($offer, $item[
'IBLOCK_ID'], 5,
true, $item[
'MORE_PHOTO']);
2577 $offer[
'OWNER_PICT'] = empty($offerPictures[
'PICT']);
2578 $offer[
'PREVIEW_PICTURE'] =
false;
2579 $offer[
'PREVIEW_PICTURE_SECOND'] =
false;
2580 $offer[
'SECOND_PICT'] =
true;
2582 if (!$offer[
'OWNER_PICT'])
2584 if (empty($offerPictures[
'SECOND_PICT']))
2586 $offerPictures[
'SECOND_PICT'] = $offerPictures[
'PICT'];
2589 $offer[
'PREVIEW_PICTURE'] = $offerPictures[
'PICT'];
2590 $offer[
'PREVIEW_PICTURE_SECOND'] = $offerPictures[
'SECOND_PICT'];
2593 if ($iblockParams[
'OFFERS_ADD_PICT_PROP'] !=
'' && isset($offer[
'DISPLAY_PROPERTIES'][$iblockParams[
'OFFERS_ADD_PICT_PROP']]))
2595 unset($offer[
'DISPLAY_PROPERTIES'][$iblockParams[
'OFFERS_ADD_PICT_PROP']]);
2597 $offer[
'TREE'] = [];
2599 $double[$offer[
'ID']] =
true;
2600 $newOffers[$offerKey] = $offer;
2603 $item[
'OFFERS'] = $newOffers;
2605 $usedFields =
array();
2606 $sortFields =
array();
2608 $matrixKeys = array_keys($matrix);
2609 foreach ($skuPropIds as $propCode)
2611 $boolExist = $matrixFields[$propCode];
2612 foreach ($matrixKeys as $offerKey)
2616 $propId = $this->arResult[
'SKU_PROPS'][$item[
'IBLOCK_ID']][$propCode][
'ID'];
2617 $value = $matrix[$offerKey][$propCode][
'VALUE'];
2619 if (!isset($item[
'SKU_TREE_VALUES'][$propId]))
2621 $item[
'SKU_TREE_VALUES'][$propId] =
array();
2624 $item[
'SKU_TREE_VALUES'][$propId][$value] =
true;
2625 $item[
'OFFERS'][$offerKey][
'TREE'][
'PROP_'.$propId] = $value;
2626 $item[
'OFFERS'][$offerKey][
'SKU_SORT_'.$propCode] = $matrix[$offerKey][$propCode][
'SORT'];
2627 $usedFields[$propCode] =
true;
2628 $sortFields[
'SKU_SORT_'.$propCode] = SORT_NUMERIC;
2629 unset($value, $propId);
2633 unset($matrix[$offerKey][$propCode]);
2638 unset($propCode, $matrixKeys);
2640 $item[
'OFFERS_PROP'] = $usedFields;
2641 $item[
'OFFERS_PROP_CODES'] = !empty($usedFields) ? base64_encode(serialize(array_keys($usedFields))) :
'';
2643 Collection::sortByColumn($item[
'OFFERS'], $sortFields);
2651 if (!
Iblock\
Model\PropertyFeature::isEnabledFeatures())
2654 foreach (array_keys($this->storage[
'IBLOCK_PARAMS']) as
$iblockId)
2657 $this->loadBasketPropertyCodes(
$iblockId);
2658 $this->loadOfferTreePropertyCodes(
$iblockId);
2675 $this->storage[
'IBLOCK_PARAMS'][
$iblockId][
'PROPERTY_CODE'] = $list;
2676 if ($this->useCatalog)
2684 $this->storage[
'IBLOCK_PARAMS'][
$iblockId][
'OFFERS_PROPERTY_CODE'] = $list;
static setProductPropertiesCache($productId, $props)
getTemplateMultiIblockParams(&$params)
initNavString(\CIBlockResult $elementIterator)
sortItemsByTemplateVariants()
setPaginationMode($state)
getIblockElements($elementIterator)
onPrepareComponentParams($params)
getPaginationParams(&$params)
static predictRowVariants($lineElementCount, $pageElementCount)
setMultiIblockMode($state)
getElementList($iblockId, $products)
editTemplateJsOffers(&$item)
getFilteredOffersByProperty($iblockId)
getSingleIblockParams(&$params)
editTemplateProductPictures(&$item)
getSpecificIblockParams(&$params)
static parseJsonParameter($jsonString)
checkProductIblock(array $product)
getTemplateDefaultParams()
static getTemplateVariantsMap()
chooseOffer($offers, $iblockId)
getMultiIblockParams(&$params)
initIblockPropertyFeatures()
editTemplateItems(&$items)
static predictElementCountByVariants($variants, $isBigData=false)
editTemplateOfferProps(&$item)
getOffersPropFilter(array $level)
static getDefaultVariantId()
getTemplateSingleIblockParams(&$params)
loadDisplayPropertyCodes($iblockId)
modifyDisplayProperties($iblock, &$iblockElements)
prepareElementSortRow(array $params, array $orderRow, array $default)
static getFilteredOffersByProduct($iblockId, $propertyId, array $filter)
static getListPageShowPropertyCodes($iblockId, array $parameters=[])
static isEnabledFeatures()
static includeModule($moduleName)
static getHtmlConverter()
static GetSessionParam($ajax_id=false)
static GetLinkEx($real_url, $public_url, $text, $container_id, $additional='')
static ConvertCurrency($valSum, $curFrom, $curTo, $valDate="")
GetPageNavStringEx(&$navComponentObject, $navigationTitle, $templateName="", $showAlways=false, $parentComponent=null, $componentParams=[])
static SetOptionString($module_id, $name, $value="", $desc=false, $site="")
static urlAddParams($url, $add_params, $options=[])
static isCatalogFilterField(string $field)
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
if(! $catalogEdit->isSuccess()) $iblock
if(!is_null($config))($config as $configItem)(! $configItem->isVisible()) $code
if(file_exists($_SERVER['DOCUMENT_ROOT'] . "/urlrewrite.php")) $uri
$GLOBALS['____1690880296']
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
if(empty($signedUserToken)) $key
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']