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