Bitrix-D7 22.6
 
Загрузка...
Поиск...
Не найдено
elementlist.php
1<?php
2
4
13
19abstract class ElementList extends Base
20{
21 private $multiIblockMode = false;
22 private $paginationMode = false;
23 protected $navigation = false;
24 protected $pagerParameters = array();
25
33 protected function setMultiIblockMode($state)
34 {
35 $this->multiIblockMode = (bool)$state;
36
37 return $this;
38 }
39
45 public function isMultiIblockMode()
46 {
47 return (bool)$this->multiIblockMode;
48 }
49
57 protected function setPaginationMode($state)
58 {
59 $this->paginationMode = (bool)$state;
60
61 return $this;
62 }
63
69 public function isPaginationMode()
70 {
71 return (bool)$this->paginationMode;
72 }
73
74 public function onPrepareComponentParams($params)
75 {
76 $params = parent::onPrepareComponentParams($params);
77 $this->makeMagicWithPageNavigation();
78
79 // compatibility with 'ELEMENT_COUNT' components
80 if (isset($params['ELEMENT_COUNT']))
81 {
82 $params['PAGE_ELEMENT_COUNT'] = $params['ELEMENT_COUNT'];
83 }
84
85 // PREDICT_ELEMENT_COUNT - hidden parameter to get elements count from "PRODUCT_ROW_VARIANTS" instead of "PAGE_ELEMENT_COUNT"
86 if (isset($params['PREDICT_ELEMENT_COUNT']) && $params['PREDICT_ELEMENT_COUNT'] === 'Y' && !empty($params['PRODUCT_ROW_VARIANTS']))
87 {
88 $isBigData = $this->request->get('bigData') === 'Y';
89 $params['PRODUCT_ROW_VARIANTS'] = static::parseJsonParameter($params['PRODUCT_ROW_VARIANTS']);
90 $params['PAGE_ELEMENT_COUNT'] = static::predictElementCountByVariants($params['PRODUCT_ROW_VARIANTS'], $isBigData);
91 }
92
93 $params['PAGE_ELEMENT_COUNT'] = (int)$params['PAGE_ELEMENT_COUNT'];
94 $params['ELEMENT_COUNT'] = (int)($params['ELEMENT_COUNT'] ?? 0);
95 $params['LINE_ELEMENT_COUNT'] = (int)($params['LINE_ELEMENT_COUNT'] ?? 3);
96
97 if (!isset($params['INCLUDE_SUBSECTIONS']) || !in_array($params['INCLUDE_SUBSECTIONS'], array('Y', 'A', 'N')))
98 {
99 $params['INCLUDE_SUBSECTIONS'] = 'Y';
100 }
101
102 if (
103 !isset($params['HIDE_NOT_AVAILABLE'])
104 || ($params['HIDE_NOT_AVAILABLE'] !== 'Y' && $params['HIDE_NOT_AVAILABLE'] !== 'L')
105 )
106 {
107 $params['HIDE_NOT_AVAILABLE'] = 'N';
108 }
109
110 if (
111 !isset($params['HIDE_NOT_AVAILABLE_OFFERS'])
112 || ($params['HIDE_NOT_AVAILABLE_OFFERS'] !== 'Y' && $params['HIDE_NOT_AVAILABLE_OFFERS'] !== 'L')
113 )
114 {
115 $params['HIDE_NOT_AVAILABLE_OFFERS'] = 'N';
116 }
117
118 // ajax request doesn't have access to page $GLOBALS
119 if (isset($params['GLOBAL_FILTER']))
120 {
121 $this->globalFilter = $params['GLOBAL_FILTER'];
122 }
123 else
124 {
125 if (
126 !empty($params['FILTER_NAME'])
127 && preg_match(self::PARAM_TITLE_MASK, $params['FILTER_NAME'])
128 && isset($GLOBALS[$params['FILTER_NAME']])
129 && is_array($GLOBALS[$params['FILTER_NAME']])
130 )
131 {
132 $this->globalFilter = $GLOBALS[$params['FILTER_NAME']];
133 }
134
135 if (isset($this->globalFilter['FACET_OPTIONS']) && count($this->globalFilter) == 1)
136 {
137 unset($this->globalFilter['FACET_OPTIONS']);
138 }
139
140 // save global filter for ajax request params
141 $this->arResult['ORIGINAL_PARAMETERS']['GLOBAL_FILTER'] = $this->globalFilter;
142 }
143
144 $productMappingFilter = [];
145 if (
146 Loader::includeModule('catalog')
147 && Catalog\Product\SystemField\ProductMapping::isAllowed()
148 )
149 {
150 $productMappingFilter = Catalog\Product\SystemField\ProductMapping::getExtendedFilterByArea(
151 [],
152 Catalog\Product\SystemField\ProductMapping::MAP_LANDING
153 );
154 }
155 $params['CACHE_FILTER'] = isset($params['CACHE_FILTER']) && $params['CACHE_FILTER'] === 'Y';
156 if (
157 !$params['CACHE_FILTER']
158 && !empty($this->globalFilter)
159 && array_diff_assoc($this->globalFilter, $productMappingFilter)
160 )
161 {
162 $params['CACHE_TIME'] = 0;
163 }
164
165 $params = $this->prepareElementSortRow(
166 $params,
167 ['ORDER' => 'ELEMENT_SORT_FIELD', 'DIRECTION' => 'ELEMENT_SORT_ORDER'],
168 ['ORDER' => 'SORT', 'DIRECTION' => 'asc']
169 );
170
171 $params = $this->prepareElementSortRow(
172 $params,
173 ['ORDER' => 'ELEMENT_SORT_FIELD2', 'DIRECTION' => 'ELEMENT_SORT_ORDER2'],
174 ['ORDER' => 'ID', 'DIRECTION' => 'desc']
175 );
176
177 $params['PAGER_BASE_LINK_ENABLE'] = (string)($params['PAGER_BASE_LINK_ENABLE'] ?? '');
178 $params['PAGER_TITLE'] = (string)($params['PAGER_TITLE'] ?? '');
179 $params['PAGER_TEMPLATE'] = (string)($params['PAGER_TEMPLATE'] ?? '');
180 if (!empty($params['PAGER_PARAMS_NAME']) && preg_match(self::PARAM_TITLE_MASK, $params['PAGER_PARAMS_NAME']))
181 {
182 $this->pagerParameters = $GLOBALS[$params['PAGER_PARAMS_NAME']] ?? [];
183
184 if (!is_array($this->pagerParameters))
185 {
186 $this->pagerParameters = array();
187 }
188 }
189
190 if (Loader::includeModule('catalog') && isset($params['CUSTOM_FILTER']) && is_string($params['CUSTOM_FILTER']))
191 {
192 try
193 {
194 $params['CUSTOM_FILTER'] = $this->parseCondition(Json::decode($params['CUSTOM_FILTER']), $params);
195 }
196 catch (\Exception $e)
197 {
198 $params['CUSTOM_FILTER'] = array();
199 }
200 }
201 else
202 {
203 $params['CUSTOM_FILTER'] = array();
204 }
205
206 if ($this->isPaginationMode())
207 {
208 $this->getPaginationParams($params);
209 }
210
211 $this->getSpecificIblockParams($params);
212
213 $params['CALCULATE_SKU_MIN_PRICE'] = (isset($params['CALCULATE_SKU_MIN_PRICE']) && $params['CALCULATE_SKU_MIN_PRICE'] === 'Y');
214
215 return $params;
216 }
217
224 protected function prepareElementSortRow(array $params, array $orderRow, array $default): array
225 {
226 $order = (isset($orderRow['ORDER']) ? trim($orderRow['ORDER']) : '');
227 $direction = (isset($orderRow['DIRECTION']) ? trim($orderRow['DIRECTION']) : '');
228 if (empty($params) || $order === '' || $direction === '')
229 {
230 return $params;
231 }
232 if (empty($params[$order]))
233 {
234 $params[$order] = $default['ORDER'] ?? 'SORT';
235 }
236 $params[$order] = strtoupper($params[$order]);
237
238 if ($params[$order] === 'ID' && !empty($params[$direction]) && is_array($params[$direction]))
239 {
240 Collection::normalizeArrayValuesByInt($params[$direction], false);
241 if (empty($params[$direction]))
242 {
243 $params[$direction] = $default['DIRECTION'] ?? 'desc';
244 }
245 }
246 else
247 {
248 if (empty($params[$direction]) || !preg_match(self::SORT_ORDER_MASK, $params[$direction]))
249 {
250 $params[$direction] = $default['DIRECTION'] ?? 'desc';
251 }
252 }
253
254 return $params;
255 }
256
257 protected function checkProductIblock(array $product): bool
258 {
259 $result = true;
260 if (!$this->isMultiIblockMode())
261 {
262 $result = ($product['PRODUCT_IBLOCK_ID'] == $this->arParams['IBLOCK_ID']);
263 }
264 return $result;
265 }
266
267 protected static function predictElementCountByVariants($variants, $isBigData = false)
268 {
269 $count = 0;
270 $templateVariantsMap = static::getTemplateVariantsMap();
271
272 if (!empty($variants))
273 {
274 foreach ($variants as $variant)
275 {
276 foreach ($templateVariantsMap as $variantInfo)
277 {
278 if ((int)$variantInfo['VARIANT'] === (int)$variant['VARIANT'])
279 {
280 if (
281 ($isBigData && $variant['BIG_DATA'])
282 || (!$isBigData && !$variant['BIG_DATA'])
283 )
284 {
285 $count += (int)$variantInfo['COUNT'];
286 }
287
288 break;
289 }
290 }
291 }
292 }
293
294 return $count;
295 }
296
297 private function makeMagicWithPageNavigation()
298 {
299 if ($this->request->isAjaxRequest())
300 {
301 foreach ($this->request->getPostList() as $name => $value)
302 {
303 if (preg_match('%^PAGEN_(\d+)$%', $name, $m))
304 {
305 global $NavNum;
306 $NavNum = (int)$m[1] - 1;
307 return;
308 }
309 }
310 }
311 }
312
313 protected function getPaginationParams(&$params)
314 {
315 $params['DISPLAY_TOP_PAGER'] = isset($params['DISPLAY_TOP_PAGER']) && $params['DISPLAY_TOP_PAGER'] === 'Y';
316 $params['DISPLAY_BOTTOM_PAGER'] = !isset($params['DISPLAY_BOTTOM_PAGER']) || $params['DISPLAY_BOTTOM_PAGER'] !== 'N';
317 $params['LAZY_LOAD'] = isset($params['LAZY_LOAD']) && $params['LAZY_LOAD'] === 'Y' ? 'Y' : 'N';
318
319 if ($params['DISPLAY_TOP_PAGER'] || $params['DISPLAY_BOTTOM_PAGER'] || $params['LAZY_LOAD'] === 'Y')
320 {
321 \CPageOption::SetOptionString('main', 'nav_page_in_session', 'N');
322 $params['PAGER_TITLE'] = isset($params['PAGER_TITLE']) ? trim($params['PAGER_TITLE']) : '';
323 $params['PAGER_SHOW_ALWAYS'] = isset($params['PAGER_SHOW_ALWAYS']) && $params['PAGER_SHOW_ALWAYS'] === 'Y';
324 $params['PAGER_TEMPLATE'] = isset($params['PAGER_TEMPLATE']) ? trim($params['PAGER_TEMPLATE']) : '';
325 $params['PAGER_DESC_NUMBERING'] = isset($params['PAGER_DESC_NUMBERING']) && $params['PAGER_DESC_NUMBERING'] === 'Y';
326 $params['PAGER_DESC_NUMBERING_CACHE_TIME'] = (int)$params['PAGER_DESC_NUMBERING_CACHE_TIME'];
327 $params['PAGER_SHOW_ALL'] = isset($params['PAGER_SHOW_ALL']) && $params['PAGER_SHOW_ALL'] === 'Y';
328 $params['LOAD_ON_SCROLL'] = isset($params['LOAD_ON_SCROLL']) && $params['LOAD_ON_SCROLL'] === 'Y' ? 'Y' : 'N';
329 $params['MESS_BTN_LAZY_LOAD'] = isset($params['MESS_BTN_LAZY_LOAD']) ? trim($params['MESS_BTN_LAZY_LOAD']) : '';
330 }
331 else
332 {
333 $this->setPaginationMode(false);
334 $params['PAGER_SHOW_ALWAYS'] = false;
335 $params['PAGER_SHOW_ALL'] = false;
336 $params['LOAD_ON_SCROLL'] = 'N';
337 }
338 if ($params['LAZY_LOAD'] === 'Y' && $params['LOAD_ON_SCROLL'] === 'Y')
339 {
340 $params['DEFERRED_LOAD'] = isset($params['DEFERRED_LOAD']) && $params['DEFERRED_LOAD'] === 'Y' ? 'Y' : 'N';
341 }
342 else
343 {
344 $params['DEFERRED_LOAD'] = 'N';
345 }
346 }
347
348 protected function getSpecificIblockParams(&$params)
349 {
350 if ($this->isMultiIblockMode())
351 {
352 $parameters = $this->getMultiIblockParams($params);
353 }
354 else
355 {
356 $parameters = $this->getSingleIblockParams($params);
357 }
358
359 $this->storage['IBLOCK_PARAMS'] = $parameters;
360 }
361
368 protected function getMultiIblockParams(&$params)
369 {
370 $usePropertyFeatures = Iblock\Model\PropertyFeature::isEnabledFeatures();
371
372 $params['PROPERTY_CODE'] = array();
373 $params['CART_PROPERTIES'] = array();
374 $params['SHOW_PRODUCTS'] = $params['SHOW_PRODUCTS'] ?? array();
375
376 foreach ($params as $name => $prop)
377 {
378 $match = array();
379 if (preg_match('/^PROPERTY_CODE_(\d+)$/', $name, $match))
380 {
381 $iblockId = (int)$match[1];
382 if ($iblockId <= 0)
383 continue;
384
385 if (!empty($params[$name]) && is_array($params[$name]))
386 {
387 foreach ($params[$name] as $k => $v)
388 {
389 if ($v == '')
390 {
391 unset($params[$name][$k]);
392 }
393 }
394
395 $params['PROPERTY_CODE'][$iblockId] = $params[$name];
396 }
397 unset($params[$match[0]]);
398 }
399 elseif (preg_match('/^CART_PROPERTIES_(\d+)$/', $name, $match))
400 {
401 $iblockId = (int)$match[1];
402 if ($iblockId <= 0)
403 continue;
404
405 if (!empty($params[$name]) && is_array($params[$name]))
406 {
407 foreach ($params[$name] as $k => $v)
408 {
409 if ($v == '' || $v === '-')
410 {
411 unset($params[$name][$k]);
412 }
413 }
414 $params['CART_PROPERTIES'][$iblockId] = $params[$name];
415 }
416 unset($params[$match[0]]);
417 }
418 elseif (preg_match('/^OFFER_TREE_PROPS_(\d+)$/', $name, $match))
419 {
420 $iblockId = (int)$match[1];
421 if ($iblockId <= 0)
422 continue;
423
424 if (!empty($params[$name]) && is_array($params[$name]))
425 {
426 foreach ($params[$name] as $k => $v)
427 {
428 if ($v == '' || $v === '-')
429 {
430 unset($params[$name][$k]);
431 }
432 }
433
434 $params['OFFER_TREE_PROPS'][$iblockId] = $params[$name];
435 }
436 unset($params[$match[0]]);
437 }
438 elseif (preg_match('/^SHOW_PRODUCTS_(\d+)$/', $name, $match))
439 {
440 $iblockId = (int)$match[1];
441 if ($iblockId <= 0)
442 continue;
443
444 if ($params[$name] === 'Y')
445 {
446 $params['SHOW_PRODUCTS'][$iblockId] = true;
447 }
448
449 unset($params[$match[0]]);
450 }
451 unset($match);
452 }
453
454 $parameters = array();
455
456 if (!empty($params['SHOW_PRODUCTS']))
457 {
458 foreach (array_keys($params['SHOW_PRODUCTS']) as $iblockId)
459 {
460 $catalog = \CCatalogSku::GetInfoByProductIBlock($iblockId);
461
462 // product iblock parameters
463 $parameters[$iblockId] = array(
464 'PROPERTY_CODE' => $params['PROPERTY_CODE'][$iblockId] ?? array(),
465 'CART_PROPERTIES' => (!$usePropertyFeatures && isset($params['CART_PROPERTIES'][$iblockId])
466 ? $params['CART_PROPERTIES'][$iblockId]
467 : array()
468 )
469 );
470
471 // offers iblock parameters
472 if (!empty($catalog))
473 {
474 $parameters[$iblockId]['OFFERS_FIELD_CODE'] = array('ID', 'CODE', 'NAME', 'SORT', 'PREVIEW_PICTURE', 'DETAIL_PICTURE');
475 $parameters[$iblockId]['OFFERS_PROPERTY_CODE'] = $params['PROPERTY_CODE'][$catalog['IBLOCK_ID']] ?? array();
476 $parameters[$iblockId]['OFFERS_CART_PROPERTIES'] = (!$usePropertyFeatures && isset($params['CART_PROPERTIES'][$catalog['IBLOCK_ID']])
477 ? $params['CART_PROPERTIES'][$catalog['IBLOCK_ID']]
478 : array()
479 );
480 $parameters[$iblockId]['OFFERS_TREE_PROPS'] = (!$usePropertyFeatures && isset($params['OFFER_TREE_PROPS'][$catalog['IBLOCK_ID']])
481 ? $params['OFFER_TREE_PROPS'][$catalog['IBLOCK_ID']]
482 : []
483 );
484 }
485 }
486 }
487
488 return $parameters;
489 }
490
497 protected function getSingleIblockParams(&$params)
498 {
499 $usePropertyFeatures = Iblock\Model\PropertyFeature::isEnabledFeatures();
500
501 if (!isset($params['PROPERTY_CODE']) || !is_array($params['PROPERTY_CODE']))
502 {
503 $params['PROPERTY_CODE'] = array();
504 }
505
506 foreach ($params['PROPERTY_CODE'] as $k => $v)
507 {
508 if ($v == '')
509 {
510 unset($params['PROPERTY_CODE'][$k]);
511 }
512 }
513
514 if (!isset($params['OFFERS_FIELD_CODE']))
515 {
516 $params['OFFERS_FIELD_CODE'] = array();
517 }
518 elseif (!is_array($params['OFFERS_FIELD_CODE']))
519 {
520 $params['OFFERS_FIELD_CODE'] = array($params['OFFERS_FIELD_CODE']);
521 }
522
523 foreach ($params['OFFERS_FIELD_CODE'] as $key => $value)
524 {
525 if ($value == '')
526 {
527 unset($params['OFFERS_FIELD_CODE'][$key]);
528 }
529 }
530
531 if (!isset($params['OFFERS_PROPERTY_CODE']))
532 {
533 $params['OFFERS_PROPERTY_CODE'] = array();
534 }
535 elseif (!is_array($params['OFFERS_PROPERTY_CODE']))
536 {
537 $params['OFFERS_PROPERTY_CODE'] = array($params['OFFERS_PROPERTY_CODE']);
538 }
539
540 foreach ($params['OFFERS_PROPERTY_CODE'] as $key => $value)
541 {
542 if ($value == '')
543 {
544 unset($params['OFFERS_PROPERTY_CODE'][$key]);
545 }
546 }
547
548 $cartProperties = [];
549 $offersCartProperties = [];
550 $offersTreeProperties = [];
551 if (!$usePropertyFeatures)
552 {
553 if (!isset($params['PRODUCT_PROPERTIES']) || !is_array($params['PRODUCT_PROPERTIES']))
554 {
555 $params['PRODUCT_PROPERTIES'] = array();
556 }
557
558 foreach ($params['PRODUCT_PROPERTIES'] as $k => $v)
559 {
560 if ($v == '')
561 {
562 unset($params['PRODUCT_PROPERTIES'][$k]);
563 }
564 }
565 $cartProperties = $params['PRODUCT_PROPERTIES'];
566
567 if (!isset($params['OFFERS_CART_PROPERTIES']) || !is_array($params['OFFERS_CART_PROPERTIES']))
568 {
569 $params['OFFERS_CART_PROPERTIES'] = array();
570 }
571
572 foreach ($params['OFFERS_CART_PROPERTIES'] as $i => $pid)
573 {
574 if ($pid == '')
575 {
576 unset($params['OFFERS_CART_PROPERTIES'][$i]);
577 }
578 }
579 $offersCartProperties = $params['OFFERS_CART_PROPERTIES'];
580
581 if (!isset($params['OFFER_TREE_PROPS']))
582 {
583 $params['OFFER_TREE_PROPS'] = array();
584 }
585 elseif (!is_array($params['OFFER_TREE_PROPS']))
586 {
587 $params['OFFER_TREE_PROPS'] = array($params['OFFER_TREE_PROPS']);
588 }
589
590 foreach ($params['OFFER_TREE_PROPS'] as $key => $value)
591 {
592 $value = (string)$value;
593 if ($value == '' || $value === '-')
594 {
595 unset($params['OFFER_TREE_PROPS'][$key]);
596 }
597 }
598
599 if (empty($params['OFFER_TREE_PROPS']) && !empty($params['OFFERS_CART_PROPERTIES']))
600 {
601 $params['OFFER_TREE_PROPS'] = $params['OFFERS_CART_PROPERTIES'];
602 foreach ($params['OFFER_TREE_PROPS'] as $key => $value)
603 {
604 if ($value === '-')
605 {
606 unset($params['OFFER_TREE_PROPS'][$key]);
607 }
608 }
609 }
610 $offersTreeProperties = $params['OFFER_TREE_PROPS'];
611 }
612
613 return array(
614 $params['IBLOCK_ID'] => array(
615 'PROPERTY_CODE' => $params['PROPERTY_CODE'],
616 'CART_PROPERTIES' => $cartProperties,
617 'OFFERS_FIELD_CODE' => $params['OFFERS_FIELD_CODE'],
618 'OFFERS_PROPERTY_CODE' => $params['OFFERS_PROPERTY_CODE'],
619 'OFFERS_CART_PROPERTIES' => $offersCartProperties,
620 'OFFERS_TREE_PROPS' => $offersTreeProperties
621 )
622 );
623 }
624
629 protected function getProductIds()
630 {
631 if ($this->isEmptyStartLoad())
632 {
633 return [];
634 }
635 return parent::getProductIds();
636 }
637
641 protected function isEmptyStartLoad(): bool
642 {
643 return (
644 isset($this->arParams['LAZY_LOAD'])
645 && $this->arParams['LAZY_LOAD'] === 'Y'
646 && isset($this->arParams['LOAD_ON_SCROLL'])
647 && $this->arParams['LOAD_ON_SCROLL'] === 'Y'
648 && isset($this->arParams['DEFERRED_LOAD'])
649 && $this->arParams['DEFERRED_LOAD'] === 'Y'
650 );
651 }
652
653 // some logic of \CComponentAjax to execute in component_epilog
654 public function prepareLinks(&$data)
655 {
656 $addParam = \CAjax::GetSessionParam($this->arParams['AJAX_ID']);
657
658 $regexpLinks = '/(<a\s[^>]*?>.*?<\/a>)/is'.BX_UTF_PCRE_MODIFIER;
659 $regexpParams = '/([\w\-]+)\s*=\s*([\"\'])(.*?)\2/is'.BX_UTF_PCRE_MODIFIER;
660
661 $this->checkPcreLimit($data);
662 $arData = preg_split($regexpLinks, $data, -1, PREG_SPLIT_DELIM_CAPTURE);
663
664 $dataCount = count($arData);
665 if ($dataCount < 2)
666 return;
667
668 $ignoreAttributes = array(
669 'onclick' => true,
670 'target' => true
671 );
672 $search = array(
673 $addParam.'&',
674 $addParam,
675 'AJAX_CALL=Y&',
676 'AJAX_CALL=Y'
677 );
678 $dataChanged = false;
679
680 for ($i = 1; $i < $dataCount; $i += 2)
681 {
682 if (!preg_match('/^<a\s([^>]*?)>(.*?)<\/a>$/is'.BX_UTF_PCRE_MODIFIER, $arData[$i], $match))
683 continue;
684
685 $params = $match[1];
686
687 if (!preg_match_all($regexpParams, $params, $linkParams))
688 continue;
689
690 $strAdditional = ' ';
691 $urlKey = -1;
692 $ignoreLink = false;
693
694 foreach ($linkParams[0] as $key => $value)
695 {
696 if ($value == '')
697 continue;
698
699 $paramName = mb_strtolower($linkParams[1][$key]);
700
701 if ($paramName === 'href')
702 {
703 $urlKey = $key;
704 }
705 elseif (isset($ignoreAttributes[$paramName]))
706 {
707 $ignoreLink = true;
708 break;
709 }
710 else
711 {
712 $strAdditional .= $value.' ';
713 }
714 }
715
716 if ($urlKey >= 0 && !$ignoreLink)
717 {
718 $url = Text\Converter::getHtmlConverter()->decode($linkParams[3][$urlKey]);
719 $url = str_replace($search, '', $url);
720
721 if ($this->isAjaxURL($url))
722 {
723 $realUrl = $url;
724
725 $pos = mb_strpos($url, '#');
726 if ($pos !== false)
727 {
728 $realUrl = mb_substr($realUrl, 0, $pos);
729 }
730
731 $realUrl .= mb_strpos($url, '?') === false ? '?' : '&';
732 $realUrl .= $addParam;
733
734 $arData[$i] = \CAjax::GetLinkEx($realUrl, $url, $match[2], 'comp_'.$this->arParams['AJAX_ID'], $strAdditional);
735
736 $dataChanged = true;
737 }
738 }
739 }
740
741 if ($dataChanged)
742 {
743 $data = implode('', $arData);
744 }
745 }
746
747 private function checkPcreLimit($data)
748 {
749 $pcreBacktrackLimit = (int)ini_get('pcre.backtrack_limit');
750 $textLen = function_exists('mb_strlen')? mb_strlen($data, 'latin1') : mb_strlen($data);
751 $textLen++;
752
753 if ($pcreBacktrackLimit > 0 && $pcreBacktrackLimit < $textLen)
754 {
755 @ini_set('pcre.backtrack_limit', $textLen);
756 $pcreBacktrackLimit = intval(ini_get('pcre.backtrack_limit'));
757 }
758
759 return $pcreBacktrackLimit >= $textLen;
760 }
761
762 private function isAjaxURL($url)
763 {
764 if (preg_match('/^(#|mailto:|javascript:|callto:)/', $url))
765 return false;
766
767 if (mb_strpos($url, '://') !== false)
768 return false;
769
770 $url = preg_replace('/#.*/', '', $url);
771
772 if (mb_strpos($url, '?') !== false)
773 {
774 $url = mb_substr($url, 0, mb_strpos($url, '?'));
775 }
776
777 if (mb_substr($url, -4) != '.php')
778 {
779 if (mb_substr($url, -1) != '/')
780 {
781 $url .= '/';
782 }
783
784 $url .= 'index.php';
785 }
786
787 $currentUrl = $this->arParams['CURRENT_BASE_PAGE'];
788
789 if (mb_strpos($currentUrl, '?') !== false)
790 {
791 $currentUrl = mb_substr($currentUrl, 0, mb_strpos($currentUrl, '?'));
792 }
793
794 if (mb_substr($currentUrl, -4) != '.php')
795 {
796 if (mb_substr($currentUrl, -1) != '/')
797 {
798 $currentUrl .= '/';
799 }
800
801 $currentUrl .= 'index.php';
802 }
803
804 $currentUrlDirName = dirname($currentUrl);
805 $currentUrlBaseName = basename($currentUrl);
806 $dirName = dirname($url);
807
808 if (
809 ($dirName == $currentUrlDirName || $dirName == '' || $dirName == '.')
810 && basename($url) == $currentUrlBaseName
811 )
812 {
813 return true;
814 }
815
816 return false;
817 }
818
819 protected function initQueryFields()
820 {
821 parent::initQueryFields();
822 $this->initSubQuery();
823 }
824
825 protected function initSubQuery()
826 {
827 $this->storage['SUB_FILTER'] = array();
828
829 if (
830 $this->useCatalog
831 && !$this->isMultiIblockMode()
832 && $this->offerIblockExist($this->arParams['IBLOCK_ID'])
833 )
834 {
835 $catalogFilter = array();
836 foreach ($this->globalFilter as $key => $value)
837 {
838 if (\CProductQueryBuilder::isCatalogFilterField($key))
839 {
840 //TODO: remove this hack after new catalog.section filter
841 if ($key === '=PRODUCT_UF_PRODUCT_MAPPING')
842 {
843 continue;
844 }
845 $catalogFilter[$key] = $value;
846 unset($this->globalFilter[$key]);
847 }
848 }
849
850 $iblock = $this->storage['CATALOGS'][$this->arParams['IBLOCK_ID']];
851 $offersFilterExists = !empty($this->globalFilter['OFFERS']) && is_array($this->globalFilter['OFFERS']);
852
853 if ($offersFilterExists)
854 {
855 $this->storage['SUB_FILTER'] = array_merge($this->globalFilter['OFFERS'], $catalogFilter);
856 $this->storage['SUB_FILTER']['IBLOCK_ID'] = $iblock['IBLOCK_ID'];
857 $this->storage['SUB_FILTER']['ACTIVE_DATE'] = 'Y';
858 $this->storage['SUB_FILTER']['ACTIVE'] = 'Y';
859
860 if ($this->arParams['HIDE_NOT_AVAILABLE'] === 'Y')
861 {
862 $this->storage['SUB_FILTER']['AVAILABLE'] = 'Y';
863 }
864
865 $this->filterFields['=ID'] = \CIBlockElement::SubQuery(
866 'PROPERTY_'.$iblock['SKU_PROPERTY_ID'],
867 $this->storage['SUB_FILTER']
868 );
869 }
870 elseif (!empty($catalogFilter))
871 {
872 $this->storage['SUB_FILTER'] = $catalogFilter;
873 $this->storage['SUB_FILTER']['IBLOCK_ID'] = $iblock['IBLOCK_ID'];
874 $this->storage['SUB_FILTER']['ACTIVE_DATE'] = 'Y';
875 $this->storage['SUB_FILTER']['ACTIVE'] = 'Y';
876
877 $this->filterFields[] = array(
878 'LOGIC' => 'OR',
879 array($catalogFilter),
880 '=ID' => \CIBlockElement::SubQuery(
881 'PROPERTY_'.$iblock['SKU_PROPERTY_ID'],
882 $this->storage['SUB_FILTER']
883 ),
884 );
885 }
886 }
887 }
888
889 protected function getIblockElements($elementIterator)
890 {
891 $iblockElements = array();
892
893 if (!empty($elementIterator))
894 {
895 while ($element = $elementIterator->GetNext())
896 {
897 $this->processElement($element);
898 $iblockElements[$element['ID']] = $element;
899 }
900 }
901
902 return $iblockElements;
903 }
904
905 protected function modifyDisplayProperties($iblock, &$iblockElements)
906 {
907 if (!empty($iblockElements))
908 {
909 $iblockParams = $this->storage['IBLOCK_PARAMS'][$iblock];
910 $propertyCodes = $iblockParams['PROPERTY_CODE'];
911 $productProperties = $iblockParams['CART_PROPERTIES'];
912 $getPropertyCodes = !empty($propertyCodes);
913 $getProductProperties = $this->arParams['ADD_PROPERTIES_TO_BASKET'] === 'Y' && !empty($productProperties);
914 $getIblockProperties = $getPropertyCodes || $getProductProperties;
915
916 if ($getIblockProperties || ($this->useCatalog && $this->useDiscountCache))
917 {
918 $propFilter = array(
919 'ID' => array_keys($iblockElements),
920 'IBLOCK_ID' => $iblock
921 );
922 \CIBlockElement::GetPropertyValuesArray($iblockElements, $iblock, $propFilter);
923
924 if ($getPropertyCodes)
925 {
926 $propertyList = $this->getPropertyList($iblock, $propertyCodes);
927 }
928
929 foreach ($iblockElements as &$element)
930 {
931 if ($this->useCatalog && $this->useDiscountCache)
932 {
933 if ($this->storage['USE_SALE_DISCOUNTS'])
934 Catalog\Discount\DiscountManager::setProductPropertiesCache($element['ID'], $element["PROPERTIES"]);
935 else
936 \CCatalogDiscount::SetProductPropertiesCache($element['ID'], $element['PROPERTIES']);
937 }
938
939 if ($getIblockProperties)
940 {
941 if (!empty($propertyList))
942 {
943 foreach ($propertyList as $pid)
944 {
945 if (!isset($element['PROPERTIES'][$pid]))
946 continue;
947
948 $prop =& $element['PROPERTIES'][$pid];
949 $isArr = is_array($prop['VALUE']);
950 if (
951 ($isArr && !empty($prop['VALUE']))
952 || (!$isArr && (string)$prop['VALUE'] !== '')
954 )
955 {
956 $element['DISPLAY_PROPERTIES'][$pid] = \CIBlockFormatProperties::GetDisplayValue($element, $prop, 'catalog_out');
957 }
958 unset($prop);
959 }
960 unset($pid);
961 }
962
963 if ($getProductProperties)
964 {
965 $element['PRODUCT_PROPERTIES'] = \CIBlockPriceTools::GetProductProperties(
966 $iblock,
967 $element['ID'],
968 $productProperties,
969 $element['PROPERTIES']
970 );
971
972 if (!empty($element['PRODUCT_PROPERTIES']))
973 {
974 $element['PRODUCT_PROPERTIES_FILL'] = \CIBlockPriceTools::getFillProductProperties($element['PRODUCT_PROPERTIES']);
975 }
976 }
977 }
978 }
979 unset($element);
980 }
981 }
982 }
983
984 protected function getFilter()
985 {
986 $filterFields = parent::getFilter();
987 $filterFields['ACTIVE'] = 'Y';
988
989 if ($this->arParams['HIDE_NOT_AVAILABLE'] === 'Y')
990 {
991 $filterFields['AVAILABLE'] = 'Y';
992 }
993
994 if (!empty($this->arParams['CUSTOM_FILTER']))
995 {
996 $filterFields[] = $this->arParams['CUSTOM_FILTER'];
997 }
998
999 if (!empty($this->arParams['FILTER_IDS']))
1000 {
1001 $filterFields['!ID'] = $this->arParams['FILTER_IDS'];
1002 }
1003
1004 return $filterFields;
1005 }
1006
1007 protected function getSort()
1008 {
1009 $sortFields = $this->getCustomSort();
1010 if (empty($sortFields))
1011 {
1012 if (
1013 (
1014 $this->isIblockCatalog
1015 || (
1016 $this->isMultiIblockMode()
1017 || (!$this->isMultiIblockMode() && $this->offerIblockExist($this->arParams['IBLOCK_ID']))
1018 )
1019 )
1020 && $this->arParams['HIDE_NOT_AVAILABLE'] === 'L'
1021 )
1022 {
1023 $sortFields['AVAILABLE'] = 'desc,nulls';
1024 }
1025
1026 $field = strtoupper($this->arParams['ELEMENT_SORT_FIELD']);
1027 if (!isset($sortFields[$field]))
1028 {
1029 $sortFields[$field] = $this->arParams['ELEMENT_SORT_ORDER'];
1030 }
1031
1032 $field = strtoupper($this->arParams['ELEMENT_SORT_FIELD2']);
1033 if (!isset($sortFields[$field]))
1034 {
1035 $sortFields[$field] = $this->arParams['ELEMENT_SORT_ORDER2'];
1036 }
1037 unset($field);
1038 if (!isset($sortFields['ID']))
1039 {
1040 $sortFields['ID'] = 'DESC';
1041 }
1042 }
1043
1044 return $sortFields;
1045 }
1046
1047 protected function getCustomSort(): array
1048 {
1049 $result = [];
1050
1051 if (!empty($this->arParams['CUSTOM_ELEMENT_SORT']) && is_array($this->arParams['CUSTOM_ELEMENT_SORT']))
1052 {
1053 foreach ($this->arParams['CUSTOM_ELEMENT_SORT'] as $field => $value)
1054 {
1055 $field = strtoupper($field);
1056 if (isset($result[$field]))
1057 {
1058 continue;
1059 }
1060 if ($field === 'ID' && !empty($value) && is_array($value))
1061 {
1062 Collection::normalizeArrayValuesByInt($value, false);
1063 if (empty($value))
1064 {
1065 continue;
1066 }
1067 }
1068 else
1069 {
1070 if (!is_string($value))
1071 {
1072 continue;
1073 }
1074 if (!preg_match(self::SORT_ORDER_MASK, $value))
1075 {
1076 continue;
1077 }
1078 }
1079
1080 $result[$field] = $value;
1081 }
1082 unset($field, $value);
1083 }
1084
1085 return $result;
1086 }
1087
1088 protected function getElementList($iblockId, $products)
1089 {
1090 // initialLoad case with only deferred bigData items
1091 if (is_array($this->navParams) && isset($this->navParams['nTopCount']) && $this->navParams['nTopCount'] == 0)
1092 {
1093 return false;
1094 }
1095
1096 $elementIterator = parent::getElementList($iblockId, $products);
1097
1098 if (!empty($elementIterator) && $this->isPaginationMode())
1099 {
1100 $this->initNavString($elementIterator);
1101 }
1102
1103 return $elementIterator;
1104 }
1105
1106 protected function initNavString(\CIBlockResult $elementIterator)
1107 {
1108 $navComponentParameters = array();
1109
1110 if ($this->arParams['PAGER_BASE_LINK_ENABLE'] === 'Y')
1111 {
1112 $pagerBaseLink = trim($this->arParams['PAGER_BASE_LINK']) ?: $this->arResult['SECTION_PAGE_URL'];
1113
1114 if ($this->pagerParameters && isset($this->pagerParameters['BASE_LINK']))
1115 {
1116 $pagerBaseLink = $this->pagerParameters['BASE_LINK'];
1117 unset($this->pagerParameters['BASE_LINK']);
1118 }
1119
1120 $navComponentParameters['BASE_LINK'] = \CHTTP::urlAddParams($pagerBaseLink, $this->pagerParameters, array('encode' => true));
1121 }
1122 else
1123 {
1124 $uri = new Main\Web\Uri($this->arParams['CURRENT_BASE_PAGE']);
1125 $uri->deleteParams(array(
1126 'PAGEN_'.$elementIterator->NavNum,
1127 'SIZEN_'.$elementIterator->NavNum,
1128 'SHOWALL_'.$elementIterator->NavNum,
1129 'PHPSESSID',
1130 'clear_cache',
1131 'bitrix_include_areas'
1132 ));
1133 $navComponentParameters['BASE_LINK'] = $uri->getUri();
1134 }
1135
1136 $this->arResult['NAV_STRING'] = $elementIterator->GetPageNavStringEx(
1137 $navComponentObject,
1138 $this->arParams['PAGER_TITLE'],
1139 $this->arParams['PAGER_TEMPLATE'],
1140 $this->arParams['PAGER_SHOW_ALWAYS'],
1141 $this,
1142 $navComponentParameters
1143 );
1144 $this->arResult['NAV_CACHED_DATA'] = null;
1145 $this->arResult['NAV_RESULT'] = $elementIterator;
1146 $this->arResult['NAV_PARAM'] = $navComponentParameters;
1147 }
1148
1149 protected function chooseOffer($offers, $iblockId)
1150 {
1151 if (empty($offers) || empty($this->storage['CATALOGS'][$iblockId]))
1152 return;
1153 $uniqueSortHash = array();
1154 $filteredOffers = array();
1155 $filteredElements = array();
1156 $filteredByProperty = $this->getFilteredOffersByProperty($iblockId);
1157
1158 if (!$this->isMultiIblockMode() && !empty($this->storage['SUB_FILTER']))
1159 {
1160 $catalog = $this->storage['CATALOGS'][$iblockId];
1161 $this->storage['SUB_FILTER']['=PROPERTY_'.$catalog['SKU_PROPERTY_ID']] = array_keys($this->elementLinks);
1162 $filteredOffers = Iblock\Component\Filters::getFilteredOffersByProduct(
1163 $catalog['IBLOCK_ID'],
1164 $catalog['SKU_PROPERTY_ID'],
1165 $this->storage['SUB_FILTER']
1166 );
1167 unset($catalog);
1168 }
1169
1170 foreach ($offers as &$offer)
1171 {
1172 $elementId = $offer['LINK_ELEMENT_ID'];
1173
1174 if (!isset($this->elementLinks[$elementId]))
1175 continue;
1176
1177 if (!isset($uniqueSortHash[$elementId]))
1178 {
1179 $uniqueSortHash[$elementId] = array();
1180 }
1181
1182 $uniqueSortHash[$elementId][$offer['SORT_HASH']] = true;
1183
1184 if ($this->elementLinks[$elementId]['OFFER_ID_SELECTED'] == 0 && $offer['CAN_BUY'])
1185 {
1186 if (isset($filteredOffers[$elementId]))
1187 {
1188 if (isset($filteredOffers[$elementId][$offer['ID']]))
1189 {
1190 $this->elementLinks[$elementId]['OFFER_ID_SELECTED'] = $offer['ID'];
1191 $filteredElements[$elementId] = true;
1192 }
1193 }
1194 elseif (isset($filteredByProperty[$elementId]))
1195 {
1196 if (isset($filteredByProperty[$elementId][$offer['ID']]))
1197 {
1198 $this->elementLinks[$elementId]['OFFER_ID_SELECTED'] = $offer['ID'];
1199 $filteredElements[$elementId] = true;
1200 }
1201 }
1202 else
1203 {
1204 $this->elementLinks[$elementId]['OFFER_ID_SELECTED'] = $offer['ID'];
1205 }
1206 }
1207 unset($elementId);
1208 }
1209
1210 if (!empty($filteredOffers))
1211 {
1212 $this->arResult['FILTERED_OFFERS_ID'] = array();
1213 }
1214
1215 foreach ($this->elementLinks as &$element)
1216 {
1217 if (isset($filteredOffers[$element['ID']]))
1218 {
1219 $this->arResult['FILTERED_OFFERS_ID'][$element['ID']] = $filteredOffers[$element['ID']];
1220 }
1221
1222 if ($element['OFFER_ID_SELECTED'] == 0 || isset($filteredElements[$element['ID']]))
1223 continue;
1224
1225 if (count($uniqueSortHash[$element['ID']]) < 2)
1226 {
1227 $element['OFFER_ID_SELECTED'] = 0;
1228 }
1229 }
1230 }
1231
1232 protected function getFilteredOffersByProperty($iblockId)
1233 {
1234 $offers = array();
1235 if (empty($this->storage['CATALOGS'][$iblockId]))
1236 return $offers;
1237
1238 if (!$this->isMultiIblockMode())
1239 {
1240 $filter = $this->getOffersPropFilter($this->arParams['CUSTOM_FILTER']);
1241 if (!empty($filter))
1242 {
1243 $catalog = $this->storage['CATALOGS'][$iblockId];
1244 $offers = Iblock\Component\Filters::getFilteredOffersByProduct(
1245 $catalog['IBLOCK_ID'],
1246 $catalog['SKU_PROPERTY_ID'],
1247 array(
1248 '=PROPERTY_'.$catalog['SKU_PROPERTY_ID'] => array_keys($this->elementLinks),
1249 $filter
1250 )
1251 );
1252 }
1253 }
1254
1255 return $offers;
1256 }
1257
1258 protected function getOffersPropFilter(array $level)
1259 {
1260 $filter = array();
1261 $checkLogic = true;
1262
1263 if (!empty($level))
1264 {
1265 foreach ($level as $prop)
1266 {
1267 if (is_array($prop))
1268 {
1269 $filter[] = $this->getOffersPropFilter($prop);
1270 }
1271 elseif ($prop instanceOf \CIBlockElement)
1272 {
1273 $checkLogic = false;
1274 $filter = $prop->arFilter;
1275 }
1276 }
1277
1278 if ($checkLogic && is_array($filter) && count($filter) > 1)
1279 {
1280 $filter['LOGIC'] = $level['LOGIC'];
1281 }
1282 }
1283
1284 return $filter;
1285 }
1286
1287 protected function getAdditionalCacheId()
1288 {
1289 return array(
1290 $this->globalFilter,
1291 $this->productIdMap,
1292 $this->arParams['CACHE_GROUPS'] === 'N' ? false : $this->getUserGroupsCacheId(),
1293 $this->navigation,
1294 $this->pagerParameters
1295 );
1296 }
1297
1298 protected function getComponentCachePath()
1299 {
1300 return '/'.$this->getSiteId().$this->getRelativePath();
1301 }
1302
1303 protected function makeOutputResult()
1304 {
1305 parent::makeOutputResult();
1306 $this->arResult['PRICES'] = $this->storage['PRICES'];
1307 $this->arResult['ITEMS'] = $this->elements;
1308 $this->arResult['ELEMENTS'] = array_keys($this->elementLinks);
1309 }
1310
1311 public function loadData()
1312 {
1313 $this->initNavParams();
1314 parent::loadData();
1315 }
1316
1317 protected function deferredLoadAction()
1318 {
1319 $this->prepareDeferredParams();
1320 parent::deferredLoadAction();
1321 }
1322
1323 protected function prepareDeferredParams()
1324 {
1325 $this->arParams['~PRODUCT_ROW_VARIANTS'] = $this->arParams['~DEFERRED_PRODUCT_ROW_VARIANTS'];
1326 $this->arParams['PRODUCT_ROW_VARIANTS'] = static::parseJsonParameter($this->arParams['~PRODUCT_ROW_VARIANTS']);
1327
1328 if (isset($this->arParams['PREDICT_ELEMENT_COUNT']) && $this->arParams['PREDICT_ELEMENT_COUNT'] === 'Y')
1329 {
1330 $this->arParams['PAGE_ELEMENT_COUNT'] = static::predictElementCountByVariants($this->arParams['PRODUCT_ROW_VARIANTS']);
1331 }
1332 else
1333 {
1334 $this->arParams['PAGE_ELEMENT_COUNT'] = $this->arParams['DEFERRED_PAGE_ELEMENT_COUNT'];
1335 }
1336
1337 $this->arParams['PAGE_ELEMENT_COUNT'] = (int)$this->arParams['PAGE_ELEMENT_COUNT'];
1338 }
1339
1343 protected function initNavParams()
1344 {
1345 if ($this->isPaginationMode())
1346 {
1347 if (
1348 $this->arParams['PAGE_ELEMENT_COUNT'] > 0
1349 && (
1350 $this->arParams['DISPLAY_TOP_PAGER']
1351 || $this->arParams['DISPLAY_BOTTOM_PAGER']
1352 || $this->arParams['LAZY_LOAD'] === 'Y'
1353 )
1354 )
1355 {
1356 $this->navParams = array(
1357 'nPageSize' => $this->arParams['PAGE_ELEMENT_COUNT'],
1358 'bDescPageNumbering' => $this->arParams['PAGER_DESC_NUMBERING'],
1359 'bShowAll' => $this->arParams['PAGER_SHOW_ALL']
1360 );
1361 $this->navigation = \CDBResult::GetNavParams($this->navParams);
1362
1363 if ($this->navigation['PAGEN'] == 0 && $this->arParams['PAGER_DESC_NUMBERING_CACHE_TIME'] > 0)
1364 {
1365 $this->arParams['CACHE_TIME'] = $this->arParams['PAGER_DESC_NUMBERING_CACHE_TIME'];
1366 }
1367 }
1368 else
1369 {
1370 $this->navParams = array(
1371 'nTopCount' => $this->arParams['PAGE_ELEMENT_COUNT'],
1372 'bDescPageNumbering' => $this->arParams['PAGER_DESC_NUMBERING'],
1373 );
1374 $this->navigation = false;
1375 }
1376 }
1377 else
1378 {
1379 $this->navParams = array('nTopCount' => $this->arParams['PAGE_ELEMENT_COUNT']);
1380 $this->navigation = false;
1381 }
1382 }
1383
1384 protected function prepareTemplateParams()
1385 {
1386 parent::prepareTemplateParams();
1387 $params =& $this->arParams;
1388
1389 if ($params['LINE_ELEMENT_COUNT'] < 2)
1390 {
1391 $params['LINE_ELEMENT_COUNT'] = 2;
1392 }
1393
1394 if ($params['LINE_ELEMENT_COUNT'] > 5)
1395 {
1396 $params['LINE_ELEMENT_COUNT'] = 5;
1397 }
1398
1399 if ($params['ADD_TO_BASKET_ACTION'] != 'BUY')
1400 {
1401 $params['ADD_TO_BASKET_ACTION'] = 'ADD';
1402 }
1403
1404 if (
1405 (empty($params['PRODUCT_ROW_VARIANTS']) || !is_array($params['PRODUCT_ROW_VARIANTS']))
1406 && isset($params['~PRODUCT_ROW_VARIANTS'])
1407 )
1408 {
1409 $params['PRODUCT_ROW_VARIANTS'] = static::parseJsonParameter($params['~PRODUCT_ROW_VARIANTS']);
1410 }
1411
1412 if (empty($params['PRODUCT_ROW_VARIANTS']))
1413 {
1414 $params['PRODUCT_ROW_VARIANTS'] = static::predictRowVariants($params['LINE_ELEMENT_COUNT'], $params['PAGE_ELEMENT_COUNT']);
1415 }
1416
1417 if (empty($params['PRODUCT_BLOCKS_ORDER']))
1418 {
1419 $params['PRODUCT_BLOCKS_ORDER'] = 'price,props,sku,quantityLimit,quantity,buttons';
1420 }
1421
1422 if (is_string($params['PRODUCT_BLOCKS_ORDER']))
1423 {
1424 $params['PRODUCT_BLOCKS_ORDER'] = explode(',', $params['PRODUCT_BLOCKS_ORDER']);
1425 }
1426
1427 $params['PRODUCT_DISPLAY_MODE'] = isset($params['PRODUCT_DISPLAY_MODE']) && $params['PRODUCT_DISPLAY_MODE'] === 'Y' ? 'Y' : 'N';
1428
1429 if ($this->isMultiIblockMode())
1430 {
1431 $this->getTemplateMultiIblockParams($params);
1432 }
1433 else
1434 {
1435 $this->getTemplateSingleIblockParams($params);
1436 }
1437 }
1438
1439 protected static function parseJsonParameter($jsonString)
1440 {
1441 $parameter = [];
1442
1443 if (!empty($jsonString) && is_string($jsonString))
1444 {
1445 try
1446 {
1447 $parameter = Json::decode(str_replace("'", '"', $jsonString));
1448 }
1449 catch (\Exception $e) {}
1450 }
1451
1452 return $parameter;
1453 }
1454
1460 protected function getTemplateMultiIblockParams(&$params)
1461 {
1462 $params['ADDITIONAL_PICT_PROP'] = array();
1463 $params['LABEL_PROP'] = array();
1464 $params['LABEL_PROP_MOBILE'] = array();
1465 $params['PROPERTY_CODE_MOBILE'] = array();
1466 $params['ENLARGE_PROP'] = array();
1467 $params['OFFER_TREE_PROPS'] = array();
1468
1469 foreach ($params as $name => $prop)
1470 {
1471 if (preg_match('/^ADDITIONAL_PICT_PROP_(\d+)$/', $name, $match))
1472 {
1473 $iblockId = (int)$match[1];
1474 if ($iblockId <= 0)
1475 continue;
1476
1477 if ($params[$name] != '' && $params[$name] != '-')
1478 {
1479 $params['ADDITIONAL_PICT_PROP'][$iblockId] = $params[$name];
1480 }
1481 unset($params[$match[0]]);
1482 }
1483 elseif (preg_match('/^LABEL_PROP_(\d+)$/', $name, $match))
1484 {
1485 $iblockId = (int)$match[1];
1486 if ($iblockId <= 0)
1487 continue;
1488
1489 if (!empty($params[$name]))
1490 {
1491 if (!is_array($params[$name]))
1492 {
1493 $params[$name] = array($params[$name]);
1494 }
1495
1496 foreach ($params[$name] as $k => $v)
1497 {
1498 if ($v == '')
1499 {
1500 unset($params[$name][$k]);
1501 }
1502 }
1503
1504 $params['LABEL_PROP'][$iblockId] = $params[$name];
1505 }
1506 }
1507 elseif (preg_match('/^LABEL_PROP_MOBILE_(\d+)$/', $name, $match))
1508 {
1509 $iblockId = (int)$match[1];
1510 if ($iblockId <= 0)
1511 continue;
1512
1513 if (!empty($params[$name]) && is_array($params[$name]))
1514 {
1515 foreach ($params[$name] as $k => $v)
1516 {
1517 if ($v == '')
1518 {
1519 unset($params[$name][$k]);
1520 }
1521 }
1522
1523 if (!empty($params[$name]))
1524 {
1525 $params[$name] = array_flip($params[$name]);
1526 }
1527
1528 $params['LABEL_PROP_MOBILE'][$iblockId] = $params[$name];
1529 }
1530 unset($params[$match[0]]);
1531 }
1532 elseif (preg_match('/^PROPERTY_CODE_MOBILE_(\d+)$/', $name, $match))
1533 {
1534 $iblockId = (int)$match[1];
1535 if ($iblockId <= 0)
1536 continue;
1537
1538 if (!empty($params[$name]) && is_array($params[$name]))
1539 {
1540 foreach ($params[$name] as $k => $v)
1541 {
1542 if ($v == '')
1543 {
1544 unset($params[$name][$k]);
1545 }
1546 }
1547
1548 if (!empty($params[$name]))
1549 {
1550 $params[$name] = array_flip($params[$name]);
1551 }
1552
1553 $params['PROPERTY_CODE_MOBILE'][$iblockId] = $params[$name];
1554 }
1555 unset($params[$match[0]]);
1556 }
1557 elseif (preg_match('/^ENLARGE_PROP_(\d+)$/', $name, $match))
1558 {
1559 $iblockId = (int)$match[1];
1560 if ($iblockId <= 0)
1561 continue;
1562
1563 if ($params[$name] != '' && $params[$name] != '-')
1564 {
1565 $params['ENLARGE_PROP'][$iblockId] = $params[$name];
1566 }
1567 unset($params[$match[0]]);
1568 }
1569 }
1570
1571 if (!empty($params['SHOW_PRODUCTS']))
1572 {
1573 $usePropertyFeatures = Iblock\Model\PropertyFeature::isEnabledFeatures();
1574
1575 foreach (array_keys($params['SHOW_PRODUCTS']) as $iblockId)
1576 {
1577 if (!isset($this->storage['IBLOCK_PARAMS'][$iblockId]) || !is_array($this->storage['IBLOCK_PARAMS'][$iblockId]))
1578 {
1579 $this->storage['IBLOCK_PARAMS'][$iblockId] = array();
1580 }
1581
1582 // product iblock parameters
1583 $this->storage['IBLOCK_PARAMS'][$iblockId]['ADD_PICT_PROP'] = $params['ADDITIONAL_PICT_PROP'][$iblockId] ?? '';
1584 $this->storage['IBLOCK_PARAMS'][$iblockId]['LABEL_PROP'] = $params['LABEL_PROP'][$iblockId] ?? array();
1585 $this->storage['IBLOCK_PARAMS'][$iblockId]['LABEL_PROP_MOBILE'] = $params['LABEL_PROP_MOBILE'][$iblockId] ?? array();
1586 $this->storage['IBLOCK_PARAMS'][$iblockId]['PROPERTY_CODE_MOBILE'] = $params['PROPERTY_CODE_MOBILE'][$iblockId] ?? array();
1587 $this->storage['IBLOCK_PARAMS'][$iblockId]['ENLARGE_PROP'] = $params['ENLARGE_PROP'][$iblockId] ?? '';
1588
1589 // offers iblock parameters
1590 $catalog = \CCatalogSku::GetInfoByProductIBlock($iblockId);
1591 if (!empty($catalog))
1592 {
1593 $this->storage['IBLOCK_PARAMS'][$iblockId]['OFFERS_ADD_PICT_PROP'] = $params['ADDITIONAL_PICT_PROP'][$catalog['IBLOCK_ID']] ?? '';
1594 }
1595 }
1596
1597 unset($usePropertyFeatures);
1598 }
1599 }
1600
1606 protected function getTemplateSingleIblockParams(&$params)
1607 {
1608 $params['ADD_PICT_PROP'] = isset($params['ADD_PICT_PROP']) ? trim($params['ADD_PICT_PROP']) : '';
1609 if ($params['ADD_PICT_PROP'] === '-')
1610 {
1611 $params['ADD_PICT_PROP'] = '';
1612 }
1613
1614 if (!isset($params['LABEL_PROP']) || !is_array($params['LABEL_PROP']))
1615 {
1616 $params['LABEL_PROP'] = array();
1617 }
1618
1619 if (!isset($params['LABEL_PROP_MOBILE']) || !is_array($params['LABEL_PROP_MOBILE']))
1620 {
1621 $params['LABEL_PROP_MOBILE'] = array();
1622 }
1623
1624 if (!empty($params['LABEL_PROP_MOBILE']))
1625 {
1626 $params['LABEL_PROP_MOBILE'] = array_flip($params['LABEL_PROP_MOBILE']);
1627 }
1628
1629 if (!isset($params['PROPERTY_CODE_MOBILE']) || !is_array($params['PROPERTY_CODE_MOBILE']))
1630 {
1631 $params['PROPERTY_CODE_MOBILE'] = array();
1632 }
1633
1634 if (!empty($params['PROPERTY_CODE_MOBILE']))
1635 {
1636 $params['PROPERTY_CODE_MOBILE'] = array_flip($params['PROPERTY_CODE_MOBILE']);
1637 }
1638
1639 $params['ENLARGE_PROP'] = isset($params['ENLARGE_PROP']) ? trim($params['ENLARGE_PROP']) : '';
1640 if ($params['ENLARGE_PROP'] === '-')
1641 {
1642 $params['ENLARGE_PROP'] = '';
1643 }
1644
1645 $params['OFFER_ADD_PICT_PROP'] = isset($params['OFFER_ADD_PICT_PROP']) ? trim($params['OFFER_ADD_PICT_PROP']) : '';
1646 if ($params['OFFER_ADD_PICT_PROP'] === '-')
1647 {
1648 $params['OFFER_ADD_PICT_PROP'] = '';
1649 }
1650
1651 if (!isset($this->storage['IBLOCK_PARAMS'][$params['IBLOCK_ID']]) || !is_array($this->storage['IBLOCK_PARAMS'][$params['IBLOCK_ID']]))
1652 {
1653 $this->storage['IBLOCK_PARAMS'][$params['IBLOCK_ID']] = array();
1654 }
1655
1656 $this->storage['IBLOCK_PARAMS'][$params['IBLOCK_ID']]['ADD_PICT_PROP'] = $params['ADD_PICT_PROP'];
1657 $this->storage['IBLOCK_PARAMS'][$params['IBLOCK_ID']]['LABEL_PROP'] = $params['LABEL_PROP'];
1658 $this->storage['IBLOCK_PARAMS'][$params['IBLOCK_ID']]['LABEL_PROP_MOBILE'] = $params['LABEL_PROP_MOBILE'];
1659 $this->storage['IBLOCK_PARAMS'][$params['IBLOCK_ID']]['PROPERTY_CODE_MOBILE'] = $params['PROPERTY_CODE_MOBILE'];
1660 $this->storage['IBLOCK_PARAMS'][$params['IBLOCK_ID']]['ENLARGE_PROP'] = $params['ENLARGE_PROP'];
1661 $this->storage['IBLOCK_PARAMS'][$params['IBLOCK_ID']]['OFFERS_ADD_PICT_PROP'] = $params['OFFER_ADD_PICT_PROP'];
1662 unset($skuTreeProperties);
1663 }
1664
1665 public static function getDefaultVariantId()
1666 {
1667 $variantId = 0;
1668 $templateVariantsMap = static::getTemplateVariantsMap();
1669
1670 if (!empty($templateVariantsMap))
1671 {
1672 foreach ($templateVariantsMap as $key => $variant)
1673 {
1674 if (isset($variant['DEFAULT']) && $variant['DEFAULT'] === 'Y')
1675 {
1676 $variantId = $variant['VARIANT'];
1677 break;
1678 }
1679 }
1680 }
1681
1682 return $variantId;
1683 }
1684
1685 public static function predictRowVariants($lineElementCount, $pageElementCount)
1686 {
1687 if ($pageElementCount <= 0)
1688 {
1689 return array();
1690 }
1691
1692 $templateVariantsMap = static::getTemplateVariantsMap();
1693
1694 if (empty($templateVariantsMap))
1695 {
1696 return array();
1697 }
1698
1699 $variantId = self::getDefaultVariantId();
1700
1701 foreach ($templateVariantsMap as $key => $variant)
1702 {
1703 if ($variant['COUNT'] == $lineElementCount && $variant['ENLARGED_POS'] === false)
1704 {
1705 $variantId = $key;
1706 break;
1707 }
1708 }
1709
1710 return array_fill(
1711 0,
1712 ceil($pageElementCount / $templateVariantsMap[$variantId]['COUNT']),
1713 array('VARIANT' => $variantId, 'BIG_DATA' => false)
1714 );
1715 }
1716
1717 protected function checkTemplateTheme()
1718 {
1719 parent::checkTemplateTheme();
1720
1721 if ($this->isPaginationMode())
1722 {
1723 if (is_array($this->arResult['NAV_PARAM']))
1724 {
1725 $this->arResult['NAV_PARAM']['TEMPLATE_THEME'] = $this->arParams['TEMPLATE_THEME'];
1726 }
1727
1728 if (!empty($this->arResult['NAV_RESULT']))
1729 {
1731 $this->arResult['NAV_STRING'] = $this->arResult['NAV_RESULT']->GetPageNavStringEx(
1732 $navComponentObject,
1733 $this->arParams['PAGER_TITLE'],
1734 $this->arParams['PAGER_TEMPLATE'],
1735 $this->arParams['PAGER_SHOW_ALWAYS'],
1736 $this,
1737 $this->arResult['NAV_PARAM']
1738 );
1739 }
1740 }
1741 }
1742
1743 protected function getTemplateDefaultParams()
1744 {
1745 $defaultParams = parent::getTemplateDefaultParams();
1746 $defaultParams['PRODUCT_BLOCKS_ORDER'] = 'price,props,sku,quantity,buttons';
1747 $defaultParams['PRODUCT_ROW_VARIANTS'] = array();
1748 $defaultParams['PROPERTY_CODE_MOBILE'] = array();
1749 $defaultParams['SHOW_SLIDER'] = 'Y';
1750 $defaultParams['SLIDER_INTERVAL'] = 3000;
1751 $defaultParams['ENLARGE_PRODUCT'] = 'STRICT';
1752 $defaultParams['ENLARGE_PROP'] = '';
1753 $defaultParams['ADD_TO_BASKET_ACTION'] = 'ADD';
1754 $defaultParams['MESS_BTN_LAZY_LOAD'] = '';
1755
1756 return $defaultParams;
1757 }
1758
1759 protected function editTemplateData()
1760 {
1761 $this->arResult['CURRENCIES'] = $this->getTemplateCurrencies();
1762
1763 if (!empty($this->arResult['ITEMS']))
1764 {
1765 $this->arResult['DEFAULT_PICTURE'] = $this->getTemplateEmptyPreview();
1766 $this->arResult['SKU_PROPS'] = $this->getTemplateSkuPropList();
1767 $this->editTemplateItems($this->arResult['ITEMS']);
1769 }
1770
1771 $this->arResult['BIG_DATA'] = [];
1772 if ($this->request->getRequestMethod() === 'GET')
1773 {
1774 $this->arResult['BIG_DATA'] = $this->getBigDataInfo();
1775 }
1776 }
1777
1781 protected function sortItemsByTemplateVariants()
1782 {
1783 $rows = array();
1784 $variantsMap = static::getTemplateVariantsMap();
1785 $isBigData = $this->getAction() === 'bigDataLoad';
1786
1787 if ($this->arParams['ENLARGE_PRODUCT'] === 'PROP')
1788 {
1789 $enlargedIndexMap = $this->getEnlargedIndexMap();
1790 }
1791
1792 if (!empty($this->arParams['PRODUCT_ROW_VARIANTS']))
1793 {
1794 $showItems = false;
1795
1796 foreach ($this->arParams['PRODUCT_ROW_VARIANTS'] as $variant)
1797 {
1798 if (
1799 (!$isBigData && !$variant['BIG_DATA'])
1800 || ($isBigData && $variant['BIG_DATA'])
1801 )
1802 {
1803 $showItems = true;
1804 break;
1805 }
1806 }
1807 }
1808 else
1809 {
1810 $showItems = true;
1811 }
1812
1813 if ($showItems)
1814 {
1815 $variantParam = false;
1816 $itemsCounter = 0;
1817 $itemsLength = count($this->arResult['ITEMS']);
1818
1819 while (($itemsRemaining = $itemsLength - $itemsCounter) > 0)
1820 {
1821 if ($variantParam === false)
1822 {
1823 $variantParam = reset($this->arParams['PRODUCT_ROW_VARIANTS']);
1824 }
1825
1826 // skip big_data rows on initial load and not_big_data rows on deferred load
1827 if (!empty($variantParam))
1828 {
1829 if (
1830 $isBigData && !$variantParam['BIG_DATA']
1831 || !$isBigData && $variantParam['BIG_DATA']
1832 )
1833 {
1834 $variantParam = next($this->arParams['PRODUCT_ROW_VARIANTS']);
1835 // if last variant is not suitable - should reset again
1836 if ($variantParam === false)
1837 {
1838 $variantParam = reset($this->arParams['PRODUCT_ROW_VARIANTS']);
1839 }
1840
1841 if ($variantParam === false)
1842 break;
1843 else
1844 continue;
1845 }
1846 }
1847
1848 if (
1849 $variantParam === false
1850 || !isset($variantsMap[$variantParam['VARIANT']])
1851 || ($variantsMap[$variantParam['VARIANT']]['SHOW_ONLY_FULL'] && $variantsMap[$variantParam['VARIANT']]['COUNT'] > $itemsRemaining)
1852 )
1853 {
1854 // default variant
1855 $variant = $variantsMap[self::getDefaultVariantId()];
1856 }
1857 else
1858 {
1859 $variant = $variantsMap[$variantParam['VARIANT']];
1860 }
1861
1862 // sorting by property $arResult['ITEMS'] for proper elements enlarge
1863 if ($this->arParams['ENLARGE_PRODUCT'] === 'PROP' && $variant['ENLARGED_POS'] !== false)
1864 {
1865 if (!empty($enlargedIndexMap))
1866 {
1867 $overallPos = $itemsCounter + $variant['ENLARGED_POS'];
1868 $overallPosKey = array_search($overallPos, $enlargedIndexMap);
1869 if ($overallPosKey === false)
1870 {
1871 $closestPos = false;
1872 $closestPosKey = false;
1873 $enlargedPosInRange = array_intersect($enlargedIndexMap , range($itemsCounter, $itemsCounter + $variant['COUNT']));
1874
1875 if (!empty($enlargedPosInRange))
1876 {
1877 foreach ($enlargedPosInRange as $key => $posInRange)
1878 {
1879 if ($closestPos === false || abs($overallPos - $closestPos) > abs($posInRange - $overallPos))
1880 {
1881 $closestPos = $posInRange;
1882 $closestPosKey = $key;
1883 }
1884 }
1885
1886 $temporary = array($this->arResult['ITEMS'][$closestPos]);
1887 unset($this->arResult['ITEMS'][$closestPos], $enlargedIndexMap[$closestPosKey]);
1888 array_splice($this->arResult['ITEMS'], $overallPos, 0, $temporary);
1889 }
1890 }
1891 else
1892 {
1893 unset($enlargedIndexMap[$overallPosKey]);
1894 }
1895 }
1896 }
1897
1898 $rows[] = $variant;
1899 $itemsCounter += $variant['COUNT'];
1900 $variantParam = next($this->arParams['PRODUCT_ROW_VARIANTS']);
1901 }
1902 }
1903
1904 $this->arResult['ITEM_ROWS'] = $rows;
1905 }
1906
1912 protected function getBigDataInfo()
1913 {
1914 $rows = array();
1915 $count = 0;
1916 $rowsRange = array();
1917 $variantsMap = static::getTemplateVariantsMap();
1918
1919 if (!empty($this->arParams['PRODUCT_ROW_VARIANTS']))
1920 {
1921 foreach ($this->arParams['PRODUCT_ROW_VARIANTS'] as $key => $row)
1922 {
1923 if ($row['BIG_DATA'])
1924 {
1925 $rows[$key] = $row;
1926
1927 if (isset($variantsMap[$row['VARIANT']]))
1928 {
1929 $count += (int)$variantsMap[$row['VARIANT']]['COUNT'];
1930 }
1931
1932 $rowsRange[] = $count;
1933 }
1934 }
1935 }
1936
1937 $shownIds = array();
1938 if (!empty($this->elements))
1939 {
1940 foreach ($this->elements as $element)
1941 {
1942 $shownIds[] = $element['ID'];
1943 }
1944 }
1945
1946 return array(
1947 'enabled' => $count > 0,
1948 'rows' => $rows,
1949 'count' => $count,
1950 'rowsRange' => $rowsRange,
1951 'shownIds' => $shownIds,
1952 'js' => array(
1953 'cookiePrefix' => \COption::GetOptionString('main', 'cookie_name', 'BITRIX_SM'),
1954 'cookieDomain' => Main\Web\Cookie::getCookieDomain(),
1955 'serverTime' => $count > 0 ? time() : 0,
1956 ),
1957 'params' => $this->getBigDataServiceRequestParams(($this->arParams['RCM_TYPE'] ?? ''))
1958 );
1959 }
1960
1961 // getting positions of enlarged elements
1962 protected function getEnlargedIndexMap()
1963 {
1964 $enlargedIndexMap = array();
1965
1966 foreach ($this->arResult['ITEMS'] as $key => $item)
1967 {
1968 if ($item['ENLARGED'] === 'Y')
1969 {
1970 $enlargedIndexMap[] = $key;
1971 }
1972 }
1973
1974 return $enlargedIndexMap;
1975 }
1976
1977 public static function getTemplateVariantsMap()
1978 {
1979 return array(
1980 array(
1981 'VARIANT' => 0,
1982 'TYPE' => 'CARD',
1983 'COLS' => 1,
1984 'CLASS' => 'product-item-list-col-1',
1985 'CODE' => '1',
1986 'ENLARGED_POS' => false,
1987 'SHOW_ONLY_FULL' => false,
1988 'COUNT' => 1,
1989 'DEFAULT' => 'N'
1990 ),
1991 array(
1992 'VARIANT' => 1,
1993 'TYPE' => 'CARD',
1994 'COLS' => 2,
1995 'CLASS' => 'product-item-list-col-2',
1996 'CODE' => '2',
1997 'ENLARGED_POS' => false,
1998 'SHOW_ONLY_FULL' => false,
1999 'COUNT' => 2,
2000 'DEFAULT' => 'N'
2001 ),
2002 array(
2003 'VARIANT' => 2,
2004 'TYPE' => 'CARD',
2005 'COLS' => 3,
2006 'CLASS' => 'product-item-list-col-3',
2007 'CODE' => '3',
2008 'ENLARGED_POS' => false,
2009 'SHOW_ONLY_FULL' => false,
2010 'COUNT' => 3,
2011 'DEFAULT' => 'Y'
2012 ),
2013 array(
2014 'VARIANT' => 3,
2015 'TYPE' => 'CARD',
2016 'COLS' => 4,
2017 'CLASS' => 'product-item-list-col-4',
2018 'CODE' => '4',
2019 'ENLARGED_POS' => false,
2020 'SHOW_ONLY_FULL' => false,
2021 'COUNT' => 4,
2022 'DEFAULT' => 'N'
2023 ),
2024 array(
2025 'VARIANT' => 4,
2026 'TYPE' => 'CARD',
2027 'COLS' => 4,
2028 'CLASS' => 'product-item-list-col-1-4',
2029 'CODE' => '1-4',
2030 'ENLARGED_POS' => 0,
2031 'SHOW_ONLY_FULL' => false,
2032 'COUNT' => 5,
2033 'DEFAULT' => 'N'
2034 ),
2035 array(
2036 'VARIANT' => 5,
2037 'TYPE' => 'CARD',
2038 'COLS' => 4,
2039 'CLASS' => 'product-item-list-col-4-1',
2040 'CODE' => '4-1',
2041 'ENLARGED_POS' => 4,
2042 'SHOW_ONLY_FULL' => true,
2043 'COUNT' => 5,
2044 'DEFAULT' => 'N'
2045 ),
2046 array(
2047 'VARIANT' => 6,
2048 'TYPE' => 'CARD',
2049 'COLS' => 6,
2050 'CLASS' => 'product-item-list-col-6',
2051 'CODE' => '6',
2052 'ENLARGED_POS' => false,
2053 'SHOW_ONLY_FULL' => false,
2054 'COUNT' => 6,
2055 'DEFAULT' => 'N'
2056 ),
2057 array(
2058 'VARIANT' => 7,
2059 'TYPE' => 'CARD',
2060 'COLS' => 6,
2061 'CLASS' => 'product-item-list-col-1-6',
2062 'CODE' => '1-6',
2063 'ENLARGED_POS' => 0,
2064 'SHOW_ONLY_FULL' => false,
2065 'COUNT' => 7,
2066 'DEFAULT' => 'N'
2067 ),
2068 array(
2069 'VARIANT' => 8,
2070 'TYPE' => 'CARD',
2071 'COLS' => 6,
2072 'CLASS' => 'product-item-list-col-6-1',
2073 'CODE' => '6-1',
2074 'ENLARGED_POS' => 6,
2075 'SHOW_ONLY_FULL' => true,
2076 'COUNT' => 7,
2077 'DEFAULT' => 'N'
2078 ),
2079 array(
2080 'VARIANT' => 9,
2081 'TYPE' => 'LINE',
2082 'COLS' => 1,
2083 'CLASS' => 'product-item-line-list',
2084 'CODE' => 'line',
2085 'ENLARGED_POS' => false,
2086 'SHOW_ONLY_FULL' => false,
2087 'COUNT' => 1,
2088 'DEFAULT' => 'N'
2089 )
2090 );
2091 }
2092
2093 public function getTemplateSkuPropList()
2094 {
2095 $skuPropList = array();
2096
2097 if ($this->arResult['MODULES']['catalog'] && !empty($this->storage['IBLOCK_PARAMS']))
2098 {
2099 $elementIndex = array_keys($this->elements);
2100
2101 foreach ($this->storage['IBLOCK_PARAMS'] as $iblockId => $iblockParams)
2102 {
2103 $skuPropList[$iblockId] = array();
2104 $sku = \CCatalogSku::GetInfoByProductIBlock($iblockId);
2105 $boolSku = !empty($sku) && is_array($sku);
2106
2107 if ($boolSku && !empty($iblockParams['OFFERS_TREE_PROPS']) && $this->arParams['PRODUCT_DISPLAY_MODE'] === 'Y')
2108 {
2109 $skuPropList[$iblockId] = \CIBlockPriceTools::getTreeProperties(
2110 $sku,
2111 $iblockParams['OFFERS_TREE_PROPS'],
2112 array(
2113 'PICT' => $this->arResult['DEFAULT_PICTURE'],
2114 'NAME' => '-'
2115 )
2116 );
2117
2118 if (!empty($skuPropList[$iblockId]))
2119 {
2120 if (!empty($this->productWithOffers[$iblockId]))
2121 {
2122 $skuPropIds = array();
2123 foreach ($skuPropList[$iblockId] as $property)
2124 {
2125 $skuPropIds[$property['CODE']] = array(
2126 'ID' => $property['ID'],
2127 'CODE' => $property['CODE'],
2128 'PROPERTY_TYPE' => $property['PROPERTY_TYPE'],
2129 'USER_TYPE' => $property['USER_TYPE']
2130 );
2131 }
2132 unset($property);
2133
2134 $needValues = array();
2135 foreach ($elementIndex as $index)
2136 {
2137 if ($this->elements[$index]['IBLOCK_ID'] != $iblockId)
2138 continue;
2139 if ($this->elements[$index]['PRODUCT']['TYPE'] != Catalog\ProductTable::TYPE_SKU)
2140 continue;
2141 if (empty($this->elements[$index]['OFFERS']))
2142 continue;
2143 foreach ($this->elements[$index]['OFFERS'] as $offer)
2144 {
2145 foreach ($skuPropIds as $property)
2146 {
2147 if (isset($offer['DISPLAY_PROPERTIES'][$property['CODE']]))
2148 {
2149 if (!isset($needValues[$property['ID']]))
2150 $needValues[$property['ID']] = array();
2151 $valueId = ($property['PROPERTY_TYPE'] == Iblock\PropertyTable::TYPE_LIST
2152 ? $offer['DISPLAY_PROPERTIES'][$property['CODE']]['VALUE_ENUM_ID']
2153 : $offer['DISPLAY_PROPERTIES'][$property['CODE']]['VALUE']
2154 );
2155 $needValues[$property['ID']][$valueId] = $valueId;
2156 unset($valueId);
2157 }
2158 }
2159 unset($property);
2160 }
2161 unset($offer);
2162 }
2163 unset($index);
2164
2165 if (!empty($needValues))
2166 \CIBlockPriceTools::getTreePropertyValues($skuPropList[$iblockId], $needValues);
2167 unset($needValues);
2168
2169 unset($skuPropIds);
2170 }
2171 }
2172 else
2173 {
2174 $this->arParams['PRODUCT_DISPLAY_MODE'] = 'N';
2175 }
2176 }
2177 }
2178 }
2179
2180 return $skuPropList;
2181 }
2182
2183 protected function editTemplateItems(&$items)
2184 {
2185 $enableCompatible = $this->isEnableCompatible();
2186 foreach ($items as $key => &$item)
2187 {
2188 $iblockParams = $this->storage['IBLOCK_PARAMS'][$item['IBLOCK_ID']];
2189
2190 if (!isset($item['CATALOG_QUANTITY']))
2191 {
2192 $item['CATALOG_QUANTITY'] = 0;
2193 }
2194
2195 $item['CATALOG_QUANTITY'] = $item['CATALOG_QUANTITY'] > 0 && is_float($item['ITEM_MEASURE_RATIOS'][$item['ITEM_MEASURE_RATIO_SELECTED']]['RATIO'])
2196 ? (float)$item['CATALOG_QUANTITY']
2197 : (int)$item['CATALOG_QUANTITY'];
2198
2199 $item['CATALOG'] = false;
2200 $item['CATALOG_SUBSCRIPTION'] = ($item['CATALOG_SUBSCRIPTION'] ?? '') === 'Y' ? 'Y' : 'N';
2201
2202 $item['BIG_DATA'] = $this->getAction() === 'bigDataLoad';
2203
2204 \CIBlockPriceTools::getLabel($item, $iblockParams['LABEL_PROP']);
2205 $item['LABEL_PROP_MOBILE'] = $iblockParams['LABEL_PROP_MOBILE'];
2206 $item['PROPERTY_CODE_MOBILE'] = $iblockParams['PROPERTY_CODE_MOBILE'];
2207 static::checkEnlargedData($item, $iblockParams['ENLARGE_PROP']);
2208
2209 if ($this->arParams['SHOW_SLIDER'] === 'Y')
2210 {
2211 $this->editTemplateProductSlider($item, $item['IBLOCK_ID'], 5, true, array($this->arResult['DEFAULT_PICTURE']));
2212 }
2213
2214 $this->editTemplateProductPictures($item);
2215 $this->editTemplateCatalogInfo($item);
2216
2217 if ($item['CATALOG'] && !empty($item['OFFERS']))
2218 {
2219 if ($this->arParams['PRODUCT_DISPLAY_MODE'] === 'Y')
2220 {
2221 $this->editTemplateOfferProps($item);
2222 $this->editTemplateJsOffers($item);
2223 }
2224
2225 if ($this->arParams['CALCULATE_SKU_MIN_PRICE'] || $this->arParams['PRODUCT_DISPLAY_MODE'] !== 'Y')
2226 {
2227 $baseCurrency = '';
2228 if ($this->arResult['MODULES']['catalog'] && !isset($this->arResult['CONVERT_CURRENCY']['CURRENCY_ID']))
2229 {
2230 $baseCurrency = Currency\CurrencyManager::getBaseCurrency();
2231 }
2232
2233 $currency = $this->arResult['CONVERT_CURRENCY']['CURRENCY_ID'] ?? $baseCurrency;
2234
2235 $item['ITEM_START_PRICE'] = null;
2236 $item['ITEM_START_PRICE_SELECTED'] = null;
2237 if ($enableCompatible)
2238 $item['MIN_PRICE'] = false;
2239
2240 $minPrice = null;
2241 $minPriceIndex = null;
2242 foreach (array_keys($item['OFFERS']) as $index)
2243 {
2244 if (!$item['OFFERS'][$index]['CAN_BUY'] || $item['OFFERS'][$index]['ITEM_PRICE_SELECTED'] === null)
2245 continue;
2246
2247 $currentPrice = $item['OFFERS'][$index]['ITEM_PRICES'][$item['OFFERS'][$index]['ITEM_PRICE_SELECTED']];
2248 if ($currentPrice['CURRENCY'] != $currency)
2249 {
2250 $priceScale = \CCurrencyRates::ConvertCurrency(
2251 $currentPrice['RATIO_PRICE'],
2252 $currentPrice['CURRENCY'],
2253 $currency
2254 );
2255 }
2256 else
2257 {
2258 $priceScale = $currentPrice['RATIO_PRICE'];
2259 }
2260 if ($minPrice === null || $minPrice > $priceScale)
2261 {
2262 $minPrice = $priceScale;
2263 $minPriceIndex = $index;
2264 }
2265 unset($priceScale, $currentPrice);
2266 }
2267 unset($index);
2268
2269 if ($minPriceIndex !== null)
2270 {
2271 $minOffer = $item['OFFERS'][$minPriceIndex];
2272 $item['ITEM_START_PRICE_SELECTED'] = $minPriceIndex;
2273 $item['ITEM_START_PRICE'] = $minOffer['ITEM_PRICES'][$minOffer['ITEM_PRICE_SELECTED']];
2274 if ($enableCompatible)
2275 {
2276 $item['MIN_PRICE'] = array(
2277 'CATALOG_MEASURE_RATIO' => $minOffer['ITEM_MEASURE_RATIOS'][$minOffer['ITEM_MEASURE_RATIO_SELECTED']]['RATIO'],
2278 'CATALOG_MEASURE' => $minOffer['ITEM_MEASURE']['ID'],
2279 'CATALOG_MEASURE_NAME' => $minOffer['ITEM_MEASURE']['TITLE'],
2280 '~CATALOG_MEASURE_NAME' => $minOffer['ITEM_MEASURE']['~TITLE'],
2281 'VALUE' => $item['ITEM_START_PRICE']['RATIO_BASE_PRICE'],
2282 'DISCOUNT_VALUE' => $item['ITEM_START_PRICE']['RATIO_PRICE'],
2283 'PRINT_VALUE' => $item['ITEM_START_PRICE']['PRINT_RATIO_BASE_PRICE'],
2284 'PRINT_DISCOUNT_VALUE' => $item['ITEM_START_PRICE']['PRINT_RATIO_PRICE'],
2285 'DISCOUNT_DIFF' => $item['ITEM_START_PRICE']['RATIO_DISCOUNT'],
2286 'PRINT_DISCOUNT_DIFF' => $item['ITEM_START_PRICE']['PRINT_RATIO_DISCOUNT'],
2287 'DISCOUNT_DIFF_PERCENT' => $item['ITEM_START_PRICE']['PERCENT'],
2288 'CURRENCY' => $item['ITEM_START_PRICE']['CURRENCY']
2289 );
2290 }
2291 unset($minOffer);
2292 }
2293 unset($minPriceIndex, $minPrice);
2294
2295 unset($baseCurrency, $currency);
2296 }
2297 }
2298
2299 if (
2300 $this->arResult['MODULES']['catalog']
2301 && $item['CATALOG']
2302 && (
2303 $item['CATALOG_TYPE'] == Catalog\ProductTable::TYPE_PRODUCT
2304 || $item['CATALOG_TYPE'] == Catalog\ProductTable::TYPE_SET
2305 )
2306 )
2307 {
2308 if ($enableCompatible)
2309 {
2310 if ($item['ITEM_PRICE_SELECTED'] === null)
2311 {
2312 $item['RATIO_PRICE'] = null;
2313 $item['MIN_BASIS_PRICE'] = null;
2314 }
2315 else
2316 {
2317 $itemPrice = $item['ITEM_PRICES'][$item['ITEM_PRICE_SELECTED']];
2318 $item['RATIO_PRICE'] = array(
2319 'VALUE' => $itemPrice['RATIO_BASE_PRICE'],
2320 'DISCOUNT_VALUE' => $itemPrice['RATIO_PRICE'],
2321 'PRINT_VALUE' => $itemPrice['PRINT_RATIO_BASE_PRICE'],
2322 'PRINT_DISCOUNT_VALUE' => $itemPrice['PRINT_RATIO_PRICE'],
2323 'DISCOUNT_DIFF' => $itemPrice['RATIO_DISCOUNT'],
2324 'PRINT_DISCOUNT_DIFF' => $itemPrice['PRINT_RATIO_DISCOUNT'],
2325 'DISCOUNT_DIFF_PERCENT' => $itemPrice['PERCENT'],
2326 'CURRENCY' => $itemPrice['CURRENCY']
2327 );
2328 $item['MIN_BASIS_PRICE'] = array(
2329 'VALUE' => $itemPrice['BASE_PRICE'],
2330 'DISCOUNT_VALUE' => $itemPrice['PRICE'],
2331 'PRINT_VALUE' => $itemPrice['PRINT_BASE_PRICE'],
2332 'PRINT_DISCOUNT_VALUE' => $itemPrice['PRINT_PRICE'],
2333 'DISCOUNT_DIFF' => $itemPrice['DISCOUNT'],
2334 'PRINT_DISCOUNT_DIFF' => $itemPrice['PRINT_DISCOUNT'],
2335 'DISCOUNT_DIFF_PERCENT' => $itemPrice['PERCENT'],
2336 'CURRENCY' => $itemPrice['CURRENCY']
2337 );
2338 unset($itemPrice);
2339 }
2340 }
2341 }
2342
2343 if (!empty($item['DISPLAY_PROPERTIES']))
2344 {
2345 foreach ($item['DISPLAY_PROPERTIES'] as $propKey => $displayProp)
2346 {
2347 {
2348 if ($displayProp['PROPERTY_TYPE'] === 'F')
2349 {
2350 unset($item['DISPLAY_PROPERTIES'][$propKey]);
2351 }
2352 }
2353 }
2354 }
2355
2356 $item['LAST_ELEMENT'] = 'N';
2357 }
2358
2359 end($items);
2360 $items[key($items)]['LAST_ELEMENT'] = 'Y';
2361 }
2362
2363 protected function editTemplateProductPictures(&$item)
2364 {
2365 $iblockParams = $this->storage['IBLOCK_PARAMS'][$item['IBLOCK_ID']];
2366 $productPictures = \CIBlockPriceTools::getDoublePicturesForItem($item, $iblockParams['ADD_PICT_PROP']);
2367
2368 if (empty($productPictures['PICT']))
2369 {
2370 $productPictures['PICT'] = $this->arResult['DEFAULT_PICTURE'];
2371 }
2372
2373 if (empty($productPictures['SECOND_PICT']))
2374 {
2375 $productPictures['SECOND_PICT'] = $productPictures['PICT'];
2376 }
2377
2378 $item['PREVIEW_PICTURE'] = $productPictures['PICT'];
2379 $item['PREVIEW_PICTURE_SECOND'] = $productPictures['SECOND_PICT'];
2380 $item['SECOND_PICT'] = true;
2381 $item['PRODUCT_PREVIEW'] = $productPictures['PICT'];
2382 $item['PRODUCT_PREVIEW_SECOND'] = $productPictures['SECOND_PICT'];
2383 }
2384
2385 protected function editTemplateJsOffers(&$item)
2386 {
2387 $matrix = array();
2388 $boolSkuDisplayProperties = false;
2389 $intSelected = -1;
2390
2391 foreach ($item['OFFERS'] as $offerKey => $offer)
2392 {
2393 if ($item['OFFER_ID_SELECTED'] > 0)
2394 {
2395 $foundOffer = ($item['OFFER_ID_SELECTED'] == $offer['ID']);
2396 }
2397 else
2398 {
2399 $foundOffer = $offer['CAN_BUY'];
2400 }
2401
2402 if ($foundOffer && $intSelected == -1)
2403 {
2404 $intSelected = $offerKey;
2405 }
2406
2407 unset($foundOffer);
2408
2409 $skuProps = false;
2410 if (!empty($offer['DISPLAY_PROPERTIES']))
2411 {
2412 $boolSkuDisplayProperties = true;
2413 $skuProps = array();
2414 foreach ($offer['DISPLAY_PROPERTIES'] as $oneProp)
2415 {
2416 if ($oneProp['PROPERTY_TYPE'] === 'F')
2417 continue;
2418
2419 $skuProps[] = array(
2420 'CODE' => $oneProp['CODE'],
2421 'NAME' => $oneProp['NAME'],
2422 'VALUE' => $oneProp['DISPLAY_VALUE']
2423 );
2424 }
2425 unset($oneProp);
2426 }
2427
2428 $ratioSelectedIndex = $offer['ITEM_MEASURE_RATIO_SELECTED'];
2429 $oneRow = array(
2430 'ID' => $offer['ID'],
2431 'NAME' => ($offer['~NAME'] ?? ''),
2432 'TREE' => $offer['TREE'],
2433 'DISPLAY_PROPERTIES' => $skuProps,
2434
2435 // compatible prices
2436 'PRICE' => ($offer['RATIO_PRICE'] ?? $offer['MIN_PRICE'] ?? 0),
2437 'BASIS_PRICE' => ($offer['MIN_PRICE'] ?? 0),
2438
2439 // new prices
2440 'ITEM_PRICE_MODE' => $offer['ITEM_PRICE_MODE'],
2441 'ITEM_PRICES' => $offer['ITEM_PRICES'],
2442 'ITEM_PRICE_SELECTED' => $offer['ITEM_PRICE_SELECTED'],
2443 'ITEM_QUANTITY_RANGES' => $offer['ITEM_QUANTITY_RANGES'],
2444 'ITEM_QUANTITY_RANGE_SELECTED' => $offer['ITEM_QUANTITY_RANGE_SELECTED'],
2445 'ITEM_MEASURE_RATIOS' => $offer['ITEM_MEASURE_RATIOS'],
2446 'ITEM_MEASURE_RATIO_SELECTED' => $ratioSelectedIndex,
2447 'SECOND_PICT' => $offer['SECOND_PICT'],
2448 'OWNER_PICT' => $offer['OWNER_PICT'],
2449 'PREVIEW_PICTURE' => $offer['PREVIEW_PICTURE'],
2450 'PREVIEW_PICTURE_SECOND' => $offer['PREVIEW_PICTURE_SECOND'],
2451 'CHECK_QUANTITY' => $offer['CHECK_QUANTITY'],
2452 'MAX_QUANTITY' => $offer['PRODUCT']['QUANTITY'],
2453 'STEP_QUANTITY' => $offer['ITEM_MEASURE_RATIOS'][$ratioSelectedIndex]['RATIO'], // deprecated
2454 'QUANTITY_FLOAT' => is_float($offer['ITEM_MEASURE_RATIOS'][$ratioSelectedIndex]['RATIO']), //deprecated
2455 'MEASURE' => $offer['ITEM_MEASURE']['TITLE'],
2456 'CAN_BUY' => $offer['CAN_BUY'],
2457 'CATALOG_SUBSCRIBE' => $offer['PRODUCT']['SUBSCRIBE']
2458 );
2459 unset($ratioSelectedIndex);
2460
2461 if (isset($offer['MORE_PHOTO_COUNT']) && $offer['MORE_PHOTO_COUNT'] > 0)
2462 {
2463 $oneRow['MORE_PHOTO'] = $offer['MORE_PHOTO'];
2464 $oneRow['MORE_PHOTO_COUNT'] = $offer['MORE_PHOTO_COUNT'];
2465 }
2466
2467 $matrix[$offerKey] = $oneRow;
2468 }
2469
2470 if ($intSelected == -1)
2471 {
2472 $intSelected = 0;
2473 }
2474
2475 if (!$matrix[$intSelected]['OWNER_PICT'])
2476 {
2477 $item['PREVIEW_PICTURE'] = $matrix[$intSelected]['PREVIEW_PICTURE'];
2478 $item['PREVIEW_PICTURE_SECOND'] = $matrix[$intSelected]['PREVIEW_PICTURE_SECOND'];
2479 }
2480
2481 $item['JS_OFFERS'] = $matrix;
2482 $item['OFFERS_SELECTED'] = $intSelected;
2483 $item['OFFERS_PROPS_DISPLAY'] = $boolSkuDisplayProperties;
2484 }
2485
2486 protected function editTemplateOfferProps(&$item)
2487 {
2488 $matrix = array();
2489 $newOffers = array();
2490 $double = array();
2491 $item['OFFERS_PROP'] = false;
2492 $item['SKU_TREE_VALUES'] = array();
2493
2494 $iblockParams = $this->storage['IBLOCK_PARAMS'][$item['IBLOCK_ID']];
2495 $skuPropList = [];
2496 if (isset($this->arResult['SKU_PROPS'][$item['IBLOCK_ID']]))
2497 {
2498 $skuPropList = $this->arResult['SKU_PROPS'][$item['IBLOCK_ID']];
2499 }
2500 $skuPropIds = array_keys($skuPropList);
2501 $matrixFields = array_fill_keys($skuPropIds, false);
2502
2503 foreach ($item['OFFERS'] as $offerKey => $offer)
2504 {
2505 $offer['ID'] = (int)$offer['ID'];
2506
2507 if (isset($double[$offer['ID']]))
2508 continue;
2509
2510 $row = array();
2511 foreach ($skuPropIds as $code)
2512 {
2513 $row[$code] = $this->getTemplatePropCell($code, $offer, $matrixFields, $skuPropList);
2514 }
2515
2516 $matrix[$offerKey] = $row;
2517
2518 \CIBlockPriceTools::clearProperties($offer['DISPLAY_PROPERTIES'], $iblockParams['OFFERS_TREE_PROPS']);
2519 \CIBlockPriceTools::setRatioMinPrice($offer, false);
2520
2521 if ($this->arParams['SHOW_SLIDER'] === 'Y')
2522 {
2523 $this->editTemplateOfferSlider($offer, $item['IBLOCK_ID'], 5, true, $item['MORE_PHOTO']);
2524 }
2525
2526 $offerPictures = \CIBlockPriceTools::getDoublePicturesForItem($offer, $iblockParams['OFFERS_ADD_PICT_PROP']);
2527 $offer['OWNER_PICT'] = empty($offerPictures['PICT']);
2528 $offer['PREVIEW_PICTURE'] = false;
2529 $offer['PREVIEW_PICTURE_SECOND'] = false;
2530 $offer['SECOND_PICT'] = true;
2531
2532 if (!$offer['OWNER_PICT'])
2533 {
2534 if (empty($offerPictures['SECOND_PICT']))
2535 {
2536 $offerPictures['SECOND_PICT'] = $offerPictures['PICT'];
2537 }
2538
2539 $offer['PREVIEW_PICTURE'] = $offerPictures['PICT'];
2540 $offer['PREVIEW_PICTURE_SECOND'] = $offerPictures['SECOND_PICT'];
2541 }
2542
2543 if ($iblockParams['OFFERS_ADD_PICT_PROP'] != '' && isset($offer['DISPLAY_PROPERTIES'][$iblockParams['OFFERS_ADD_PICT_PROP']]))
2544 {
2545 unset($offer['DISPLAY_PROPERTIES'][$iblockParams['OFFERS_ADD_PICT_PROP']]);
2546 }
2547
2548 $double[$offer['ID']] = true;
2549 $newOffers[$offerKey] = $offer;
2550 }
2551
2552 $item['OFFERS'] = $newOffers;
2553
2554 $usedFields = array();
2555 $sortFields = array();
2556
2557 $matrixKeys = array_keys($matrix);
2558 foreach ($skuPropIds as $propCode)
2559 {
2560 $boolExist = $matrixFields[$propCode];
2561 foreach ($matrixKeys as $offerKey)
2562 {
2563 if ($boolExist)
2564 {
2565 if (!isset($item['OFFERS'][$offerKey]['TREE']))
2566 {
2567 $item['OFFERS'][$offerKey]['TREE'] = array();
2568 }
2569
2570 $propId = $this->arResult['SKU_PROPS'][$item['IBLOCK_ID']][$propCode]['ID'];
2571 $value = $matrix[$offerKey][$propCode]['VALUE'];
2572
2573 if (!isset($item['SKU_TREE_VALUES'][$propId]))
2574 {
2575 $item['SKU_TREE_VALUES'][$propId] = array();
2576 }
2577
2578 $item['SKU_TREE_VALUES'][$propId][$value] = true;
2579 $item['OFFERS'][$offerKey]['TREE']['PROP_'.$propId] = $value;
2580 $item['OFFERS'][$offerKey]['SKU_SORT_'.$propCode] = $matrix[$offerKey][$propCode]['SORT'];
2581 $usedFields[$propCode] = true;
2582 $sortFields['SKU_SORT_'.$propCode] = SORT_NUMERIC;
2583 unset($value, $propId);
2584 }
2585 else
2586 {
2587 unset($matrix[$offerKey][$propCode]);
2588 }
2589 }
2590 unset($offerKey);
2591 }
2592 unset($propCode, $matrixKeys);
2593
2594 $item['OFFERS_PROP'] = $usedFields;
2595 $item['OFFERS_PROP_CODES'] = !empty($usedFields) ? base64_encode(serialize(array_keys($usedFields))) : '';
2596
2597 Collection::sortByColumn($item['OFFERS'], $sortFields);
2598 }
2599
2603 protected function initIblockPropertyFeatures()
2604 {
2605 if (!Iblock\Model\PropertyFeature::isEnabledFeatures())
2606 return;
2607
2608 foreach (array_keys($this->storage['IBLOCK_PARAMS']) as $iblockId)
2609 {
2610 $this->loadDisplayPropertyCodes($iblockId);
2611 $this->loadBasketPropertyCodes($iblockId);
2612 $this->loadOfferTreePropertyCodes($iblockId);
2613 }
2614 unset($iblockId);
2615 }
2616
2621 protected function loadDisplayPropertyCodes($iblockId)
2622 {
2623 $list = Iblock\Model\PropertyFeature::getListPageShowPropertyCodes(
2624 $iblockId,
2625 ['CODE' => 'Y']
2626 );
2627 if ($list === null)
2628 $list = [];
2629 $this->storage['IBLOCK_PARAMS'][$iblockId]['PROPERTY_CODE'] = $list;
2630 if ($this->useCatalog)
2631 {
2632 $list = Iblock\Model\PropertyFeature::getListPageShowPropertyCodes(
2633 $this->getOffersIblockId($iblockId),
2634 ['CODE' => 'Y']
2635 );
2636 if ($list === null)
2637 $list = [];
2638 $this->storage['IBLOCK_PARAMS'][$iblockId]['OFFERS_PROPERTY_CODE'] = $list;
2639 }
2640 unset($list);
2641 }
2642}
getOffersIblockId($iblockId)
Definition: base.php:5078
getBigDataServiceRequestParams($type='')
Definition: base.php:1379
processElement(array &$element)
Definition: base.php:2301
parseCondition($condition, $params)
Definition: base.php:2048
getTemplatePropCell($code, $offer, &$matrixFields, $skuPropList)
Definition: base.php:5045
loadOfferTreePropertyCodes($iblockId)
Definition: base.php:5158
loadBasketPropertyCodes($iblockId)
Definition: base.php:5101
getPropertyList($iblock, $propertyCodes)
Definition: base.php:2460
editTemplateProductSlider(&$item, $iblock, $limit=0, $addDetailToSlider=true, $default=array())
Definition: base.php:4990
offerIblockExist($iblockId)
Definition: base.php:586
editTemplateOfferSlider(&$item, $iblock, $limit=0, $addDetailToSlider=true, $default=array())
Definition: base.php:5010
initNavString(\CIBlockResult $elementIterator)
static predictRowVariants($lineElementCount, $pageElementCount)
getElementList($iblockId, $products)
static parseJsonParameter($jsonString)
static predictElementCountByVariants($variants, $isBigData=false)
modifyDisplayProperties($iblock, &$iblockElements)
prepareElementSortRow(array $params, array $orderRow, array $default)
static isCheckboxProperty(array $property)
Definition: tools.php:189