1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
discount.php
См. документацию.
1<?php
2
14use Bitrix\Sale;
15
17{
18 public const TYPE_PERCENT = 'P';
19 public const TYPE_FIX = 'F';
20 public const TYPE_SALE = 'S';
21
22 public const ENTITY_ID = 0;
23 public const CURRENT_FORMAT = 2;
24 public const OLD_FORMAT = 1;
25
26 private const NOTIFY_DISCOUNT_REINDEX_ID = 'CATALOG_DISC_FORMAT';
27
28 static protected $arCacheProduct = array();
29 static protected $arCacheDiscountFilter = array();
30 static protected $arCacheDiscountResult = array();
31 static protected $arCacheProductSectionChain = array();
32 static protected $arCacheProductSections = array();
33 static protected $arCacheProductProperties = array();
34 static protected $cacheDiscountHandlers = array();
35 static protected $usedModules = array();
36
37 static protected $existCouponsManager = null;
38 static protected $useSaleDiscount = null;
39 static protected $getPriceTypesOnly = false;
40 static protected $getPercentFromBasePrice = null;
41 static private $needDiscountCache = [];
42
43 private static function calculatePriceByDiscount($basePrice, $currentPrice, $oneDiscount, &$needErase)
44 {
45 $calculatePrice = false;
46 switch ($oneDiscount['VALUE_TYPE'])
47 {
48 case self::TYPE_PERCENT:
49 $discountValue = Price\Calculation::roundPrecision(
50 -(self::$getPercentFromBasePrice ? $basePrice : $currentPrice) * $oneDiscount['VALUE'] / 100
51 );
52 if (isset($oneDiscount['DISCOUNT_CONVERT']) && $oneDiscount['DISCOUNT_CONVERT'] > 0)
53 {
54 if ($discountValue + $oneDiscount['DISCOUNT_CONVERT'] <= 0)
55 $discountValue = -$oneDiscount['DISCOUNT_CONVERT'];
56 }
57 $needErase = ($currentPrice + $discountValue < 0);
58 if (!$needErase)
59 {
60 $calculatePrice = $currentPrice + $discountValue;
61 }
62 unset($discountValue);
63 break;
64 case self::TYPE_FIX:
65 $needErase = ($oneDiscount['DISCOUNT_CONVERT'] > $currentPrice);
66 if (!$needErase)
67 {
68 $calculatePrice = $currentPrice - $oneDiscount['DISCOUNT_CONVERT'];
69 }
70 break;
71 case self::TYPE_SALE:
72 $needErase = ($oneDiscount['DISCOUNT_CONVERT'] >= $currentPrice);
73 if (!$needErase)
74 {
75 $calculatePrice = $oneDiscount['DISCOUNT_CONVERT'];
76 }
77 break;
78 default:
79 $needErase = true;
80 break;
81 }
82
83 return $calculatePrice;
84 }
85
89 public static function execAgent(): string
90 {
91 if (
93 || (string)Option::get('sale', 'use_sale_discount_only') !== 'N')
94 {
95 return '';
96 }
97
99 [],
100 ['MODULE_ID' => 'catalog', 'TAG' => self::NOTIFY_DISCOUNT_REINDEX_ID]
101 );
102 while ($row = $iterator->Fetch())
103 {
104 \CAdminNotify::Delete($row['ID']);
105 }
106 unset($row, $iterator);
107
108 $defaultLang = '';
109 $messages = [];
111 'select' => ['ID', 'DEF'],
112 'filter' => ['=ACTIVE' => 'Y']
113 ]);
114 while ($row = $iterator->fetch())
115 {
116 if ($defaultLang == '')
117 $defaultLang = $row['ID'];
118 if ($row['DEF'] == 'Y')
119 $defaultLang = $row['ID'];
120 $languageId = $row['ID'];
122 __FILE__,
123 $languageId
124 );
125 $messages[$languageId] = Loc::getMessage(
126 'CATALOG_DISCOUNT_REINDEX_MESS',
127 ['#LANGUAGE_ID#' => $languageId],
128 $languageId
129 );
130 }
131 unset($languageId, $row, $iterator);
132
133 if (!empty($messages))
134 {
136 'MODULE_ID' => 'catalog',
137 'TAG' => self::NOTIFY_DISCOUNT_REINDEX_ID,
138 'ENABLE_CLOSE' => 'Y',
139 'NOTIFY_TYPE' => \CAdminNotify::TYPE_NORMAL,
140 'MESSAGE' => $messages[$defaultLang],
141 'LANG' => $messages
142 ]);
143 }
144 unset($messages, $defaultLang);
145
146 return '';
147 }
148
149 public static function GetDiscountTypes($boolFull = false)
150 {
151 $boolFull = ($boolFull === true);
152 if ($boolFull)
153 {
154 return array(
155 self::TYPE_PERCENT => Loc::getMessage('BT_CAT_DISCOUNT_TYPE_PERCENT'),
156 self::TYPE_FIX => Loc::getMessage('BT_CAT_DISCOUNT_TYPE_FIX'),
157 self::TYPE_SALE => Loc::getMessage('BT_CAT_DISCOUNT_TYPE_SALE_EXT'),
158 );
159 }
160 return array(
161 self::TYPE_PERCENT,
162 self::TYPE_FIX,
163 self::TYPE_SALE,
164 );
165 }
166
167 public static function setSaleDiscountFilter($priceTypesOnly = false)
168 {
170 if (self::$useSaleDiscount)
171 {
172 self::$getPriceTypesOnly = ($priceTypesOnly === true);
173 }
174 }
175
181 public static function getUseBasePrice()
182 {
183 if (self::$getPercentFromBasePrice === null)
185 return self::$getPercentFromBasePrice;
186 }
187
194 public static function setUseBasePrice($useBasePrice)
195 {
196 if ($useBasePrice !== true && $useBasePrice !== false)
197 return;
198 self::$getPercentFromBasePrice = $useBasePrice;
199 }
200
201 public static function CheckFields($ACTION, &$arFields, $ID = 0)
202 {
204 global $APPLICATION, $DB, $USER;
205
206 $boolResult = true;
207 $arMsg = array();
208
209 $ACTION = mb_strtoupper($ACTION);
210 if ($ACTION != 'UPDATE' && $ACTION != 'ADD')
211 return false;
212
213 if (!is_array($arFields))
214 return false;
215
216 $boolValueType = false;
217 $boolValue = false;
218 $arCurrent = array(
219 'VALUE' => 0,
220 'VALUE_TYPE' => ''
221 );
222
223 $clearFields = array(
224 'ID',
225 '~ID',
226 'UNPACK',
227 '~UNPACK',
228 '~CONDITIONS',
229 '~USE_COUPONS',
230 'HANDLERS',
231 '~HANDLERS',
232 'ENTITY',
233 '~ENTITY',
234 '~TYPE',
235 '~VERSION',
236 'TIMESTAMP_X',
237 'DATE_CREATE',
238 '~DATE_CREATE',
239 '~MODIFIED_BY',
240 '~CREATED_BY'
241 );
242 if ($ACTION == 'UPDATE')
243 $clearFields[] = 'CREATED_BY';
244 $arFields = array_filter($arFields, 'CCatalogDiscount::clearFields');
245 foreach ($clearFields as &$fieldName)
246 {
247 if (isset($arFields[$fieldName]))
248 unset($arFields[$fieldName]);
249 }
250 unset($fieldName, $clearFields);
251
252 $arFields['TYPE'] = self::ENTITY_ID;
253 $arFields['VERSION'] = self::CURRENT_FORMAT;
254
255 if ($ACTION == 'ADD')
256 {
257 $boolValueType = true;
258 $boolValue = true;
259
261 'ACTIVE' => 'Y',
262 'RENEWAL' => 'N',
263 'MAX_USES' => 0,
264 'COUNT_USES' => 0,
265 'SORT' => 100,
266 'MAX_DISCOUNT' => 0,
267 'VALUE_TYPE' => self::TYPE_PERCENT,
268 'MIN_ORDER_SUM' => 0,
269 'PRIORITY' => 1,
270 'LAST_DISCOUNT' => 'Y'
271 );
272 $arFields = array_merge($defaultValues, $arFields);
273 unset($defaultValues);
274
275 if (!isset($arFields['SITE_ID']))
276 {
277 $boolResult = false;
278 $arMsg[] = array('id' => 'SITE_ID', 'text' => Loc::getMessage("KGD_EMPTY_SITE"));
279 }
280 if (!isset($arFields['CURRENCY']))
281 {
282 $boolResult = false;
283 $arMsg[] = array('id' => 'CURRENCY', 'text' => Loc::getMessage('KGD_EMPTY_CURRENCY'));
284 }
285 if (!isset($arFields['NAME']))
286 {
287 $boolResult = false;
288 $arMsg[] = array('id' => 'NAME', 'text' => Loc::getMessage('KGD_EMPTY_NAME'));
289 }
290 if (!isset($arFields['VALUE']))
291 {
292 $boolResult = false;
293 $arMsg[] = array('id' => 'VALUE', 'text' => Loc::getMessage('BT_MOD_CATALOG_DISC_ERR_BAD_VALUE'));
294 }
295 if (!isset($arFields['CONDITIONS']))
296 {
297 $boolResult = false;
298 $arMsg[] = array('id' => 'CONDITIONS', 'text' => Loc::getMessage('BT_MOD_CATALOG_DISC_ERR_EMPTY_CONDITIONS'));
299 }
300 $arFields['USE_COUPONS'] = 'N';
301 }
302
303 if ($ACTION == 'UPDATE')
304 {
305 $ID = (int)$ID;
306 if ($ID <= 0)
307 {
308 $boolResult = false;
309 $arMsg[] = array('id' => 'ID', 'text' => Loc::getMessage('BT_MOD_CATALOG_DISC_ERR_BAD_ID', array('#ID#', $ID)));
310 }
311 else
312 {
313 $boolValueType = isset($arFields['VALUE_TYPE']);
314 $boolValue = isset($arFields['VALUE']);
315 if ($boolValueType != $boolValue)
316 {
317 $rsDiscounts = CCatalogDiscount::GetList(
318 array(),
319 array('ID' => $ID),
320 false,
321 false,
322 array('ID', 'VALUE_TYPE', 'VALUE')
323 );
324 if ($arCurrent = $rsDiscounts->Fetch())
325 {
326 $arCurrent['VALUE'] = doubleval($arCurrent['VALUE']);
327 }
328 else
329 {
330 $boolResult = false;
331 $arMsg[] = array('id' => 'ID', 'text' => Loc::getMessage('BT_MOD_CATALOG_DISC_ERR_BAD_ID', array('#ID#', $ID)));
332 }
333 }
334 }
335 }
336
337 if ($boolResult)
338 {
339 if (isset($arFields['SITE_ID']))
340 {
341 if (empty($arFields['SITE_ID']))
342 {
343 $boolResult = false;
344 $arMsg[] = array('id' => 'SITE_ID', 'text' => Loc::getMessage('KGD_EMPTY_SITE'));
345 }
346 }
347 if (isset($arFields['CURRENCY']))
348 {
349 if (empty($arFields['CURRENCY']))
350 {
351 $boolResult = false;
352 $arMsg[] = array('id' => 'CURRENCY', 'text' => Loc::getMessage('KGD_EMPTY_CURRENCY'));
353 }
354 }
355 if (isset($arFields['NAME']))
356 {
357 $arFields['NAME'] = trim($arFields['NAME']);
358 if ($arFields['NAME'] === '')
359 {
360 $boolResult = false;
361 $arMsg[] = array('id' => 'NAME', 'text' => Loc::getMessage('KGD_EMPTY_NAME'));
362 }
363 }
364 if (isset($arFields['ACTIVE']))
365 {
366 $arFields['ACTIVE'] = ($arFields['ACTIVE'] != 'N' ? 'Y' : 'N');
367 }
368 if (isset($arFields['ACTIVE_FROM']))
369 {
370 if (!$DB->IsDate($arFields['ACTIVE_FROM'], false, LANGUAGE_ID, 'FULL'))
371 {
372 $arFields['ACTIVE_FROM'] = false;
373 }
374 }
375 if (isset($arFields['ACTIVE_TO']))
376 {
377 if (!$DB->IsDate($arFields['ACTIVE_TO'], false, LANGUAGE_ID, 'FULL'))
378 {
379 $arFields['ACTIVE_TO'] = false;
380 }
381 }
382 if (isset($arFields['RENEWAL']))
383 {
384 $arFields['RENEWAL'] = ($arFields['RENEWAL'] == 'Y' ? 'Y' : 'N');
385 }
386 if (isset($arFields['MAX_USES']))
387 {
388 $arFields['MAX_USES'] = (int)$arFields['MAX_USES'];
389 if ($arFields['MAX_USES'] < 0)
390 $arFields['MAX_USES'] = 0;
391 }
392 if (isset($arFields['COUNT_USES']))
393 {
394 $arFields['COUNT_USES'] = (int)$arFields['COUNT_USES'];
395 if ($arFields['COUNT_USES'] < 0)
396 $arFields['COUNT_USES'] = 0;
397 }
398 if (isset($arFields['CATALOG_COUPONS']))
399 {
400 if (empty($arFields['CATALOG_COUPONS']) && !is_array($arFields['CATALOG_COUPONS']))
401 unset($arFields['CATALOG_COUPONS']);
402 }
403 if (isset($arFields['SORT']))
404 {
405 $arFields['SORT'] = (int)$arFields['SORT'];
406 if ($arFields['SORT'] <= 0)
407 $arFields['SORT'] = 100;
408 }
409 if (isset($arFields['MAX_DISCOUNT']))
410 {
411 $arFields['MAX_DISCOUNT'] = str_replace(',', '.', $arFields['MAX_DISCOUNT']);
412 $arFields['MAX_DISCOUNT'] = doubleval($arFields['MAX_DISCOUNT']);
413 if ($arFields['MAX_DISCOUNT'] < 0)
414 $arFields['MAX_DISCOUNT'] = 0;
415 }
416
417 if ($boolValueType)
418 {
419 if (!in_array($arFields['VALUE_TYPE'], CCatalogDiscount::GetDiscountTypes()))
420 $arFields['VALUE_TYPE'] = self::TYPE_PERCENT;
421 }
422 if ($boolValue)
423 {
424 $arFields['VALUE'] = str_replace(',', '.', $arFields['VALUE']);
425 $arFields['VALUE'] = doubleval($arFields['VALUE']);
426 if ($arFields['VALUE'] <= 0)
427 {
428 $boolResult = false;
429 $arMsg[] = array('id' => 'VALUE', 'text' => Loc::getMessage('BT_MOD_CATALOG_DISC_ERR_BAD_VALUE'));
430 }
431 }
432 if ($ACTION == 'UPDATE')
433 {
434 if ($boolValue != $boolValueType)
435 {
436 if (!$boolValue)
437 {
438 $arFields['VALUE'] = $arCurrent['VALUE'];
439 $boolValue = true;
440 }
441 if (!$boolValueType)
442 {
443 $arFields['VALUE_TYPE'] = $arCurrent['VALUE_TYPE'];
444 $boolValueType = true;
445 }
446 }
447 }
448 if ($boolValue && $boolValueType)
449 {
450 if ($arFields['VALUE_TYPE'] == self::TYPE_PERCENT && $arFields['VALUE'] > 100)
451 {
452 $boolResult = false;
453 $arMsg[] = array('id' => 'VALUE', 'text' => Loc::getMessage("BT_MOD_CATALOG_DISC_ERR_BAD_VALUE"));
454 }
455 }
456 if (isset($arFields['MIN_ORDER_SUM']))
457 {
458 $arFields['MIN_ORDER_SUM'] = str_replace(',', '.', $arFields['MIN_ORDER_SUM']);
459 $arFields['MIN_ORDER_SUM'] = doubleval($arFields['MIN_ORDER_SUM']);
460 }
461 if (isset($arFields['PRIORITY']))
462 {
463 $arFields['PRIORITY'] = (int)$arFields['PRIORITY'];
464 if (0 >= $arFields['PRIORITY'])
465 $arFields['PRIORITY'] = 1;
466 }
467 if (isset($arFields['LAST_DISCOUNT']))
468 {
469 $arFields['LAST_DISCOUNT'] = ($arFields['LAST_DISCOUNT'] != 'N' ? 'Y' : 'N');
470 }
471 if (isset($arFields['USE_COUPONS']))
472 $arFields['USE_COUPONS'] = ($arFields['USE_COUPONS'] != 'Y' ? 'N' : 'Y');
473 }
474 if ($boolResult)
475 {
476 if (isset($arFields['CONDITIONS']))
477 {
478 if (empty($arFields['CONDITIONS']))
479 {
480 $boolResult = false;
481 $arMsg[] = array('id' => 'CONDITIONS', 'text' => Loc::getMessage("BT_MOD_CATALOG_DISC_ERR_EMPTY_CONDITIONS"));
482 }
483 else
484 {
485 $usedHandlers = array();
486 $usedEntities = array();
487 $boolCond = true;
488 $strEval = '';
489 if (!is_array($arFields['CONDITIONS']))
490 {
491 if (!CheckSerializedData($arFields['CONDITIONS']))
492 {
493 $boolCond = false;
494 $boolResult = false;
495 $arMsg[] = array('id' => 'CONDITIONS', 'text' => Loc::getMessage("BT_MOD_CATALOG_DISC_ERR_BAD_CONDITIONS"));
496 }
497 else
498 {
499 $arFields['CONDITIONS'] = unserialize($arFields['CONDITIONS'], ['allowed_classes' => false]);
500 if (empty($arFields['CONDITIONS']) || !is_array($arFields['CONDITIONS']))
501 {
502 $boolCond = false;
503 $boolResult = false;
504 $arMsg[] = array('id' => 'CONDITIONS', 'text' => Loc::getMessage("BT_MOD_CATALOG_DISC_ERR_BAD_CONDITIONS"));
505 }
506 }
507 }
508 if ($boolCond)
509 {
510 $obCond = new CCatalogCondTree();
511 $boolCond = $obCond->Init(BT_COND_MODE_GENERATE, BT_COND_BUILD_CATALOG, array());
512 if (!$boolCond)
513 {
514 return false;
515 }
516 $strEval = $obCond->Generate($arFields['CONDITIONS'], array('FIELD' => '$arProduct'));
517 if (empty($strEval) || 'false' == $strEval)
518 {
519 $boolCond = false;
520 $boolResult = false;
521 $arMsg[] = array('id' => 'CONDITIONS', 'text' => Loc::getMessage("BT_MOD_CATALOG_DISC_ERR_BAD_CONDITIONS"));
522 }
523 else
524 {
525 $usedHandlers = $obCond->GetConditionHandlers();
526 $usedEntities = $obCond->GetUsedEntityList();
527 }
528 }
529 if ($boolCond)
530 {
531 $arFields['UNPACK'] = $strEval;
532 $arFields['CONDITIONS'] = serialize($arFields['CONDITIONS']);
533 if (!empty($usedHandlers))
534 $arFields['HANDLERS'] = $usedHandlers;
535 if (!empty($usedEntities))
536 $arFields['ENTITY'] = $usedEntities;
537
538 if ($DB->type == 'MYSQL')
539 {
540 if (64000 < strlen($arFields['UNPACK']) || 64000 < strlen($arFields['CONDITIONS']))
541 {
542 $boolResult = false;
543 $arMsg[] = array('id' => 'CONDITIONS', 'text' => Loc::getMessage('BT_MOD_CATALOG_DISC_ERR_CONDITIONS_TOO_LONG'));
544 unset($arFields['UNPACK']);
545 $arFields['CONDITIONS'] = unserialize($arFields['CONDITIONS'], ['allowed_classes' => false]);
546 }
547 }
548 }
549 }
550 }
551 }
552
553 $intUserID = 0;
554 $boolUserExist = CCatalog::IsUserExists();
555 if ($boolUserExist)
556 $intUserID = (int)$USER->GetID();
557 $strDateFunction = $DB->GetNowFunction();
558 $arFields['~TIMESTAMP_X'] = $strDateFunction;
559 if ($boolUserExist)
560 {
561 if (!isset($arFields['MODIFIED_BY']) || (int)$arFields["MODIFIED_BY"] <= 0)
562 $arFields["MODIFIED_BY"] = $intUserID;
563 }
564 if ($ACTION == 'ADD')
565 {
566 $arFields['~DATE_CREATE'] = $strDateFunction;
567 if ($boolUserExist)
568 {
569 if (!isset($arFields['CREATED_BY']) || (int)$arFields["CREATED_BY"] <= 0)
570 $arFields["CREATED_BY"] = $intUserID;
571 }
572 }
573
574 if (!$boolResult)
575 {
576 $obError = new CAdminException($arMsg);
577 $APPLICATION->ResetException();
578 $APPLICATION->ThrowException($obError);
579 }
580 return $boolResult;
581 }
582
583 public static function Add($arFields)
584 {
585 foreach (GetModuleEvents("catalog", "OnBeforeDiscountAdd", true) as $arEvent)
586 {
587 if (ExecuteModuleEventEx($arEvent, array(&$arFields)) === false)
588 return false;
589 }
590
592 if (empty($mxRows) || !is_array($mxRows))
593 return false;
594
595 $boolNewVersion = true;
596 if (!array_key_exists('CONDITIONS', $arFields))
597 {
599 $boolNewVersion = false;
600 }
601
603 $ID = (int)$ID;
604 if ($ID <= 0)
605 return false;
606
607 if ($boolNewVersion)
608 {
609 $arValuesList = self::__GetConditionValues($arFields);
610 if (is_array($arValuesList) && !empty($arValuesList))
611 {
612 self::__GetOldOneEntity($arFields, $arValuesList, 'IBLOCK_IDS', 'CondIBIBlock');
613 self::__GetOldOneEntity($arFields, $arValuesList, 'SECTION_IDS', 'CondIBSection');
614 self::__GetOldOneEntity($arFields, $arValuesList, 'PRODUCT_IDS', 'CondIBElement');
615 }
616 }
617
618 if (!CCatalogDiscount::__UpdateSubdiscount($ID, $mxRows, $arFields['ACTIVE']))
619 return false;
620
622
623 foreach ($arFields['ENTITY'] as $entity)
624 {
625 $fields = array(
626 'DISCOUNT_ID' => $ID,
627 'MODULE_ID' => $entity['MODULE'],
628 'ENTITY' => $entity['ENTITY'],
629 'FIELD_ENTITY' => $entity['FIELD_ENTITY'],
630 );
631 if (isset($entity['ENTITY_ID']))
632 $fields['ENTITY_ID'] = $entity['ENTITY_ID'];
633 if (isset($entity['ENTITY_VALUE']))
634 $fields['ENTITY_VALUE'] = $entity['ENTITY_VALUE'];
635 if (is_array($fields['FIELD_ENTITY']))
636 $fields['FIELD_ENTITY'] = implode('-', $fields['FIELD_ENTITY']);
637 if (isset($entity['FIELD_TABLE']) && is_array($entity['FIELD_TABLE']))
638 {
639 foreach ($entity['FIELD_TABLE'] as $oneField)
640 {
641 if (empty($oneField))
642 continue;
643 $fields['FIELD_TABLE'] = $oneField;
645 }
646 unset($oneField);
647 }
648 else
649 {
650 $fields['FIELD_TABLE'] = (isset($entity['FIELD_TABLE']) ? $entity['FIELD_TABLE'] : $entity['FIELD_ENTITY']);
652 }
653 }
654 unset($entity);
655
656 if (isset($arFields['CATALOG_COUPONS']))
657 {
658 if (!is_array($arFields["CATALOG_COUPONS"]))
659 {
660 $arFields["CATALOG_COUPONS"] = array(
661 "DISCOUNT_ID" => $ID,
662 "ACTIVE" => "Y",
663 "ONE_TIME" => "Y",
664 "COUPON" => $arFields["CATALOG_COUPONS"],
665 "DATE_APPLY" => false
666 );
667 }
668
669 $arKeys = array_keys($arFields["CATALOG_COUPONS"]);
670 if (!is_array($arFields["CATALOG_COUPONS"][$arKeys[0]]))
671 $arFields["CATALOG_COUPONS"] = array($arFields["CATALOG_COUPONS"]);
672
673 foreach ($arFields["CATALOG_COUPONS"] as &$arOneCoupon)
674 {
675 if (!empty($arOneCoupon['COUPON']))
676 {
677 $arOneCoupon['DISCOUNT_ID'] = $ID;
678 if (CCatalogDiscountCoupon::Add($arOneCoupon, false))
679 $arFields['USE_COUPONS'] = 'Y';
680 }
681 if (isset($arOneCoupon))
682 unset($arOneCoupon);
683 }
684 }
685
686 foreach (GetModuleEvents("catalog", "OnDiscountAdd", true) as $arEvent)
687 {
689 }
690
691 return $ID;
692 }
693
694 public static function Update($ID, $arFields)
695 {
696 $ID = (int)$ID;
697 if ($ID <= 0)
698 return false;
699
700 foreach (GetModuleEvents("catalog", "OnBeforeDiscountUpdate", true) as $arEvent)
701 {
702 if (false === ExecuteModuleEventEx($arEvent, array($ID, &$arFields)))
703 return false;
704 }
705
706 $boolExistUserGroups = (isset($arFields['GROUP_IDS']) && is_array($arFields['GROUP_IDS']));
707 $boolExistPriceTypes = (isset($arFields['CATALOG_GROUP_IDS']) && is_array($arFields['CATALOG_GROUP_IDS']));
708 $boolUpdateRestrictions = $boolExistUserGroups || $boolExistPriceTypes || isset($arFields['ACTIVE']);
709
710 $mxRows = false;
711 if ($boolUpdateRestrictions)
712 {
713 if (!$boolExistUserGroups)
714 {
715 if (!CCatalogDiscount::__FillArrays($ID, $arFields, 'GROUP_IDS'))
716 return false;
717 }
718 if (!$boolExistPriceTypes)
719 {
720 if (!CCatalogDiscount::__FillArrays($ID, $arFields, 'CATALOG_GROUP_IDS'))
721 return false;
722 }
724 if (empty($mxRows) || !is_array($mxRows))
725 return false;
726 }
727
728 $boolNewVersion = true;
729 if (!array_key_exists('CONDITIONS', $arFields))
730 {
732 $boolNewVersion = false;
733 }
734
736 return false;
737
738 if ($boolNewVersion)
739 {
740 $arValuesList = self::__GetConditionValues($arFields);
741 if (is_array($arValuesList) && !empty($arValuesList))
742 {
743 self::__GetOldOneEntity($arFields, $arValuesList, 'IBLOCK_IDS', 'CondIBIBlock');
744 self::__GetOldOneEntity($arFields, $arValuesList, 'SECTION_IDS', 'CondIBSection');
745 self::__GetOldOneEntity($arFields, $arValuesList, 'PRODUCT_IDS', 'CondIBElement');
746 }
747 }
748
749 if ($boolUpdateRestrictions)
750 {
751 if (!CCatalogDiscount::__UpdateSubdiscount($ID, $mxRows, (isset($arFields['ACTIVE']) ? $arFields['ACTIVE'] : '')))
752 return false;
753 }
754
756
757 if (isset($arFields['ENTITY']))
758 {
760 'select' => ['ID'],
761 'filter' => ['=DISCOUNT_ID' => $ID],
762 'order' => ['ID' => 'ASC']
763 ]);
764 $entityIds = $iterator->fetchAll();
765 unset($iterator);
766 foreach ($arFields['ENTITY'] as $entity)
767 {
768 $fields = array(
769 'DISCOUNT_ID' => $ID,
770 'MODULE_ID' => $entity['MODULE'],
771 'ENTITY' => $entity['ENTITY'],
772 'FIELD_ENTITY' => $entity['FIELD_ENTITY'],
773 );
774 if (isset($entity['ENTITY_ID']))
775 $fields['ENTITY_ID'] = $entity['ENTITY_ID'];
776 if (isset($entity['ENTITY_VALUE']))
777 $fields['ENTITY_VALUE'] = $entity['ENTITY_VALUE'];
778 if (is_array($fields['FIELD_ENTITY']))
779 $fields['FIELD_ENTITY'] = implode('-', $fields['FIELD_ENTITY']);
780 if (isset($entity['FIELD_TABLE']) && is_array($entity['FIELD_TABLE']))
781 {
782 foreach ($entity['FIELD_TABLE'] as $oneField)
783 {
784 if (empty($oneField))
785 continue;
786 $fields['FIELD_TABLE'] = $oneField;
787 if (!empty($entityIds))
788 {
789 $rowId = array_shift($entityIds);
791 }
792 else
793 {
795 }
796 }
797 unset($oneField);
798 }
799 else
800 {
801 $fields['FIELD_TABLE'] = (isset($entity['FIELD_TABLE']) ? $entity['FIELD_TABLE'] : $entity['FIELD_ENTITY']);
802 if (!empty($entityIds))
803 {
804 $rowId = array_shift($entityIds);
806 }
807 else
808 {
810 }
811 }
812 }
813 unset($entity);
814 if (!empty($entityIds))
815 {
816 foreach ($entityIds as $rowId)
817 {
819 }
820 }
821 unset($entityIds);
822 }
823
824 if (isset($arFields['CATALOG_COUPONS']))
825 {
826 if (!is_array($arFields["CATALOG_COUPONS"]))
827 {
828 $arFields["CATALOG_COUPONS"] = array(
829 "DISCOUNT_ID" => $ID,
830 "ACTIVE" => "Y",
831 "ONE_TIME" => "Y",
832 "COUPON" => $arFields["CATALOG_COUPONS"],
833 "DATE_APPLY" => false
834 );
835 }
836
837 $arKeys = array_keys($arFields["CATALOG_COUPONS"]);
838 if (!is_array($arFields["CATALOG_COUPONS"][$arKeys[0]]))
839 $arFields["CATALOG_COUPONS"] = array($arFields["CATALOG_COUPONS"]);
840
841 foreach ($arFields["CATALOG_COUPONS"] as &$arOneCoupon)
842 {
843 if (!empty($arOneCoupon['COUPON']))
844 {
845 $arOneCoupon['DISCOUNT_ID'] = $ID;
846 CCatalogDiscountCoupon::Add($arOneCoupon, false);
847 }
848 if (isset($arOneCoupon))
849 unset($arOneCoupon);
850 }
851 }
852
853 foreach (GetModuleEvents("catalog", "OnDiscountUpdate", true) as $arEvent)
854 {
856 }
857
858 return $ID;
859 }
860
868 public static function SetCoupon($coupon)
869 {
871 return CCatalogDiscountCoupon::SetCoupon($coupon);
872 }
873
880 public static function GetCoupons()
881 {
884 }
885
893 public static function EraseCoupon($strCoupon)
894 {
896 return CCatalogDiscountCoupon::EraseCoupon($strCoupon);
897 }
898
905 public static function ClearCoupon()
906 {
909 }
910
919 public static function SetCouponByManage($intUserID,$strCoupon)
920 {
922 return CCatalogDiscountCoupon::SetCouponByManage($intUserID,$strCoupon);
923 }
924
932 public static function GetCouponsByManage($intUserID)
933 {
936 }
937
946 public static function EraseCouponByManage($intUserID, $strCoupon)
947 {
949 return CCatalogDiscountCoupon::EraseCouponByManage($intUserID,$strCoupon);
950 }
951
959 public static function ClearCouponsByManage($intUserID)
960 {
963 }
964
965 public static function OnCurrencyDelete($Currency)
966 {
967 if (empty($Currency)) return false;
968
969 $dbDiscounts = CCatalogDiscount::GetList(array(), array("CURRENCY" => $Currency), false, false, array("ID"));
970 while ($arDiscounts = $dbDiscounts->Fetch())
971 {
972 CCatalogDiscount::Delete($arDiscounts["ID"]);
973 }
974
975 return true;
976 }
977
978 public static function OnGroupDelete($GroupID)
979 {
980 global $DB;
981 $GroupID = (int)$GroupID;
982 if ($GroupID <= 0)
983 return false;
984
985 return $DB->Query("DELETE FROM b_catalog_discount2group WHERE GROUP_ID = ".$GroupID, true);
986 }
987
994 public static function GenerateDataFile($ID)
995 {
996 }
997
1005 public static function ClearFile($ID, $strDataFileName = false)
1006 {
1007 }
1008
1009 public static function GetDiscountByPrice($productPriceID, $arUserGroups = array(), $renewal = "N", $siteID = false, $arDiscountCoupons = false)
1010 {
1011 global $APPLICATION;
1012
1013 foreach (GetModuleEvents("catalog", "OnGetDiscountByPrice", true) as $arEvent)
1014 {
1015 $mxResult = ExecuteModuleEventEx($arEvent, array($productPriceID, $arUserGroups, $renewal, $siteID, $arDiscountCoupons));
1016 if (true !== $mxResult)
1017 return $mxResult;
1018 }
1019
1020 $productPriceID = (int)$productPriceID;
1021 if ($productPriceID <= 0)
1022 {
1023 $APPLICATION->ThrowException(Loc::getMessage("BT_MOD_CATALOG_DISC_ERR_PRICE_ID_ABSENT"), "NO_PRICE_ID");
1024 return false;
1025 }
1026
1027 $dbPrice = CPrice::GetListEx(
1028 array(),
1029 array("ID" => $productPriceID),
1030 false,
1031 false,
1032 array("ID", "PRODUCT_ID", "CATALOG_GROUP_ID", "ELEMENT_IBLOCK_ID")
1033 );
1034 if ($arPrice = $dbPrice->Fetch())
1035 {
1036 return CCatalogDiscount::GetDiscount($arPrice["PRODUCT_ID"], $arPrice["ELEMENT_IBLOCK_ID"], array($arPrice["CATALOG_GROUP_ID"]), $arUserGroups, $renewal, $siteID, $arDiscountCoupons);
1037 }
1038 else
1039 {
1040 $APPLICATION->ThrowException(
1042 'BT_MOD_CATALOG_DISC_ERR_PRICE_ID_NOT_FOUND',
1043 array(
1044 '#ID#' => $productPriceID
1045 )
1046 ),
1047 'NO_PRICE'
1048 );
1049 return false;
1050 }
1051 }
1052
1053 public static function GetDiscountByProduct($productID = 0, $arUserGroups = array(), $renewal = "N", $arCatalogGroups = array(), $siteID = false, $arDiscountCoupons = false)
1054 {
1055 global $APPLICATION;
1056
1057 foreach (GetModuleEvents("catalog", "OnGetDiscountByProduct", true) as $arEvent)
1058 {
1059 $mxResult = ExecuteModuleEventEx($arEvent, array($productID, $arUserGroups, $renewal, $arCatalogGroups, $siteID, $arDiscountCoupons));
1060 if (true !== $mxResult)
1061 return $mxResult;
1062 }
1063
1064 $productID = (int)$productID;
1065 if ($productID <= 0)
1066 {
1067 $APPLICATION->ThrowException(
1069 'BT_MOD_CATALOG_DISC_ERR_ELEMENT_ID_NOT_FOUND',
1070 array(
1071 '#ID' => $productID
1072 )
1073 ),
1074 'NO_ELEMENT');
1075 return false;
1076 }
1077
1078 $intIBlockID = CIBlockElement::GetIBlockByID($productID);
1079 if ($intIBlockID === false)
1080 {
1081 $APPLICATION->ThrowException(
1083 'BT_MOD_CATALOG_DISC_ERR_ELEMENT_ID_NOT_FOUND',
1084 array(
1085 '#ID#' => $productID
1086 )
1087 ),
1088 'NO_ELEMENT'
1089 );
1090 return false;
1091 }
1092
1093 return CCatalogDiscount::GetDiscount($productID, $intIBlockID, $arCatalogGroups, $arUserGroups, $renewal, $siteID, $arDiscountCoupons);
1094 }
1095
1096 private static function getDiscountsFromApplyResult(array $calcResults, \Bitrix\Sale\BasketItemBase $basketItem)
1097 {
1098 $finalDiscountList = array();
1099
1100 if($calcResults && !empty($calcResults['PRICES']['BASKET']) && count($calcResults['PRICES']['BASKET']) === 1)
1101 {
1102 if(isset($calcResults['PRICES']['BASKET'][$basketItem->getBasketCode()]))
1103 {
1104 $priceData = $calcResults['PRICES']['BASKET'][$basketItem->getBasketCode()];
1105 if (!empty($calcResults['RESULT']['BASKET'][$basketItem->getBasketCode()]))
1106 {
1107 foreach($calcResults['RESULT']['BASKET'][$basketItem->getBasketCode()] as $resultRow)
1108 {
1109 $realDiscountId = null;
1110 if(!isset($calcResults['DISCOUNT_LIST'][$resultRow['DISCOUNT_ID']]))
1111 {
1112 continue;
1113 }
1114
1115 $realDiscountId = $calcResults['DISCOUNT_LIST'][$resultRow['DISCOUNT_ID']]['REAL_DISCOUNT_ID'];
1116 if(isset($finalDiscountList[$realDiscountId]))
1117 {
1118 continue;
1119 }
1120
1121 $finalDiscountList[$realDiscountId] = array_merge(
1122 $calcResults['DISCOUNT_LIST'][$resultRow['DISCOUNT_ID']],
1123 $calcResults['FULL_DISCOUNT_LIST'][$realDiscountId]
1124 );
1125 }
1126 }
1127 }
1128 }
1129
1130 return $finalDiscountList;
1131 }
1132
1133 private static function getReformattedDiscounts(array $finalDiscountList, array $calcResults, $siteId, $isRenewal = false)
1134 {
1135 $reformatList = array();
1136 foreach($finalDiscountList as $discount)
1137 {
1138 if($discount['SHORT_DESCRIPTION_STRUCTURE'])
1139 {
1140 $actionConfiguration = $discount['SHORT_DESCRIPTION_STRUCTURE'];
1141 }
1142 else
1143 {
1144 $actionConfiguration = \Bitrix\Sale\Discount\Actions::getActionConfiguration($discount);
1145 }
1146
1147 if(!$actionConfiguration || $actionConfiguration['VALUE_TYPE'] === \Bitrix\Sale\Discount\Actions::VALUE_TYPE_SUMM)
1148 {
1149 continue;
1150 }
1151
1152 if($actionConfiguration['TYPE'] == 'Extra')
1153 {
1154 continue;
1155 }
1156
1157 if ($actionConfiguration['TYPE'] == 'Closeout')
1158 $actionConfiguration['VALUE_TYPE'] = self::TYPE_SALE;
1159
1160 $reformattedDiscount = array(
1161 'ID' => $discount['ID'],
1163 'SITE_ID' => $siteId,
1164 'ACTIVE' => 'Y',
1165 'ACTIVE_FROM' => empty($discount['ACTIVE_FROM']) ? '' : $discount['ACTIVE_FROM']->toString(),
1166 'ACTIVE_TO' => empty($discount['ACTIVE_TO']) ? '' : $discount['ACTIVE_TO']->toString(),
1167 'RENEWAL' => $isRenewal? 'Y' : 'N',
1168 'NAME' => $discount['NAME'],
1169 'SORT' => $discount['SORT'],
1170 'MAX_DISCOUNT' => $actionConfiguration['LIMIT_VALUE'],
1171 'VALUE_TYPE' => $actionConfiguration['VALUE_TYPE'],
1172 'VALUE' => $actionConfiguration['VALUE'],
1173 'CURRENCY' => $discount['CURRENCY'],
1174 'PRIORITY' => $discount['PRIORITY'],
1175 'LAST_DISCOUNT' => $discount['LAST_DISCOUNT'],
1176 'LAST_LEVEL_DISCOUNT' => $discount['LAST_LEVEL_DISCOUNT'],
1177 'COUPON' => '',
1178 'COUPON_ONE_TIME' => null,
1179 'COUPON_ACTIVE' => '',
1180 'UNPACK' => $discount['UNPACK'],
1181 'CONDITIONS' => serialize($discount['CONDITIONS']),
1182 'HANDLERS' => array(
1183 'MODULES' => array(),
1184 'EXT_FILES' => array(),
1185 ),
1186 'MODULE_ID' => 'sale', //or catalog?
1187 );
1188
1189 if($discount['USE_COUPONS'] === 'Y')
1190 {
1191 foreach($calcResults['COUPON_LIST'] as $coupon)
1192 {
1193 if($coupon['DATA']['DISCOUNT_ID'] != $discount['REAL_DISCOUNT_ID'])
1194 {
1195 continue;
1196 }
1197
1198 $reformattedDiscount['COUPON'] = $coupon['COUPON'];
1199 $reformattedDiscount['COUPON_ACTIVE'] = $coupon['DATA']['ACTIVE'];
1200 if($coupon['TYPE'] == \Bitrix\Sale\Internals\DiscountCouponTable::TYPE_BASKET_ROW)
1201 {
1202 $reformattedDiscount['COUPON_ONE_TIME'] = 'Y';
1203 }
1204 elseif($coupon['TYPE'] == \Bitrix\Sale\Internals\DiscountCouponTable::TYPE_ONE_ORDER)
1205 {
1206 $reformattedDiscount['COUPON_ONE_TIME'] = 'O';
1207 }
1208 elseif($coupon['TYPE'] == \Bitrix\Sale\Internals\DiscountCouponTable::TYPE_MULTI_ORDER)
1209 {
1210 $reformattedDiscount['COUPON_ONE_TIME'] = 'N';
1211 }
1212 }
1213 }
1214
1215 $reformatList[$discount['ID']] = $reformattedDiscount;
1216 }
1217
1218 return $reformatList;
1219 }
1220
1221 private static function getSaleDiscountsByProduct(array $product, $siteId, array $userGroups, array $priceRow, $isRenewal, $coupons)
1222 {
1223 if (empty($priceRow))
1224 return array();
1225
1226 $registry = Sale\Registry::getInstance(Sale\Registry::REGISTRY_TYPE_ORDER);
1228 $couponManagerClass = $registry->getDiscountCouponClassName();
1229
1230 $freezeCoupons = (empty($coupons) && is_array($coupons));
1231 $directCoupons = (!empty($coupons) && is_array($coupons));
1232 $additionalCoupons = [];
1233
1234 if ($freezeCoupons)
1235 {
1236 $couponManagerClass::freezeCouponStorage();
1237 }
1238 else
1239 {
1240 if ($directCoupons)
1241 {
1242 $existsCoupons = $couponManagerClass::get(
1243 false,
1244 ['COUPON' => $coupons]
1245 );
1246 if (is_array($existsCoupons))
1247 {
1248 $additionalCoupons = array_diff(
1249 $coupons,
1250 $existsCoupons
1251 );
1252 }
1253
1254 if (!empty($additionalCoupons))
1255 {
1256 foreach ($additionalCoupons as $oneCoupon)
1257 {
1258 $couponManagerClass::add($oneCoupon);
1259 }
1260 }
1261 }
1262 }
1263
1265 static $basket = null,
1267 $basketItem = null;
1268
1269 if ($basket !== null)
1270 {
1271 if ($basket->getSiteId() != $siteId)
1272 {
1273 $basket = null;
1274 $basketItem = null;
1275 }
1276 }
1277 if ($basket !== null)
1278 {
1279 $orderedBasket = $basket->getOrder() !== null;
1280 if ($orderedBasket !== $isRenewal)
1281 {
1282 $basket = null;
1283 $basketItem = null;
1284 }
1285 }
1286 if ($basket === null)
1287 {
1289 $basketClass = $registry->getBasketClassName();
1290
1291 $basket = $basketClass::create($siteId);
1292 $basketItem = $basket->createItem($product['MODULE'], $product['ID']);
1293 }
1294
1295 $config = Catalog\Product\Price\Calculation::getConfig();
1296 if ($config['CURRENCY'] !== null && $config['CURRENCY'] != $priceRow['CURRENCY'])
1297 {
1298 $priceRow['PRICE'] = \CCurrencyRates::ConvertCurrency(
1299 $priceRow['PRICE'],
1300 $priceRow['CURRENCY'],
1301 $config['CURRENCY']
1302 );
1303 $priceRow['CURRENCY'] = $config['CURRENCY'];
1304 }
1305
1306 $fields = array(
1307 'PRODUCT_ID' => $product['ID'],
1308 'QUANTITY' => 1,
1309 'LID' => $siteId,
1310 'PRODUCT_PRICE_ID' => $priceRow['ID'],
1311 'PRICE' => $priceRow['PRICE'],
1312 'BASE_PRICE' => $priceRow['PRICE'],
1313 'DISCOUNT_PRICE' => 0,
1314 'CURRENCY' => $priceRow['CURRENCY'],
1315 'CAN_BUY' => 'Y',
1316 'DELAY' => 'N',
1317 'PRICE_TYPE_ID' => (int)$priceRow['CATALOG_GROUP_ID']
1318 );
1319
1320 $basketItem->setFieldsNoDemand($fields);
1321
1322 if($isRenewal)
1323 {
1325 $orderClass = $registry->getOrderClassName();
1326
1327 $order = $orderClass::create($siteId);
1328 $order->setField('RECURRING_ID', 1);
1329 $order->setBasket($basket);
1330
1331 $discount = $order->getDiscount();
1332 }
1333 else
1334 {
1335 $discount = Sale\Discount::buildFromBasket($basket, new Context\UserGroup($userGroups));
1336 }
1337
1338 $discount->setExecuteModuleFilter(array('all', 'catalog'));
1339 $discount->calculate();
1340
1341 $calcResults = $discount->getApplyResult(true);
1342 $finalDiscountList = static::getDiscountsFromApplyResult($calcResults, $basketItem);
1343
1344 if ($freezeCoupons)
1345 {
1346 $couponManagerClass::unFreezeCouponStorage();
1347 }
1348 else
1349 {
1350 if ($directCoupons)
1351 {
1352 if (!empty($additionalCoupons))
1353 {
1354 foreach ($additionalCoupons as $oneCoupon)
1355 {
1356 $couponManagerClass::delete($oneCoupon);
1357 }
1358 }
1359 }
1360 }
1361 $discount->setExecuteModuleFilter(array('all', 'sale', 'catalog'));
1362
1363 return static::getReformattedDiscounts($finalDiscountList, $calcResults, $siteId, $isRenewal);
1364 }
1365
1378 public static function GetDiscount($intProductID, $intIBlockID, $arCatalogGroups = array(), $arUserGroups = array(), $strRenewal = "N", $siteID = false, $arDiscountCoupons = false, $boolSKU = true, $boolGetIDS = false)
1379 {
1380 static $eventOnGetExists = null;
1381 static $eventOnResultExists = null;
1382
1384 global $APPLICATION;
1385
1387
1388 if ($eventOnGetExists === true || $eventOnGetExists === null)
1389 {
1390 foreach (GetModuleEvents("catalog", "OnGetDiscount", true) as $arEvent)
1391 {
1392 $eventOnGetExists = true;
1393 $mxResult = ExecuteModuleEventEx($arEvent, array($intProductID, $intIBlockID, $arCatalogGroups, $arUserGroups, $strRenewal, $siteID, $arDiscountCoupons, $boolSKU, $boolGetIDS));
1394 if ($mxResult !== true)
1395 return $mxResult;
1396 }
1397 if ($eventOnGetExists === null)
1398 $eventOnGetExists = false;
1399 }
1400
1401 $boolSKU = ($boolSKU === true);
1402 $boolGetIDS = ($boolGetIDS === true);
1403
1404 $intProductID = (int)$intProductID;
1405 if ($intProductID <= 0)
1406 {
1407 $APPLICATION->ThrowException(Loc::getMessage("BT_MOD_CATALOG_DISC_ERR_PRODUCT_ID_ABSENT"), "NO_PRODUCT_ID");
1408 return false;
1409 }
1410
1412 if ($intIBlockID <= 0)
1413 {
1414 $APPLICATION->ThrowException(Loc::getMessage("BT_MOD_CATALOG_DISC_ERR_IBLOCK_ID_ABSENT"), "NO_IBLOCK_ID");
1415 return false;
1416 }
1417
1418 if (!is_array($arUserGroups))
1419 $arUserGroups = array($arUserGroups);
1420 $arUserGroups[] = 2;
1421 if (!empty($arUserGroups))
1422 Main\Type\Collection::normalizeArrayValuesByInt($arUserGroups, true);
1423
1424 if (!is_array($arCatalogGroups))
1425 $arCatalogGroups = array($arCatalogGroups);
1426 if (empty($arCatalogGroups))
1427 {
1428 $catalogGroupIterator = CCatalogGroup::GetGroupsList(array(
1429 'GROUP_ID' => $arUserGroups,
1430 'BUY' => array('Y', 'N')
1431 ));
1432 while ($catalogGroup = $catalogGroupIterator->Fetch())
1433 $arCatalogGroups[$catalogGroup['CATALOG_GROUP_ID']] = $catalogGroup['CATALOG_GROUP_ID'];
1434 unset($catalogGroup, $catalogGroupIterator);
1435 }
1436 if (!empty($arCatalogGroups))
1437 {
1438 $emptyExist = (in_array(-1, $arCatalogGroups));
1439 Main\Type\Collection::normalizeArrayValuesByInt($arCatalogGroups, true);
1440 if ($emptyExist)
1441 $arCatalogGroups = array_merge(array(-1), $arCatalogGroups);
1442 unset($emptyExist);
1443 }
1444 if (empty($arCatalogGroups))
1445 return false;
1446
1447 $strRenewal = ((string)$strRenewal == 'Y' ? 'Y' : 'N');
1448
1449 if ($siteID === false)
1450 $siteID = SITE_ID;
1451
1452 $arSKUExt = false;
1453 if ($boolSKU)
1454 {
1456 $boolSKU = !empty($arSKUExt);
1457 }
1458
1459 $arResult = array();
1460 $arResultID = array();
1461
1462 if (self::$useSaleDiscount && Loader::includeModule('sale'))
1463 {
1464 $registry = Sale\Registry::getInstance(Sale\Registry::REGISTRY_TYPE_ORDER);
1466 $couponManagerClass = $registry->getDiscountCouponClassName();
1467
1468 $cacheIndex = 'S'.$siteID.'-U'.implode('_', $arUserGroups);
1469 $needCoupons = [];
1470 if (!empty($arDiscountCoupons) && is_array($arDiscountCoupons))
1471 {
1472 $clearCoupons = array_filter($arDiscountCoupons);
1473 if (!empty($clearCoupons))
1474 {
1475 foreach ($clearCoupons as $coupon)
1476 {
1477 $row = $couponManagerClass::getData($coupon, true);
1478 if (!is_array($row))
1479 {
1480 continue;
1481 }
1482 if ($row['CHECK_CODE'] !== $couponManagerClass::COUPON_CHECK_OK)
1483 {
1484 continue;
1485 }
1486 $needCoupons[$coupon] = $row;
1487 }
1488 unset($row);
1489 }
1490 unset($clearCoupons);
1491 }
1492 if (!empty($needCoupons))
1493 {
1494 $cacheIndex .= '-C' . implode('_', array_keys($needCoupons));
1495 }
1496 $cacheIndex = md5($cacheIndex);
1497 if (!isset(self::$needDiscountCache[$cacheIndex]))
1498 {
1499 self::$needDiscountCache[$cacheIndex] = false;
1500
1501 $cache = Sale\Discount\RuntimeCache\DiscountCache::getInstance();
1502 $ids = $cache->getDiscountIds($arUserGroups);
1503 if (!empty($ids))
1504 {
1505 $discountList = $cache->getDiscounts(
1506 $ids,
1507 ['all', 'catalog'],
1508 $siteID,
1509 $needCoupons
1510 );
1511 if (!empty($discountList))
1512 {
1513 self::$needDiscountCache[$cacheIndex] = true;
1514 }
1515 unset($discountList);
1516 }
1517 unset($ids, $cache);
1518 }
1519
1520 $product = array(
1521 'ID' => $intProductID,
1522 'MODULE' => 'catalog',
1523 );
1524
1525 if (self::$needDiscountCache[$cacheIndex] && $arCatalogGroups !== array(-1))
1526 {
1527 Catalog\Product\Price\Calculation::pushConfig();
1528 Catalog\Product\Price\Calculation::setConfig([
1529 'CURRENCY' => Sale\Internals\SiteCurrencyTable::getSiteCurrency($siteID)
1530 ]);
1531
1532 $isCompatibilityUsed = Sale\Compatible\DiscountCompatibility::isUsed();
1533 Sale\Compatible\DiscountCompatibility::stopUsageCompatible();
1534
1535 foreach ($arCatalogGroups as $catalogGroup)
1536 {
1537 $priceRow = Catalog\Discount\DiscountManager::getPriceDataByProductId($intProductID, $catalogGroup);
1538 if (!$priceRow)
1539 continue;
1540
1541 $discountList = self::getSaleDiscountsByProduct(
1542 $product,
1543 $siteID,
1544 $arUserGroups,
1545 $priceRow,
1546 $strRenewal === 'Y',
1547 $arDiscountCoupons
1548 );
1549 foreach ($discountList as $discount)
1550 {
1551 if (isset($arResult[$discount['ID']]))
1552 continue;
1553 $arResult[$discount['ID']] = $discount;
1554 $arResultID[$discount['ID']] = $discount['ID'];
1555 }
1556 }
1557
1558 if ($isCompatibilityUsed)
1559 Sale\Compatible\DiscountCompatibility::revertUsageCompatible();
1560 unset($isCompatibilityUsed);
1561
1562 Catalog\Product\Price\Calculation::popConfig();
1563 }
1564 unset($cacheIndex);
1565 }
1566 else
1567 {
1568 $strCacheKey = md5('C'.implode('_', $arCatalogGroups).'-'.'U'.implode('_', $arUserGroups));
1569 if (!isset(self::$arCacheDiscountFilter[$strCacheKey]))
1570 {
1571 $arFilter = array(
1572 'PRICE_TYPE_ID' => $arCatalogGroups,
1573 'USER_GROUP_ID' => $arUserGroups,
1574 );
1576 if (!empty($arDiscountIDs))
1577 sort($arDiscountIDs);
1578
1579 self::$arCacheDiscountFilter[$strCacheKey] = $arDiscountIDs;
1580 }
1581 else
1582 {
1583 $arDiscountIDs = self::$arCacheDiscountFilter[$strCacheKey];
1584 }
1585
1586 $arProduct = array();
1587 if (!empty($arDiscountIDs))
1588 {
1589 $orderCoupons = array();
1590 if ($arDiscountCoupons === false)
1591 {
1592 if (self::$existCouponsManager && Loader::includeModule('sale'))
1593 {
1594 $arDiscountCoupons = DiscountCouponsManager::getForApply(
1595 array('MODULE_ID' => 'catalog', 'DISCOUNT_ID' => $arDiscountIDs),
1596 array('MODULE_ID' => 'catalog', 'PRODUCT_ID' => $intProductID, 'BASKET_ID' => '0'),
1597 true
1598 );
1599 if (!empty($arDiscountCoupons))
1600 {
1601 $orderCoupons = array_filter($arDiscountCoupons, '\Bitrix\Sale\DiscountCouponsManager::filterOrderCoupons');
1602 $arDiscountCoupons = array_keys($arDiscountCoupons);
1603 }
1604 }
1605 else
1606 {
1607 if (!isset($_SESSION['CATALOG_USER_COUPONS']) || !is_array($_SESSION['CATALOG_USER_COUPONS']))
1608 $_SESSION['CATALOG_USER_COUPONS'] = array();
1609 $arDiscountCoupons = $_SESSION["CATALOG_USER_COUPONS"];
1610 }
1611 }
1612 else
1613 {
1614 if (self::$existCouponsManager && Loader::includeModule('sale'))
1615 {
1616 $orderCoupons = DiscountCouponsManager::getOrderedCoupons(true, array('COUPON' => $arDiscountCoupons));
1617 }
1618 }
1619 if ($arDiscountCoupons === false)
1620 $arDiscountCoupons = array();
1621 $boolGenerate = false;
1622 if (empty(self::$cacheDiscountHandlers))
1623 {
1624 self::$cacheDiscountHandlers = CCatalogDiscount::getDiscountHandlers($arDiscountIDs);
1625 }
1626 else
1627 {
1628 $needDiscountHandlers = array();
1629 foreach ($arDiscountIDs as &$discountID)
1630 {
1631 if (!isset(self::$cacheDiscountHandlers[$discountID]))
1632 $needDiscountHandlers[] = $discountID;
1633 }
1634 unset($discountID);
1635 if (!empty($needDiscountHandlers))
1636 {
1637 $discountHandlersList = CCatalogDiscount::getDiscountHandlers($needDiscountHandlers);
1638 if (!empty($discountHandlersList))
1639 {
1640 foreach ($discountHandlersList as $discountID => $discountHandlers)
1641 self::$cacheDiscountHandlers[$discountID] = $discountHandlers;
1642
1643 unset($discountHandlers, $discountID);
1644 }
1645 unset($discountHandlersList);
1646 }
1647 unset($needDiscountHandlers);
1648 }
1649
1650 $strCacheKey = 'D'.implode('_', $arDiscountIDs).'-'.'S'.$siteID.'-R'.$strRenewal;
1651 if (!empty($arDiscountCoupons))
1652 $strCacheKey .= '-C'.implode('|', $arDiscountCoupons);
1653
1654 $strCacheKey = md5($strCacheKey);
1655
1656 if (!isset(self::$arCacheDiscountResult[$strCacheKey]))
1657 {
1658 $arDiscountList = array();
1659
1660 $couponsDiscount = array();
1661 $couponsList = array();
1662 if (!empty($arDiscountCoupons) && is_array($arDiscountCoupons))
1663 {
1664 $iterator = Catalog\DiscountCouponTable::getList(array(
1665 'select' => array('DISCOUNT_ID', 'COUPON', 'ACTIVE', 'TYPE'),
1666 'filter' => array('@DISCOUNT_ID' => $arDiscountIDs,'@COUPON' => $arDiscountCoupons),
1667 'order' => array('DISCOUNT_ID' => 'ASC')
1668 ));
1669 while ($row = $iterator->fetch())
1670 {
1671 $id = (int)$row['DISCOUNT_ID'];
1672 $couponsList[$row['COUPON']] = $row;
1673 if (isset($couponsDiscount[$id]))
1674 continue;
1675 $couponsDiscount[$id] = $row['COUPON'];
1676 }
1677 unset($id, $row, $iterator);
1678 }
1679
1680 $select = array(
1681 'ID', 'TYPE', 'SITE_ID', 'ACTIVE', 'ACTIVE_FROM', 'ACTIVE_TO',
1682 'RENEWAL', 'NAME', 'SORT', 'MAX_DISCOUNT', 'VALUE_TYPE', 'VALUE', 'CURRENCY',
1683 'PRIORITY', 'LAST_DISCOUNT',
1684 'USE_COUPONS', 'UNPACK', 'CONDITIONS'
1685 );
1686 $currentDatetime = new Main\Type\DateTime();
1687 $discountRows = array_chunk($arDiscountIDs, 500);
1688 foreach ($discountRows as $pageIds)
1689 {
1690 $discountFilter = array(
1691 '@ID' => $pageIds,
1692 '=SITE_ID' => $siteID,
1693 '=TYPE' => Catalog\DiscountTable::TYPE_DISCOUNT,
1694 array(
1695 'LOGIC' => 'OR',
1696 'ACTIVE_FROM' => '',
1697 '<=ACTIVE_FROM' => $currentDatetime
1698 ),
1699 array(
1700 'LOGIC' => 'OR',
1701 'ACTIVE_TO' => '',
1702 '>=ACTIVE_TO' => $currentDatetime
1703 ),
1704 '=RENEWAL' => $strRenewal
1705 );
1706 if (empty($couponsDiscount))
1707 {
1708 $discountFilter['=USE_COUPONS'] = 'N';
1709 }
1710 else
1711 {
1712 $discountFilter[] = array(
1713 'LOGIC' => 'OR',
1714 '=USE_COUPONS' => 'N',
1715 array(
1716 '=USE_COUPONS' => 'Y',
1717 '@ID' => array_keys($couponsDiscount)
1718 )
1719 );
1720 }
1722 $iterator = Catalog\DiscountTable::getList(array(
1723 'select' => $select,
1724 'filter' => $discountFilter
1725 ));
1726 while ($row = $iterator->fetch())
1727 {
1728 $row['HANDLERS'] = array();
1729 $row['MODULE_ID'] = 'catalog';
1730 $row['TYPE'] = (int)$row['TYPE'];
1731 if ($row['ACTIVE_FROM'] instanceof Main\Type\DateTime)
1732 $row['ACTIVE_FROM'] = $row['ACTIVE_FROM']->toString();
1733 if ($row['ACTIVE_TO'] instanceof Main\Type\DateTime)
1734 $row['ACTIVE_TO'] = $row['ACTIVE_TO']->toString();
1735 if ($row['USE_COUPONS'] == 'N')
1736 {
1737 $row['COUPON_ACTIVE'] = '';
1738 $row['COUPON'] = '';
1739 $row['COUPON_ONE_TIME'] = null;
1740 }
1741 else
1742 {
1743 $id = (int)$row['ID'];
1744 if (isset($couponsDiscount[$id]))
1745 {
1746 $coupon = $couponsDiscount[$id];
1747 $row['COUPON'] = $coupon;
1748 $row['COUPON_ACTIVE'] = $couponsList[$coupon]['ACTIVE'];
1749 $row['COUPON_ONE_TIME'] = $couponsList[$coupon]['TYPE'];
1750 unset($coupon);
1751 }
1752 else
1753 {
1754 continue;
1755 }
1756 }
1757 $arDiscountList[] = $row;
1758 }
1759 unset($row, $iterator);
1761 }
1762 unset($pageIds, $discountRows);
1763
1764 self::$arCacheDiscountResult[$strCacheKey] = $arDiscountList;
1765 }
1766 else
1767 {
1768 $arDiscountList = self::$arCacheDiscountResult[$strCacheKey];
1769 }
1770
1771 if (!empty($arDiscountList))
1772 {
1773 $discountApply = array();
1774 foreach ($arDiscountList as &$arPriceDiscount)
1775 {
1776 if (isset($discountApply[$arPriceDiscount['ID']]))
1777 continue;
1778
1779 if (
1780 $arPriceDiscount['COUPON'] != ''
1781 && $arPriceDiscount['COUPON_ACTIVE'] == 'N'
1782 && !isset($orderCoupons[$arPriceDiscount['COUPON']])
1783 )
1784 continue;
1785
1786 if (!$boolGenerate)
1787 {
1788 if (!isset(self::$arCacheProduct[$intProductID]))
1789 {
1790 $arProduct = array('ID' => $intProductID, 'IBLOCK_ID' => $intIBlockID);
1791 if (!self::__GenerateFields($arProduct))
1792 return false;
1793 if ($boolSKU)
1794 {
1795 if (!self::__GenerateParent($arProduct, $arSKUExt))
1796 $boolSKU = false;
1797 }
1798 $boolGenerate = true;
1799 self::$arCacheProduct[$intProductID] = $arProduct;
1800 }
1801 else
1802 {
1803 $boolGenerate = true;
1804 $arProduct = self::$arCacheProduct[$intProductID];
1805 }
1806 }
1807 $discountApply[$arPriceDiscount['ID']] = true;
1808 $applyFlag = true;
1809 if (isset(self::$cacheDiscountHandlers[$arPriceDiscount['ID']]))
1810 {
1811 $arPriceDiscount['HANDLERS'] = self::$cacheDiscountHandlers[$arPriceDiscount['ID']];
1812 $moduleList = self::$cacheDiscountHandlers[$arPriceDiscount['ID']]['MODULES'];
1813 if (!empty($moduleList))
1814 {
1815 foreach ($moduleList as &$moduleID)
1816 {
1817 if (!isset(self::$usedModules[$moduleID]))
1818 self::$usedModules[$moduleID] = Loader::includeModule($moduleID);
1819
1820 if (!self::$usedModules[$moduleID])
1821 {
1822 $applyFlag = false;
1823 break;
1824 }
1825 }
1826 unset($moduleID);
1827 }
1828 unset($moduleList);
1829 }
1830 if ($applyFlag && CCatalogDiscount::__Unpack($arProduct, $arPriceDiscount['UNPACK']))
1831 {
1832 $arResult[] = $arPriceDiscount;
1833 $arResultID[] = $arPriceDiscount['ID'];
1834 }
1835 }
1836 unset($arPriceDiscount);
1837 unset($discountApply);
1838 }
1839 }
1840
1841 if (!$boolGetIDS)
1842 {
1844 'USER_ID' => 0,
1845 'USER_GROUPS' => $arUserGroups,
1846 'SITE_ID' => $siteID
1847 ));
1848 if (!empty($arDiscSave))
1849 $arResult = (!empty($arResult) ? array_merge($arResult, $arDiscSave) : $arDiscSave);
1850 }
1851 else
1852 {
1853 $arResult = $arResultID;
1854 }
1855 }
1856
1857 if ($eventOnResultExists === true || $eventOnResultExists === null)
1858 {
1859 foreach (GetModuleEvents("catalog", "OnGetDiscountResult", true) as $arEvent)
1860 {
1861 $eventOnResultExists = true;
1863 }
1864 if ($eventOnResultExists === null)
1865 $eventOnResultExists = false;
1866 }
1867
1868 return $arResult;
1869 }
1870
1871 public static function HaveCoupons($ID, $excludeID = 0)
1872 {
1873 $ID = (int)$ID;
1874 if ($ID <= 0)
1875 return false;
1876
1877 $arFilter = array("DISCOUNT_ID" => $ID);
1878
1879 $excludeID = (int)$excludeID;
1880 if ($excludeID > 0)
1881 $arFilter['!ID'] = $excludeID;
1882
1883 $dbRes = CCatalogDiscountCoupon::GetList(array(), $arFilter, false, array('nTopCount' => 1), array("ID"));
1884 if ($dbRes->Fetch())
1885 return true;
1886 else
1887 return false;
1888 }
1889
1899 public static function OnSetCouponList($intUserID, $arCoupons, $arModules)
1900 {
1902 return CCatalogDiscountCoupon::OnSetCouponList($intUserID, $arCoupons, $arModules);
1903 }
1904
1914 public static function OnClearCouponList($intUserID, $arCoupons, $arModules)
1915 {
1917 return CCatalogDiscountCoupon::OnClearCouponList($intUserID, $arCoupons, $arModules);
1918 }
1919
1928 public static function OnDeleteCouponList($intUserID, $arModules)
1929 {
1931 return CCatalogDiscountCoupon::OnDeleteCouponList($intUserID, $arModules);
1932 }
1933
1939 public static function GetDiscountForProduct($arProduct, $arParams = false)
1940 {
1941 global $DB;
1942
1944
1945 $arResult = array();
1946
1947 if (empty($arProduct) || !is_array($arProduct))
1948 return $arResult;
1949
1950 if (!is_array($arParams))
1951 $arParams = array();
1952
1953 if (!isset($arProduct['ID']))
1954 $arProduct['ID'] = 0;
1955 $arProduct['ID'] = (int)$arProduct['ID'];
1956 if (!isset($arProduct['IBLOCK_ID']))
1957 $arProduct['IBLOCK_ID'] = 0;
1958 $arProduct['IBLOCK_ID'] = (int)$arProduct['IBLOCK_ID'];
1959 if ($arProduct['IBLOCK_ID'] <= 0 || $arProduct['ID'] <= 0)
1960 return $arResult;
1961
1962 $strRenewal = (isset($arParams['RENEWAL']) ? $arParams['RENEWAL'] : 'N');
1963 $strRenewal = ($strRenewal == 'Y' ? 'Y' : 'N');
1964
1965 $siteList = array();
1966 if (isset($arParams['SITE_ID']))
1967 {
1968 if (!is_array($arParams['SITE_ID']))
1969 $arParams['SITE_ID'] = array($arParams['SITE_ID']);
1970 if (!empty($arParams['SITE_ID']))
1971 $siteList = $arParams['SITE_ID'];
1972 }
1973 if (empty($siteList))
1974 {
1975 $iterator = Iblock\IblockSiteTable::getList(array(
1976 'select' => array('SITE_ID'),
1977 'filter' => array('=IBLOCK_ID' => $arProduct['IBLOCK_ID'])
1978 ));
1979 while ($row = $iterator->fetch())
1980 $siteList[] = $row['SITE_ID'];
1981 unset($row, $iterator);
1982 }
1983
1984 if (self::$useSaleDiscount && Loader::includeModule('sale'))
1985 {
1986 $groupList = CCatalogGroup::GetListArray();
1987 if (empty($groupList))
1988 return $arResult;
1989 $prices = array();
1990 foreach (array_keys($groupList) as $groupId)
1991 {
1992 $priceRow = Catalog\Discount\DiscountManager::getPriceDataByProductId($arProduct['ID'], $groupId);
1993 if (!empty($priceRow))
1994 $prices[$groupId] = $priceRow;
1995 unset($priceRow);
1996 }
1997 unset($groupId, $groupList);
1998 if (empty($prices))
1999 return $arResult;
2000
2001 $renewal = ($strRenewal == 'Y');
2002 $product = array(
2003 'ID' => $arProduct['ID'],
2004 'MODULE' => 'catalog',
2005 );
2006
2007 $allUserGroupsId = array_keys(static::getAllUserGroups());
2008 foreach ($siteList as $siteId)
2009 {
2010 foreach ($prices as $priceRow)
2011 {
2012 if(!$priceRow)
2013 {
2014 continue;
2015 }
2016
2017 $siteResult = self::getSaleDiscountsByProduct(
2018 $product,
2019 $siteId,
2020 $allUserGroupsId,
2021 $priceRow,
2022 $renewal,
2023 []
2024 );
2025 if (empty($siteResult))
2026 continue;
2027
2028 foreach ($siteResult as $discount)
2029 {
2030 if (isset($arResult[$discount['ID']]))
2031 continue;
2032 $arResult[$discount['ID']] = $discount;
2033 }
2034 unset($discount, $siteResult);
2035 }
2036 unset($priceRow);
2037 }
2038 unset($siteId);
2039 }
2040 else
2041 {
2042 $arSKUExt = false;
2043 if (isset($arParams['SKU']) && $arParams['SKU'] == 'Y')
2044 $arSKUExt = CCatalogSku::GetInfoByOfferIBlock($arProduct['IBLOCK_ID']);
2045
2046 $arFieldsParams = array();
2047 if (isset($arParams['TIME_ZONE']))
2048 $arFieldsParams['TIME_ZONE'] = $arParams['TIME_ZONE'];
2049 if (isset($arParams['PRODUCT']))
2050 $arFieldsParams['PRODUCT'] = $arParams['PRODUCT'];
2051 $boolGenerate = false;
2052
2053 $arSelect = array('ID', 'SITE_ID', 'SORT', 'NAME', 'VALUE_TYPE', 'VALUE', 'MAX_DISCOUNT', 'CURRENCY', 'UNPACK', 'NOTES');
2054 if (isset($arParams['DISCOUNT_FIELDS']) && !empty($arParams['DISCOUNT_FIELDS']) && is_array($arParams['DISCOUNT_FIELDS']))
2055 $arSelect = $arParams['DISCOUNT_FIELDS'];
2056 if (!in_array('UNPACK', $arSelect))
2057 $arSelect[] = 'UNPACK';
2058
2059 $strDate = date($DB->DateFormatToPHP(CSite::GetDateFormat("FULL")));
2060 if (isset($arParams['CURRENT_DATE']))
2061 $strDate = $arParams['CURRENT_DATE'];
2062
2063 $strRenewal = (isset($arParams['RENEWAL']) ? $arParams['RENEWAL'] : 'N');
2064 $strRenewal = ($strRenewal == 'Y' ? 'Y' : 'N');
2065
2066 $arFilter = array(
2067 'SITE_ID' => $siteList,
2068 'TYPE' => self::ENTITY_ID,
2069 'ACTIVE' => "Y",
2070 'RENEWAL' => $strRenewal,
2071 '+<=ACTIVE_FROM' => $strDate,
2072 '+>=ACTIVE_TO' => $strDate,
2073 'USE_COUPONS' => 'N'
2074 );
2075 CTimeZone::Disable();
2076 $rsPriceDiscounts = CCatalogDiscount::GetList(
2077 array(),
2078 $arFilter,
2079 false,
2080 false,
2081 $arSelect
2082 );
2083 CTimeZone::Enable();
2084 while ($arPriceDiscount = $rsPriceDiscounts->Fetch())
2085 {
2086 if (!$boolGenerate)
2087 {
2088 if (!isset(self::$arCacheProduct[$arProduct['ID']]))
2089 {
2090 if (!self::__GenerateFields($arProduct, $arFieldsParams))
2091 return $arResult;
2092 if (!empty($arSKUExt))
2093 self::__GenerateParent($arProduct, $arSKUExt);
2094
2095 $boolGenerate = true;
2096 self::$arCacheProduct[$arProduct['ID']] = $arProduct;
2097 }
2098 $arProduct = self::$arCacheProduct[$arProduct['ID']];
2099 }
2100 if (!self::__Unpack($arProduct, $arPriceDiscount['UNPACK']))
2101 continue;
2102
2103 unset($arPriceDiscount['UNPACK']);
2104 $arResult[] = $arPriceDiscount;
2105 }
2106 unset($arPriceDiscount, $rsPriceDiscounts);
2107 }
2108
2109 return $arResult;
2110 }
2111
2112 protected static function getAllUserGroups()
2113 {
2114 static $groups = array();
2115
2116 if(!$groups)
2117 {
2118 $dbGroupsList = \CGroup::GetListEx(Array("ID" => "DESC"), array("ACTIVE" => "Y"));
2119 while ($group = $dbGroupsList->Fetch())
2120 {
2121 $groups[$group["ID"]] = $group["NAME"];
2122 }
2123 }
2124
2125 return $groups;
2126 }
2127
2128 public static function GetRestrictions($arParams, $boolKeys = true, $boolRevert = true)
2129 {
2130 $boolKeys = !!$boolKeys;
2131 $boolRevert = !!$boolRevert;
2132 if (!is_array($arParams) || empty($arParams))
2133 return array();
2134 $arFilter = array('RESTRICTIONS' => true);
2135 if (isset($arParams['USER_GROUPS']) && !empty($arParams['USER_GROUPS']))
2136 $arFilter['USER_GROUP_ID'] = $arParams['USER_GROUPS'];
2137
2138 if (isset($arParams['PRICE_TYPES']) && !empty($arParams['PRICE_TYPES']))
2139 $arFilter['PRICE_TYPE_ID'] = $arParams['PRICE_TYPES'];
2140
2141 if ($boolKeys)
2142 {
2144 }
2145 else
2146 {
2148 if (!empty($arResult) && !empty($arResult['RESTRICTIONS']))
2149 {
2150 if ($boolRevert)
2151 {
2152 foreach ($arResult['RESTRICTIONS'] as &$arOneDiscount)
2153 {
2154 $arOneDiscount['USER_GROUP'] = array_keys($arOneDiscount['USER_GROUP']);
2155 $arOneDiscount['PRICE_TYPE'] = array_keys($arOneDiscount['PRICE_TYPE']);
2156 }
2157 unset($arOneDiscount);
2158 }
2159 }
2160 return $arResult;
2161 }
2162 }
2163
2164 public static function CheckDiscount($arProduct, $arDiscount)
2165 {
2166 if (empty($arProduct) || !is_array($arProduct))
2167 return false;
2168 if (empty($arDiscount) || !is_array($arDiscount) || !isset($arDiscount['UNPACK']))
2169 return false;
2170 return self::__Unpack($arProduct, $arDiscount['UNPACK']);
2171 }
2172
2173 public static function applyDiscountList($price, $currency, &$discountList)
2174 {
2175 $price = (float)$price;
2177 if ($currency === false || !is_array($discountList))
2178 return false;
2179
2180 if (self::$useSaleDiscount === null)
2182
2183 $currentPrice = $price;
2184 $applyDiscountList = array();
2185
2186 $result = array(
2187 'PRICE' => $price,
2188 'CURRENCY' => $currency,
2189 'DISCOUNT_LIST' => array()
2190 );
2191 if ($price <= 0 || empty($discountList))
2192 return $result;
2193
2194 $accumulativeDiscountMode = (string)Option::get('catalog', 'discsave_apply');
2195 $productDiscountList = array();
2196 $accumulativeDiscountList = array();
2197
2199 $price,
2200 $currency,
2201 $discountList,
2202 $productDiscountList,
2203 $accumulativeDiscountList
2204 );
2205 if (!empty($productDiscountList))
2206 {
2207 if (self::$useSaleDiscount && Loader::includeModule('sale'))
2208 {
2211 'PRECISION' => (int)Main\Config\Option::get('sale', 'value_precision')
2212 ]);
2213 $applyDiscountList = array();
2214 foreach ($productDiscountList as $priority => $discounts)
2215 {
2216 foreach ($discounts as $discount)
2217 {
2218 $currentPrice = self::calculatePriceByDiscount($price, $currentPrice, $discount, $needErase);
2219 if ($currentPrice !== false)
2220 {
2221 $applyDiscountList[] = $discount;
2222 if($discount['LAST_DISCOUNT'] === 'Y')
2223 {
2224 break 2;
2225 }
2226 if($discount['LAST_LEVEL_DISCOUNT'] === 'Y')
2227 {
2228 break;
2229 }
2230 }
2231 }
2232 }
2234 }
2235 else
2236 {
2237 foreach ($productDiscountList as &$priority)
2238 {
2239 $currentPrice = self::calculatePriorityLevel($price, $currentPrice, $currency, $priority, $applyDiscountList);
2240 if ($currentPrice === false)
2241 return false;
2242 if (!empty($applyDiscountList))
2243 {
2244 $lastDiscount = end($applyDiscountList);
2245 reset($applyDiscountList);
2246 if (isset($lastDiscount['LAST_DISCOUNT']) && $lastDiscount['LAST_DISCOUNT'] == 'Y')
2247 break;
2248 }
2249 }
2250 unset($priority);
2251 }
2252 }
2253
2254 if (!empty($accumulativeDiscountList))
2255 {
2256 switch ($accumulativeDiscountMode)
2257 {
2259 $applyAccumulativeList = array();
2260 $accumulativePrice = self::calculateDiscSave(
2261 $price,
2262 $price,
2263 $currency,
2264 $accumulativeDiscountList,
2265 $applyAccumulativeList
2266 );
2267 if ($accumulativePrice === false)
2268 return false;
2269 if (!empty($applyAccumulativeList) && $accumulativePrice < $currentPrice)
2270 {
2271 $currentPrice = $accumulativePrice;
2272 $applyDiscountList = $applyAccumulativeList;
2273 }
2274 break;
2276 $currentPrice = self::calculateDiscSave(
2277 $price,
2278 $currentPrice,
2279 $currency,
2280 $accumulativeDiscountList,
2281 $applyDiscountList
2282 );
2283 if ($currentPrice === false)
2284 return false;
2285 break;
2287 if (empty($applyDiscountList))
2288 {
2289 $currentPrice = self::calculateDiscSave(
2290 $price,
2291 $currentPrice,
2292 $currency,
2293 $accumulativeDiscountList,
2294 $applyDiscountList
2295 );
2296 if ($currentPrice === false)
2297 return false;
2298 }
2299 break;
2300 }
2301 }
2302
2303 $result = array(
2304 'PRICE' => $currentPrice,
2305 'CURRENCY' => $currency,
2306 'DISCOUNT_LIST' => $applyDiscountList
2307 );
2308 return $result;
2309 }
2310
2311 public static function calculateDiscountList($priceData, $currency, &$discountList, $getWithVat = true)
2312 {
2313 $getWithVat = ($getWithVat !== false);
2314 $result = array();
2315 if (empty($priceData) || !is_array($priceData))
2316 return $result;
2317 $priceData['PRICE'] = (float)$priceData['PRICE'];
2318 $priceData['CURRENCY'] = CCurrency::checkCurrencyID($priceData['CURRENCY']);
2320 if ($priceData['CURRENCY'] === false || $currency === false || !is_array($discountList))
2321 return $result;
2322
2323 //$discountVat = ((string)Option::get('catalog', 'discount_vat') != 'N');
2324 $discountVat = true;
2325
2326 $currentPrice = (
2327 $priceData['CURRENCY'] == $currency
2328 ? $priceData['PRICE']
2329 : CCurrencyRates::ConvertCurrency($priceData['PRICE'], $priceData['CURRENCY'], $currency)
2330 );
2331 $priceData['ORIG_VAT_INCLUDED'] = $priceData['VAT_INCLUDED'];
2332 if ($discountVat)
2333 {
2334 if ($priceData['VAT_INCLUDED'] == 'N')
2335 {
2336 $currentPrice *= (1 + $priceData['VAT_RATE']);
2337 $priceData['VAT_INCLUDED'] = 'Y';
2338 }
2339 }
2340 else
2341 {
2342 if ($priceData['VAT_INCLUDED'] == 'Y')
2343 {
2344 $currentPrice /= (1 + $priceData['VAT_RATE']);
2345 $priceData['VAT_INCLUDED'] = 'N';
2346 }
2347 }
2348 $currentPrice = Price\Calculation::roundPrecision($currentPrice);
2349 $calculatePrice = $currentPrice;
2350 foreach ($discountList as $discount)
2351 {
2352 switch ($discount['VALUE_TYPE'])
2353 {
2354 case self::TYPE_FIX:
2355 if ($discount['CURRENCY'] == $currency)
2356 $currentDiscount = $discount['VALUE'];
2357 else
2358 $currentDiscount = CCurrencyRates::ConvertCurrency($discount['VALUE'], $discount['CURRENCY'], $currency);
2359 $currentDiscount = Price\Calculation::roundPrecision($currentDiscount);
2360 $currentPrice = $currentPrice - $currentDiscount;
2361 break;
2362 case self::TYPE_PERCENT:
2363 $currentDiscount = $currentPrice*$discount['VALUE']/100.0;
2364 if ($discount['MAX_DISCOUNT'] > 0)
2365 {
2366 if ($discount['CURRENCY'] == $currency)
2367 $maxDiscount = $discount['MAX_DISCOUNT'];
2368 else
2369 $maxDiscount = CCurrencyRates::ConvertCurrency($discount['MAX_DISCOUNT'], $discount['CURRENCY'], $currency);
2370 if ($currentDiscount > $maxDiscount)
2371 $currentDiscount = $maxDiscount;
2372 }
2373 $currentDiscount = Price\Calculation::roundPrecision($currentDiscount);
2374 $currentPrice = $currentPrice - $currentDiscount;
2375 break;
2376 case self::TYPE_SALE:
2377 if ($discount['CURRENCY'] == $currency)
2378 $currentPrice = $discount['VALUE'];
2379 else
2380 $currentPrice = CCurrencyRates::ConvertCurrency($discount['VALUE'], $discount['CURRENCY'], $currency);
2381 $currentPrice = Price\Calculation::roundPrecision($currentPrice);
2382 break;
2383 }
2384 }
2385 unset($discount);
2386
2387 $vatRate = (1 + $priceData['VAT_RATE']);
2388 if ($discountVat)
2389 {
2390 if (!$getWithVat)
2391 {
2392 $calculatePrice /= $vatRate;
2393 $currentPrice /= $vatRate;
2394 }
2395 }
2396 else
2397 {
2398 if ($getWithVat)
2399 {
2400 $calculatePrice *= $vatRate;
2401 $currentPrice *= $vatRate;
2402 }
2403 }
2404 unset($vatRate);
2405 unset($priceData['ORIG_VAT_INCLUDED']);
2406 $unroundBasePrice = $calculatePrice;
2407 $unroundPrice = $currentPrice;
2409 {
2410 $calculatePrice = Catalog\Product\Price::roundPrice(
2411 $priceData['CATALOG_GROUP_ID'],
2412 $calculatePrice,
2413 $currency
2414 );
2415 $currentPrice = Catalog\Product\Price::roundPrice(
2416 $priceData['CATALOG_GROUP_ID'],
2417 $currentPrice,
2418 $currency
2419 );
2420 if (
2421 empty($discountList)
2422 || Catalog\Product\Price\Calculation::compare($result['BASE_PRICE'], $result['PRICE'], '<=')
2423 )
2424 {
2425 $result['BASE_PRICE'] = $result['PRICE'];
2426 }
2427 }
2428 $currentDiscount = ($calculatePrice - $currentPrice);
2429
2430 $result = array(
2431 'PRICE_TYPE_ID' => $priceData['CATALOG_GROUP_ID'],
2432 'BASE_PRICE' => $calculatePrice,
2433 'DISCOUNT_PRICE' => $currentPrice,
2434 'UNROUND_BASE_PRICE' => $unroundBasePrice,
2435 'UNROUND_DISCOUNT_PRICE' => $unroundPrice,
2436 'CURRENCY' => $currency,
2437 'DISCOUNT' => $currentDiscount,
2438 'PERCENT' => (
2439 $calculatePrice > 0 && $currentDiscount > 0
2440 ? round((100*$currentDiscount)/$calculatePrice, 0)
2441 : 0
2442 ),
2443 'VAT_RATE' => $priceData['VAT_RATE'],
2444 'VAT_INCLUDED' => ($getWithVat ? 'Y' : 'N')
2445 );
2446 return $result;
2447 }
2448
2450 {
2451 $result = array(
2452 'ID' => $discount['ID'],
2453 'NAME' => $discount['NAME'],
2454 'COUPON' => '',
2455 'COUPON_TYPE' => '',
2456 'USE_COUPONS' => (isset($discount['USE_COUPONS']) ? $discount['USE_COUPONS'] : 'N'),
2457 'MODULE_ID' => (isset($discount['MODULE_ID']) ? $discount['MODULE_ID'] : 'catalog'),
2458 'TYPE' => $discount['TYPE'],
2459 'VALUE' => $discount['VALUE'],
2460 'VALUE_TYPE' => $discount['VALUE_TYPE'],
2461 'LAST_DISCOUNT' => $discount['LAST_DISCOUNT'],
2462 'MAX_VALUE' => (
2464 ? $discount['MAX_DISCOUNT']
2465 : 0
2466 ),
2467 'CURRENCY' => $discount['CURRENCY'],
2468 'HANDLERS' => (isset($discount['HANDLERS']) ? $discount['HANDLERS'] : array())
2469 );
2470 if (!empty($discount['COUPON']))
2471 {
2472 $result['USE_COUPONS'] = 'Y';
2473 $result['COUPON'] = $discount['COUPON'];
2474 $result['COUPON_TYPE'] = $discount['COUPON_ONE_TIME'];
2475 }
2476 return $result;
2477 }
2478
2479 public static function ExtendBasketItems(&$arBasket, $arExtend)
2480 {
2481 $arFields = array(
2482 'ID',
2483 'IBLOCK_ID',
2484 'CODE',
2485 'XML_ID',
2486 'NAME',
2487 'DATE_ACTIVE_FROM',
2488 'DATE_ACTIVE_TO',
2489 'SORT',
2490 'PREVIEW_TEXT',
2491 'DETAIL_TEXT',
2492 'DATE_CREATE',
2493 'CREATED_BY',
2494 'TIMESTAMP_X',
2495 'MODIFIED_BY',
2496 'TAGS',
2497 'TIMESTAMP_X_UNIX',
2498 'DATE_CREATE_UNIX'
2499 );
2500 $arCatFields = array(
2501 'ID',
2502 'TYPE',
2503 'QUANTITY',
2504 'WEIGHT',
2505 'VAT_ID',
2506 'VAT_INCLUDED',
2507 );
2508
2509 $boolFields = false;
2510 if (isset($arExtend['catalog']['fields']))
2511 $boolFields = (boolean)$arExtend['catalog']['fields'];
2512 $boolProps = false;
2513 if (isset($arExtend['catalog']['props']))
2514 $boolProps = (boolean)$arExtend['catalog']['props'];
2515
2516 $boolPrice = !empty($arExtend['catalog']['price']);
2517 $productPriceIds = array();
2518 $basketItemIds = array();
2519
2520 if ($boolFields || $boolProps || $boolPrice)
2521 {
2522 $arMap = array();
2523 $arIDS = array();
2524 foreach ($arBasket as $strKey => $arOneRow)
2525 {
2526 if (isset($arOneRow['MODULE']) && 'catalog' == $arOneRow['MODULE'])
2527 {
2528 $intProductID = (int)$arOneRow['PRODUCT_ID'];
2529 if ($intProductID > 0)
2530 {
2531 $arIDS[$intProductID] = true;
2532 if (!isset($arMap[$intProductID]))
2533 $arMap[$intProductID] = array();
2534 $arMap[$intProductID][] = $strKey;
2535 }
2536
2537 if($boolPrice)
2538 {
2539 if(isset($arOneRow['PRODUCT_PRICE_ID']))
2540 {
2541 $productPriceIds[] = $arOneRow['PRODUCT_PRICE_ID'];
2542 }
2543 else
2544 {
2545 $basketItemIds[] = $arOneRow['ID'];
2546 }
2547 }
2548 }
2549 }
2550
2551 if($boolPrice && empty($productPriceIds) && $basketItemIds)
2552 {
2553 //we have old basket.basket component without PRODUCT_PRICE_ID field in basket item
2554 $basketFilter = array(
2555 'filter' => array(
2556 '@ID' => $basketItemIds
2557 ),
2558 'select' => array('ID', 'PRODUCT_PRICE_ID',),
2559 );
2560 $registry = Sale\Registry::getInstance(Sale\Registry::REGISTRY_TYPE_ORDER);
2561
2563 $basketClass = $registry->getBasketClassName();
2564
2565 $res = $basketClass::getList($basketFilter);
2566 while($basketItem = $res->fetch())
2567 {
2568 $productPriceIds[] = $basketItem['PRODUCT_PRICE_ID'];
2569 }
2570 }
2571
2572 if (!empty($arIDS))
2573 {
2574 $offerIds = array();
2575 $arBasketResult = array();
2576 $iblockGroup = array();
2577 $arIDS = array_keys($arIDS);
2580 $rsItems = CIBlockElement::GetList(array(), array('ID' => $arIDS), false, false, $arFields);
2581 while ($arItem = $rsItems->Fetch())
2582 {
2583 $arBasketData = array();
2584 $arItem['ID'] = (int)$arItem['ID'];
2585 $arItem['IBLOCK_ID'] = (int)$arItem['IBLOCK_ID'];
2586 if (!isset($iblockGroup[$arItem['IBLOCK_ID']]))
2587 $iblockGroup[$arItem['IBLOCK_ID']] = array();
2588 $iblockGroup[$arItem['IBLOCK_ID']][] = $arItem['ID'];
2589 if ($boolFields)
2590 {
2591 $arBasketData['ID'] = $arItem['ID'];
2592 $arBasketData['IBLOCK_ID'] = $arItem['IBLOCK_ID'];
2593 $arBasketData['NAME'] = $arItem['NAME'];
2594 $arBasketData['XML_ID'] = (string)$arItem['XML_ID'];
2595 $arBasketData['CODE'] = (string)$arItem['CODE'];
2596 $arBasketData['TAGS'] = (string)$arItem['TAGS'];
2597 $arBasketData['SORT'] = (int)$arItem['SORT'];
2598 $arBasketData['PREVIEW_TEXT'] = (string)$arItem['PREVIEW_TEXT'];
2599 $arBasketData['DETAIL_TEXT'] = (string)$arItem['DETAIL_TEXT'];
2600 $arBasketData['CREATED_BY'] = (int)$arItem['CREATED_BY'];
2601 $arBasketData['MODIFIED_BY'] = (int)$arItem['MODIFIED_BY'];
2602
2603 $arBasketData['DATE_ACTIVE_FROM'] = (string)$arItem['DATE_ACTIVE_FROM'];
2604 if (!empty($arBasketData['DATE_ACTIVE_FROM']))
2605 $arBasketData['DATE_ACTIVE_FROM'] = (int)MakeTimeStamp($arBasketData['DATE_ACTIVE_FROM']);
2606
2607 $arBasketData['DATE_ACTIVE_TO'] = (string)$arItem['DATE_ACTIVE_TO'];
2608 if (!empty($arBasketData['DATE_ACTIVE_TO']))
2609 $arBasketData['DATE_ACTIVE_TO'] = (int)MakeTimeStamp($arBasketData['DATE_ACTIVE_TO']);
2610
2611 if (isset($arItem['DATE_CREATE_UNIX']))
2612 {
2613 $arBasketData['DATE_CREATE'] = (string)$arItem['DATE_CREATE_UNIX'];
2614 if ($arBasketData['DATE_CREATE'] != '')
2615 $arBasketData['DATE_CREATE'] = (int)$arBasketData['DATE_CREATE'];
2616 }
2617 else
2618 {
2619 $arBasketData['DATE_CREATE'] = (string)$arItem['DATE_CREATE'];
2620 if ($arBasketData['DATE_CREATE'] != '')
2621 $arBasketData['DATE_CREATE'] = (int)MakeTimeStamp($arBasketData['DATE_CREATE']);
2622 }
2623
2624 if (isset($arItem['TIMESTAMP_X_UNIX']))
2625 {
2626 $arBasketData['TIMESTAMP_X'] = (string)$arItem['TIMESTAMP_X_UNIX'];
2627 if ($arBasketData['TIMESTAMP_X'] != '')
2628 $arBasketData['TIMESTAMP_X'] = (int)$arBasketData['TIMESTAMP_X'];
2629 }
2630 else
2631 {
2632 $arBasketData['TIMESTAMP_X'] = (string)$arItem['TIMESTAMP_X'];
2633 if ($arBasketData['TIMESTAMP_X'] != '')
2634 $arBasketData['TIMESTAMP_X'] = (int)MakeTimeStamp($arBasketData['TIMESTAMP_X']);
2635 }
2636
2637 $arProductSections = self::__GetSectionList($arItem['IBLOCK_ID'], $arItem['ID']);
2638 if ($arProductSections !== false)
2639 $arBasketData['SECTION_ID'] = $arProductSections;
2640 else
2641 $arBasketData['SECTION_ID'] = array();
2642 }
2643 if ($boolProps)
2644 {
2645 $arBasketData['PROPERTIES'] = array();
2646 }
2647 $arBasketResult[$arItem['ID']] = $arBasketData;
2648 }
2649 $propertyFilter = array();
2650 if (isset($arExtend['iblock']['props']) && is_array($arExtend['iblock']['props']))
2651 $propertyFilter = array('ID' => $arExtend['iblock']['props']);
2652 if (!empty($iblockGroup))
2653 {
2654 $catalogIterator = Catalog\CatalogIblockTable::getList(array(
2655 'select' => array('IBLOCK_ID', 'SKU_PROPERTY_ID', 'PRODUCT_IBLOCK_ID'),
2656 'filter' => array('@IBLOCK_ID' => array_keys($iblockGroup))
2657 ));
2658 while ($catalog = $catalogIterator->fetch())
2659 {
2660 $skuPropertyId = (int)$catalog['SKU_PROPERTY_ID'];
2661 if ($skuPropertyId > 0)
2662 {
2663 if (!isset($propertyFilter['ID']))
2664 $propertyFilter['ID'] = array();
2665 $propertyFilter['ID'][] = $skuPropertyId;
2666 if (!empty($iblockGroup[$catalog['IBLOCK_ID']]))
2667 {
2668 foreach ($iblockGroup[$catalog['IBLOCK_ID']] as $itemId)
2669 {
2670 if (!isset($arBasketResult[$itemId]['PROPERTIES']))
2671 $arBasketResult[$itemId]['PROPERTIES'] = array();
2672 }
2673 unset($itemId);
2674 }
2675 $boolProps = true;
2676 }
2677 }
2678 unset($catalog, $catalogIterator);
2679 }
2681 if ($boolProps && !empty($iblockGroup))
2682 {
2683 foreach ($iblockGroup as $iblockID => $iblockItems)
2684 {
2685 $filter = array(
2686 'ID' => $iblockItems,
2687 'IBLOCK_ID' =>$iblockID
2688 );
2690 $arBasketResult,
2691 $iblockID,
2692 $filter,
2693 $propertyFilter,
2694 array(
2695 'ID' => true,
2696 'PROPERTY_TYPE' => true,
2697 'MULTIPLE' => true,
2698 'USER_TYPE' => true,
2699 )
2700 );
2701 }
2702 unset($iblockItems, $iblockID);
2703 foreach ($arBasketResult as &$basketItem)
2704 {
2705 self::__ConvertProperties($basketItem, $basketItem['PROPERTIES'], array('TIME_ZONE' => 'N'));
2706 }
2707 unset($basketItem);
2708 }
2709
2710 if($boolPrice)
2711 {
2712 $priceList = Catalog\PriceTable::getList(array(
2713 'select' => array(
2714 'PRODUCT_ID',
2715 'CATALOG_GROUP_ID',
2716 ),
2717 'filter' => array('@ID' => $productPriceIds),
2718 ));
2719 while($price = $priceList->fetch())
2720 {
2721 if(!isset($arBasketResult[$price['PRODUCT_ID']]))
2722 {
2723 $arBasketResult[$price['PRODUCT_ID']] = array();
2724 }
2725 $arBasketResult[$price['PRODUCT_ID']]['CATALOG_GROUP_ID'] = $price['CATALOG_GROUP_ID'];
2726 }
2727
2728 }
2729
2730 $rsProducts = CCatalogProduct::GetList(array(), array('@ID' => $arIDS), false, false, $arCatFields);
2731 while ($arProduct = $rsProducts->Fetch())
2732 {
2733 $productId = (int)$arProduct['ID'];
2734 $arProduct['TYPE'] = (int)$arProduct['TYPE'];
2735 if ($arProduct['TYPE'] == Catalog\ProductTable::TYPE_OFFER)
2736 $offerIds[$productId] = $productId;
2737 if (!isset($arBasketResult[$productId]))
2738 $arBasketResult[$productId] = array();
2739 unset($arProduct['ID'], $arProduct['TYPE']);
2740
2741 foreach ($arProduct as $productKey => $productValue)
2742 $arBasketResult[$productId]['CATALOG_'.$productKey] = $productValue;
2743 unset($productKey, $productValue);
2744 }
2745 unset($productId, $arProduct, $rsProducts);
2746
2747 if (!empty($offerIds))
2748 {
2749 $products = array();
2750 $productIds = array();
2751 $productList = CCatalogSku::getProductList($offerIds);
2752 if (!empty($productList))
2753 {
2754 foreach (array_keys($productList) as $index)
2755 {
2756 $id = $productList[$index]['ID'];
2757 $iblockId = $productList[$index]['IBLOCK_ID'];
2758 if (!isset($products[$iblockId]))
2759 {
2760 $products[$iblockId] = array();
2761 $productIds[$iblockId] = array();
2762 }
2763 $products[$iblockId][$id] = array();
2764 $productIds[$iblockId][] = $id;
2765 }
2766 unset($iblockId, $id, $index);
2767 }
2768 unset($productList);
2769 if (!empty($products))
2770 {
2772 $stackData = self::$useSaleDiscount;
2773 self::$useSaleDiscount = false;
2774 foreach (array_keys($products) as $iblockId)
2775 {
2776 if (!empty($propertyFilter))
2777 {
2778 $arPropFilter = array(
2779 'ID' => $productIds[$iblockId],
2780 'IBLOCK_ID' => $iblockId
2781 );
2783 $products[$iblockId],
2784 $iblockId,
2785 $arPropFilter,
2786 $propertyFilter,
2787 array(
2788 'ID' => true,
2789 'PROPERTY_TYPE' => true,
2790 'MULTIPLE' => true,
2791 'USER_TYPE' => true,
2792 )
2793 );
2794 }
2795
2796 foreach (array_keys($products[$iblockId]) as $id)
2798 unset($id);
2799
2801 CCatalogDiscount::SetDiscountProductCache($productIds[$iblockId], array('IBLOCK_ID' => $iblockId, 'GET_BY_ID' => 'Y'));
2802 }
2803 self::$useSaleDiscount = $stackData;
2804 }
2805 }
2806
2807 if (!empty($iblockGroup))
2808 {
2809 foreach ($iblockGroup as $iblockID => $iblockItems)
2810 {
2811 $sku = CCatalogSku::GetInfoByOfferIBlock($iblockID);
2812 if (!empty($sku))
2813 {
2814 foreach ($iblockItems as $itemID)
2815 {
2816 $isSku = self::__GenerateParent($arBasketResult[$itemID], $sku);
2817 }
2818 unset($isSku, $itemID);
2819 }
2820 }
2821 unset($sku, $iblockItems, $iblockID);
2822 }
2823
2824 if (!empty($arBasketResult))
2825 {
2826 foreach ($arBasketResult as $intProductID => $arBasketData)
2827 {
2828 foreach ($arMap[$intProductID] as $mxRowID)
2829 {
2830 $arBasket[$mxRowID]['CATALOG'] = $arBasketData;
2831 }
2832 }
2833 }
2835 'PRODUCT' => true,
2836 'SECTIONS' => true,
2837 'PROPERTIES' => true
2838 ));
2839 }
2840 }
2841 }
2842
2848 protected static function __GenerateFields(&$arProduct, $arParams = false)
2849 {
2850 $boolResult = false;
2851 if (!empty($arProduct) && is_array($arProduct))
2852 {
2853 if (!isset($arProduct['IBLOCK_ID']))
2854 $arProduct['IBLOCK_ID'] = 0;
2855 $arProduct['IBLOCK_ID'] = (int)$arProduct['IBLOCK_ID'];
2856 if ($arProduct['IBLOCK_ID'] > 0)
2857 {
2858 if (!is_array($arParams))
2859 $arParams = array();
2860
2861 if (!isset($arProduct['ID']))
2862 $arProduct['ID'] = 0;
2863 $arProduct['ID'] = (int)$arProduct['ID'];
2864 if ($arProduct['ID'] > 0)
2865 {
2866 if (isset($arParams['PRODUCT']) && $arParams['PRODUCT'] == 'Y')
2867 {
2868 $arDefaultProduct = array(
2869 'DATE_ACTIVE_FROM' => '',
2870 'DATE_ACTIVE_TO' => '',
2871 'SORT' => 0,
2872 'PREVIEW_TEXT' => '',
2873 'DETAIL_TEXT' => '',
2874 'TAGS' => '',
2875 'DATE_CREATE' => '',
2876 'TIMESTAMP_X' => '',
2877 'CREATED_BY' => 0,
2878 'MODIFIED_BY' => 0,
2879 'CATALOG_QUANTITY' => '',
2880 'CATALOG_WEIGHT' => '',
2881 'CATALOG_VAT_ID' => '',
2882 'CATALOG_VAT_INCLUDED' => ''
2883 );
2884 $arProduct = array_merge($arDefaultProduct, $arProduct);
2885
2886 static $intTimeOffset = false;
2887 if (false === $intTimeOffset)
2888 $intTimeOffset = CTimeZone::GetOffset();
2889 if (isset($arParams['TIME_ZONE']) && 'N' == $arParams['TIME_ZONE'])
2890 $intTimeOffset = 0;
2891
2892 if (!isset($arProduct['SECTION_ID']))
2893 {
2894 $arProductSections = self::__GetSectionList($arProduct['IBLOCK_ID'], $arProduct['ID']);
2895 if (false !== $arProductSections)
2896 $arProduct['SECTION_ID'] = $arProductSections;
2897 else
2898 $arProduct['SECTION_ID'] = array();
2899 }
2900 else
2901 {
2902 if (!is_array($arProduct['SECTION_ID']))
2903 $arProduct['SECTION_ID'] = array($arProduct['SECTION_ID']);
2904 Main\Type\Collection::normalizeArrayValuesByInt($arProduct['SECTION_ID']);
2905 }
2906
2907 if (!empty($arProduct['DATE_ACTIVE_FROM']))
2908 {
2909 $intStackTimestamp = (int)$arProduct['DATE_ACTIVE_FROM'];
2910 if ($intStackTimestamp.'!' != $arProduct['DATE_ACTIVE_FROM'].'!')
2911 $arProduct['DATE_ACTIVE_FROM'] = (int)MakeTimeStamp($arProduct['DATE_ACTIVE_FROM']) - $intTimeOffset;
2912 else
2913 $arProduct['DATE_ACTIVE_FROM'] = $intStackTimestamp;
2914 }
2915
2916 if (!empty($arProduct['DATE_ACTIVE_TO']))
2917 {
2918 $intStackTimestamp = (int)$arProduct['DATE_ACTIVE_TO'];
2919 if ($intStackTimestamp.'!' != $arProduct['DATE_ACTIVE_TO'].'!')
2920 $arProduct['DATE_ACTIVE_TO'] = (int)MakeTimeStamp($arProduct['DATE_ACTIVE_TO']) - $intTimeOffset;
2921 else
2922 $arProduct['DATE_ACTIVE_TO'] = $intStackTimestamp;
2923 }
2924
2925 $arProduct['SORT'] = (int)$arProduct['SORT'];
2926
2927 if (!empty($arProduct['DATE_CREATE']))
2928 {
2929 $intStackTimestamp = (int)$arProduct['DATE_CREATE'];
2930 if ($intStackTimestamp.'!' != $arProduct['DATE_CREATE'].'!')
2931 $arProduct['DATE_CREATE'] = (int)MakeTimeStamp($arProduct['DATE_CREATE']) - $intTimeOffset;
2932 else
2933 $arProduct['DATE_CREATE'] = $intStackTimestamp;
2934 }
2935
2936 if (!empty($arProduct['TIMESTAMP_X']))
2937 {
2938 $intStackTimestamp = (int)$arProduct['TIMESTAMP_X'];
2939 if ($intStackTimestamp.'!' != $arProduct['TIMESTAMP_X'].'!')
2940 $arProduct['TIMESTAMP_X'] = (int)MakeTimeStamp($arProduct['TIMESTAMP_X']) - $intTimeOffset;
2941 else
2942 $arProduct['TIMESTAMP_X'] = $intStackTimestamp;
2943 }
2944
2945 $arProduct['CREATED_BY'] = (int)$arProduct['CREATED_BY'];
2946 $arProduct['MODIFIED_BY'] = (int)$arProduct['MODIFIED_BY'];
2947
2948 if (isset($arProduct['QUANTITY']))
2949 {
2950 $arProduct['CATALOG_QUANTITY'] = $arProduct['QUANTITY'];
2951 unset($arProduct['QUANTITY']);
2952 }
2953 if ('' != $arProduct['CATALOG_QUANTITY'])
2954 $arProduct['CATALOG_QUANTITY'] = doubleval($arProduct['CATALOG_QUANTITY']);
2955
2956 if (isset($arProduct['WEIGHT']))
2957 {
2958 $arProduct['CATALOG_WEIGHT'] = $arProduct['WEIGHT'];
2959 unset($arProduct['WEIGHT']);
2960 }
2961 if ('' != $arProduct['CATALOG_WEIGHT'])
2962 $arProduct['CATALOG_WEIGHT'] = doubleval($arProduct['CATALOG_WEIGHT']);
2963
2964 if (isset($arProduct['VAT_ID']))
2965 {
2966 $arProduct['CATALOG_VAT_ID'] = $arProduct['VAT_ID'];
2967 unset($arProduct['VAT_ID']);
2968 }
2969 if ('' != $arProduct['CATALOG_VAT_ID'])
2970 $arProduct['CATALOG_VAT_ID'] = (int)$arProduct['CATALOG_VAT_ID'];
2971
2972 if (isset($arProduct['VAT_INCLUDED']))
2973 {
2974 $arProduct['CATALOG_VAT_INCLUDED'] = $arProduct['VAT_INCLUDED'];
2975 unset($arProduct['VAT_INCLUDED']);
2976 }
2977
2978 $arPropParams = array();
2979 if (isset($arParams['TIME_ZONE']) && 'N' == $arParams['TIME_ZONE'])
2980 $arPropParams['TIME_ZONE'] = 'N';
2981
2982 if (isset($arProduct['PROPERTIES']))
2983 {
2984 if (!empty($arProduct['PROPERTIES']) && is_array($arProduct['PROPERTIES']))
2985 {
2986 self::__ConvertProperties($arProduct, $arProduct['PROPERTIES'], $arPropParams);
2987 }
2988 unset($arProduct['PROPERTIES']);
2989 }
2990 }
2991 else
2992 {
2993 $arSelect = array('ID', 'IBLOCK_ID', 'CODE', 'XML_ID', 'NAME', 'ACTIVE', 'DATE_ACTIVE_FROM', 'DATE_ACTIVE_TO',
2994 'SORT', 'PREVIEW_TEXT', 'DETAIL_TEXT', 'DATE_CREATE', 'DATE_CREATE_UNIX', 'CREATED_BY', 'TIMESTAMP_X', 'TIMESTAMP_X_UNIX', 'MODIFIED_BY', 'TAGS', 'CATALOG_QUANTITY');
2995 CTimeZone::Disable();
2996 $rsProducts = CIBlockElement::GetList(array(), array('ID' => $arProduct['ID'], 'IBLOCK_ID' => $arProduct['IBLOCK_ID']), false, false, $arSelect);
2997 CTimeZone::Enable();
2998 if (!($obProduct = $rsProducts->GetNextElement(false,true)))
2999 return $boolResult;
3000
3001 $arProduct = array();
3002 $arProductFields = $obProduct->GetFields();
3003
3004 $arProduct['ID'] = (int)$arProductFields['ID'];
3005 $arProduct['IBLOCK_ID'] = (int)$arProductFields['IBLOCK_ID'];
3006
3007 $arProduct['SECTION_ID'] = array();
3008 $arProductSections = self::__GetSectionList($arProduct['IBLOCK_ID'], $arProduct['ID']);
3009 if (false !== $arProductSections)
3010 $arProduct['SECTION_ID'] = $arProductSections;
3011
3012 $arProduct['CODE'] = (string)$arProductFields['~CODE'];
3013 $arProduct['XML_ID'] = (string)$arProductFields['~XML_ID'];
3014 $arProduct['NAME'] = $arProductFields['~NAME'];
3015
3016 $arProduct['ACTIVE'] = $arProductFields['ACTIVE'];
3017
3018 $arProduct['DATE_ACTIVE_FROM'] = (string)$arProductFields['DATE_ACTIVE_FROM'];
3019 if (!empty($arProduct['DATE_ACTIVE_FROM']))
3020 $arProduct['DATE_ACTIVE_FROM'] = (int)MakeTimeStamp($arProduct['DATE_ACTIVE_FROM']);
3021
3022 $arProduct['DATE_ACTIVE_TO'] = (string)$arProductFields['DATE_ACTIVE_TO'];
3023 if (!empty($arProduct['DATE_ACTIVE_TO']))
3024 $arProduct['DATE_ACTIVE_TO'] = (int)MakeTimeStamp($arProduct['DATE_ACTIVE_TO']);
3025
3026 $arProduct['SORT'] = (int)$arProductFields['SORT'];
3027
3028 $arProduct['PREVIEW_TEXT'] = (string)$arProductFields['~PREVIEW_TEXT'];
3029 $arProduct['DETAIL_TEXT'] = (string)$arProductFields['~DETAIL_TEXT'];
3030 $arProduct['TAGS'] = (string)$arProductFields['~TAGS'];
3031
3032 if (isset($arProductFields['DATE_CREATE_UNIX']))
3033 {
3034 $arProduct['DATE_CREATE'] = (string)$arProductFields['DATE_CREATE_UNIX'];
3035 if ('' != $arProduct['DATE_CREATE'])
3036 $arProduct['DATE_CREATE'] = (int)$arProduct['DATE_CREATE'];
3037 }
3038 else
3039 {
3040 $arProduct['DATE_CREATE'] = (string)$arProductFields['DATE_CREATE'];
3041 if ('' != $arProduct['DATE_CREATE'])
3042 $arProduct['DATE_CREATE'] = (int)MakeTimeStamp($arProduct['DATE_CREATE']);
3043 }
3044
3045 if (isset($arProductFields['TIMESTAMP_X_UNIX']))
3046 {
3047 $arProduct['TIMESTAMP_X'] = (string)$arProductFields['TIMESTAMP_X_UNIX'];
3048 if ('' != $arProduct['TIMESTAMP_X'])
3049 $arProduct['TIMESTAMP_X'] = (int)$arProduct['TIMESTAMP_X'];
3050 }
3051 else
3052 {
3053 $arProduct['TIMESTAMP_X'] = (string)$arProductFields['TIMESTAMP_X'];
3054 if ('' != $arProduct['TIMESTAMP_X'])
3055 $arProduct['TIMESTAMP_X'] = (int)MakeTimeStamp($arProduct['TIMESTAMP_X']);
3056 }
3057
3058 $arProduct['CREATED_BY'] = (int)$arProductFields['CREATED_BY'];
3059 $arProduct['MODIFIED_BY'] = (int)$arProductFields['MODIFIED_BY'];
3060
3061 $arProduct['CATALOG_QUANTITY'] = (string)$arProductFields['CATALOG_QUANTITY'];
3062 if ('' != $arProduct['CATALOG_QUANTITY'])
3063 $arProduct['CATALOG_QUANTITY'] = doubleval($arProduct['CATALOG_QUANTITY']);
3064 $arProduct['CATALOG_WEIGHT'] = (string)$arProductFields['CATALOG_WEIGHT'];
3065 if ('' != $arProduct['CATALOG_WEIGHT'])
3066 $arProduct['CATALOG_WEIGHT'] = doubleval($arProduct['CATALOG_WEIGHT']);
3067
3068 $arProduct['CATALOG_VAT_ID'] = (string)$arProductFields['CATALOG_VAT_ID'];
3069 if ('' != $arProduct['CATALOG_VAT_ID'])
3070 $arProduct['CATALOG_VAT_ID'] = (int)$arProduct['CATALOG_VAT_ID'];
3071
3072 $arProduct['CATALOG_VAT_INCLUDED'] = (string)$arProductFields['CATALOG_VAT_INCLUDED'];
3073
3074 unset($arProductFields);
3075 if (!isset(self::$arCacheProductProperties[$arProduct['ID']]))
3076 {
3077 $arProps = $obProduct->GetProperties(array(), array('ACTIVE' => 'Y', 'EMPTY' => 'N'));
3078 }
3079 else
3080 {
3081 $arProps = self::$arCacheProductProperties[$arProduct['ID']];
3082 }
3083 self::__ConvertProperties($arProduct, $arProps, array('TIME_ZONE' => 'N'));
3084 if (isset(self::$arCacheProductProperties[$arProduct['ID']]))
3085 unset(self::$arCacheProductProperties[$arProduct['ID']]);
3086 if (isset(self::$arCacheProductSections[$arProduct['ID']]))
3087 unset(self::$arCacheProductSections[$arProduct['ID']]);
3088 }
3089 }
3090 else
3091 {
3092 $arProduct['ID'] = 0;
3093 if (!isset($arProduct['SECTION_ID']))
3094 $arProduct['SECTION_ID'] = array();
3095 if (!is_array($arProduct['SECTION_ID']))
3096 $arProduct['SECTION_ID'] = array($arProduct['SECTION_ID']);
3097 Main\Type\Collection::normalizeArrayValuesByInt($arProduct['SECTION_ID']);
3098
3099 $arProduct['DATE_ACTIVE_FROM'] = '';
3100 $arProduct['DATE_ACTIVE_TO'] = '';
3101 $arProduct['SORT'] = 500;
3102
3103 $arProduct['PREVIEW_TEXT'] = '';
3104 $arProduct['DETAIL_TEXT'] = '';
3105 $arProduct['TAGS'] = '';
3106
3107 $arProduct['DATE_CREATE'] = '';
3108 $arProduct['TIMESTAMP_X'] = '';
3109
3110 $arProduct['CREATED_BY'] = 0;
3111 $arProduct['MODIFIED_BY'] = 0;
3112
3113 $arProduct['CATALOG_QUANTITY'] = '';
3114 $arProduct['CATALOG_WEIGHT'] = '';
3115 $arProduct['CATALOG_VAT_ID'] = '';
3116 $arProduct['CATALOG_VAT_INCLUDED'] = '';
3117 }
3118 $boolResult = true;
3119 }
3120 }
3121 return $boolResult;
3122 }
3123
3124 protected static function __GetSectionList($intIBlockID, $intProductID)
3125 {
3126 $mxResult = false;
3128 $intProductID = (int)$intProductID;
3129 if ($intIBlockID > 0 && $intProductID > 0)
3130 {
3131 $mxResult = array();
3132 $arProductSections = array();
3133 if (!isset(self::$arCacheProductSections[$intProductID]))
3134 {
3135 $rsSections = CIBlockElement::GetElementGroups($intProductID, true, array("ID", "IBLOCK_SECTION_ID", "IBLOCK_ELEMENT_ID"));
3136 while ($arSection = $rsSections->Fetch())
3137 {
3138 $arSection['ID'] = (int)$arSection['ID'];
3139 $arSection['IBLOCK_SECTION_ID'] = (int)$arSection['IBLOCK_SECTION_ID'];
3140 $arProductSections[] = $arSection;
3141 }
3142 if (isset($arSection))
3143 unset($arSection);
3144 self::$arCacheProductSections[$intProductID] = $arProductSections;
3145 }
3146 else
3147 {
3148 $arProductSections = self::$arCacheProductSections[$intProductID];
3149 }
3150 if (!empty($arProductSections))
3151 {
3152 foreach ($arProductSections as &$arSection)
3153 {
3154 $mxResult[$arSection['ID']] = true;
3155 if (0 < $arSection['IBLOCK_SECTION_ID'])
3156 {
3157 if (!isset(self::$arCacheProductSectionChain[$arSection['ID']]))
3158 {
3159 self::$arCacheProductSectionChain[$arSection['ID']] = array();
3160 $rsParents = CIBlockSection::GetNavChain($intIBlockID, $arSection['ID'], array('ID'));
3161 while ($arParent = $rsParents->Fetch())
3162 {
3163 $arParent['ID'] = (int)$arParent['ID'];
3164 $mxResult[$arParent['ID']] = true;
3165 self::$arCacheProductSectionChain[$arSection['ID']][] = $arParent["ID"];
3166 }
3167 }
3168 else
3169 {
3170 foreach (self::$arCacheProductSectionChain[$arSection['ID']] as $intOneID)
3171 {
3172 $mxResult[$intOneID] = true;
3173 }
3174 if (isset($intOneID))
3175 unset($intOneID);
3176 }
3177 }
3178 }
3179 if (isset($arSection))
3180 unset($arSection);
3181 }
3182 if (!empty($mxResult))
3183 {
3184 $mxResult = array_keys($mxResult);
3185 sort($mxResult);
3186 }
3187 }
3188 return $mxResult;
3189 }
3190
3196 protected static function __ConvertProperties(&$arProduct, &$arProps, $arParams = false)
3197 {
3198 static $iblockProperties = array();
3199
3200 if (empty($arProps) || !is_array($arProps))
3201 return;
3202
3203 if (!is_array($arParams))
3204 $arParams = array();
3205 static $intTimeOffset = false;
3206 if (false === $intTimeOffset)
3207 $intTimeOffset = CTimeZone::GetOffset();
3208 if (isset($arParams['TIME_ZONE']) && 'N' == $arParams['TIME_ZONE'])
3209 $intTimeOffset = 0;
3210
3211 if (!isset($iblockProperties[$arProduct['IBLOCK_ID']]))
3212 {
3213 $iblockProperties[$arProduct['IBLOCK_ID']] = array();
3214 $propertyIterator = Iblock\PropertyTable::getList(array(
3215 'select' => array('ID', 'IBLOCK_ID', 'CODE', 'PROPERTY_TYPE', 'MULTIPLE', 'USER_TYPE', 'USER_TYPE_SETTINGS'),
3216 'filter' => array('=IBLOCK_ID' => $arProduct['IBLOCK_ID'], '=ACTIVE' => 'Y', '!=PROPERTY_TYPE' => Iblock\PropertyTable::TYPE_FILE),
3217 'order' => array('ID' => 'ASC')
3218 ));
3219 while ($property = $propertyIterator->fetch())
3220 {
3221 $id = (int)$property['ID'];
3222 $property['USER_TYPE'] = (string)$property['USER_TYPE'];
3223 $property['USER_TYPE_SETTINGS'] = (string)$property['USER_TYPE_SETTINGS'];
3224 if ($property['USER_TYPE'] != '')
3225 {
3226 $property['USER_TYPE_SETTINGS'] = (
3227 CheckSerializedData($property['USER_TYPE_SETTINGS'])
3228 ? unserialize($property['USER_TYPE_SETTINGS'], ['allowed_classes' => false])
3229 : array()
3230 );
3231 }
3232 switch ($property['PROPERTY_TYPE'])
3233 {
3237 $property['EMPTY_VALUE'] = array(-1);
3238 break;
3239 default:
3240 $property['EMPTY_VALUE'] = array('');
3241 break;
3242 }
3243 $iblockProperties[$arProduct['IBLOCK_ID']][$id] = $property;
3244 }
3245 unset($property, $propertyIterator);
3246 }
3247
3248 $propertyList = $iblockProperties[$arProduct['IBLOCK_ID']];
3249 foreach ($arProps as &$arOneProp)
3250 {
3251 if ($arOneProp['PROPERTY_TYPE'] == Iblock\PropertyTable::TYPE_FILE)
3252 continue;
3253 $propertyId = (int)$arOneProp['ID'];
3254 if (isset($propertyList[$propertyId]))
3255 unset($propertyList[$propertyId]);
3256 unset($propertyId);
3257 $boolCheck = false;
3258 if ('N' == $arOneProp['MULTIPLE'])
3259 {
3260 if (isset($arOneProp['USER_TYPE']) && !empty($arOneProp['USER_TYPE']))
3261 {
3262 switch($arOneProp['USER_TYPE'])
3263 {
3264 case 'DateTime':
3265 case 'Date':
3266 $arOneProp['VALUE'] = (string)$arOneProp['VALUE'];
3267 if ('' != $arOneProp['VALUE'])
3268 {
3269 $propertyFormat = false;
3270 if ($arOneProp['USER_TYPE'] == 'DateTime')
3271 {
3272 if (defined('FORMAT_DATETIME'))
3273 $propertyFormat = FORMAT_DATETIME;
3274 }
3275 else
3276 {
3277 if (defined('FORMAT_DATE'))
3278 $propertyFormat = FORMAT_DATE;
3279 }
3280 $intStackTimestamp = (int)$arOneProp['VALUE'];
3281 if ($intStackTimestamp.'!' != $arOneProp['VALUE'].'!')
3282 $arOneProp['VALUE'] = (int)MakeTimeStamp($arOneProp['VALUE'], $propertyFormat) - $intTimeOffset;
3283 else
3284 $arOneProp['VALUE'] = $intStackTimestamp;
3285 }
3286 $arProduct['PROPERTY_'.$arOneProp['ID'].'_VALUE'] = $arOneProp['VALUE'];
3287 $boolCheck = true;
3288 break;
3289 }
3290 }
3291 if (!$boolCheck)
3292 {
3293 if ('L' == $arOneProp['PROPERTY_TYPE'])
3294 {
3295 $arOneProp['VALUE_ENUM_ID'] = (int)$arOneProp['VALUE_ENUM_ID'];
3296 if (0 < $arOneProp['VALUE_ENUM_ID'])
3297 $arProduct['PROPERTY_'.$arOneProp['ID'].'_VALUE'] = $arOneProp['VALUE_ENUM_ID'];
3298 else
3299 $arProduct['PROPERTY_'.$arOneProp['ID'].'_VALUE'] = -1;
3300 }
3301 elseif ('E' == $arOneProp['PROPERTY_TYPE'] || 'G' == $arOneProp['PROPERTY_TYPE'])
3302 {
3303 $arOneProp['VALUE'] = (int)$arOneProp['VALUE'];
3304 if (0 < $arOneProp['VALUE'])
3305 $arProduct['PROPERTY_'.$arOneProp['ID'].'_VALUE'] = $arOneProp['VALUE'];
3306 else
3307 $arProduct['PROPERTY_'.$arOneProp['ID'].'_VALUE'] = -1;
3308 }
3309 else
3310 {
3311 $arProduct['PROPERTY_'.$arOneProp['ID'].'_VALUE'] = $arOneProp['VALUE'];
3312 }
3313 }
3314 }
3315 else
3316 {
3317 if (isset($arOneProp['USER_TYPE']) && !empty($arOneProp['USER_TYPE']))
3318 {
3319 switch($arOneProp['USER_TYPE'])
3320 {
3321 case 'DateTime':
3322 case 'Date':
3323 $arValues = array();
3324 if (is_array($arOneProp['VALUE']) && !empty($arOneProp['VALUE']))
3325 {
3326 $propertyFormat = false;
3327 if ($arOneProp['USER_TYPE'] == 'DateTime')
3328 {
3329 if (defined('FORMAT_DATETIME'))
3330 $propertyFormat = FORMAT_DATETIME;
3331 }
3332 else
3333 {
3334 if (defined('FORMAT_DATE'))
3335 $propertyFormat = FORMAT_DATE;
3336 }
3337 foreach ($arOneProp['VALUE'] as &$strOneValue)
3338 {
3339 $strOneValue = (string)$strOneValue;
3340 if ('' != $strOneValue)
3341 {
3342 $intStackTimestamp = (int)$strOneValue;
3343 if ($intStackTimestamp.'!' != $strOneValue.'!')
3344 $strOneValue = (int)MakeTimeStamp($strOneValue, $propertyFormat) - $intTimeOffset;
3345 else
3346 $strOneValue = $intStackTimestamp;
3347 }
3348 $arValues[] = $strOneValue;
3349 }
3350 if (isset($strOneValue))
3351 unset($strOneValue);
3352 }
3353 $arProduct['PROPERTY_'.$arOneProp['ID'].'_VALUE'] = $arValues;
3354 $boolCheck = true;
3355 break;
3356 }
3357 }
3358 if (!$boolCheck)
3359 {
3360 if ('L' == $arOneProp['PROPERTY_TYPE'])
3361 {
3362 $arValues = array();
3363 if (is_array($arOneProp['VALUE_ENUM_ID']) && !empty($arOneProp['VALUE_ENUM_ID']))
3364 {
3365 foreach ($arOneProp['VALUE_ENUM_ID'] as &$intOneValue)
3366 {
3367 $intOneValue = (int)$intOneValue;
3368 if (0 < $intOneValue)
3369 $arValues[] = $intOneValue;
3370 }
3371 if (isset($intOneValue))
3372 unset($intOneValue);
3373 }
3374 if (empty($arValues))
3375 $arValues = array(-1);
3376 $arProduct['PROPERTY_'.$arOneProp['ID'].'_VALUE'] = $arValues;
3377 }
3378 elseif ('E' == $arOneProp['PROPERTY_TYPE'] || 'G' == $arOneProp['PROPERTY_TYPE'])
3379 {
3380 $arValues = array();
3381 if (is_array($arOneProp['VALUE']) && !empty($arOneProp['VALUE']))
3382 {
3383 foreach ($arOneProp['VALUE'] as &$intOneValue)
3384 {
3385 $intOneValue = (int)$intOneValue;
3386 if (0 < $intOneValue)
3387 $arValues[] = $intOneValue;
3388 }
3389 if (isset($intOneValue))
3390 unset($intOneValue);
3391 }
3392 if (empty($arValues))
3393 $arValues = array(-1);
3394 $arProduct['PROPERTY_'.$arOneProp['ID'].'_VALUE'] = $arValues;
3395 }
3396 else
3397 {
3398 $arProduct['PROPERTY_'.$arOneProp['ID'].'_VALUE'] = $arOneProp['VALUE'];
3399 }
3400 }
3401 }
3402 if (!is_array($arProduct['PROPERTY_'.$arOneProp['ID'].'_VALUE']))
3403 $arProduct['PROPERTY_'.$arOneProp['ID'].'_VALUE'] = array($arProduct['PROPERTY_'.$arOneProp['ID'].'_VALUE']);
3404 }
3405 unset($arOneProp);
3406
3407 if (!empty($propertyList))
3408 {
3409 foreach ($propertyList as &$property)
3410 $arProduct['PROPERTY_'.$property['ID'].'_VALUE'] = $property['EMPTY_VALUE'];
3411 unset($property);
3412 }
3413 unset($propertyList);
3414 }
3415
3416 protected static function __GenerateParent(&$product, $sku)
3417 {
3418 $parentID = 0;
3419 if (isset($product['PARENT_ID']))
3420 $parentID = (int)$product['PARENT_ID'];
3421 elseif (isset($product['PROPERTY_'.$sku['SKU_PROPERTY_ID'].'_VALUE']))
3422 $parentID = (int)current($product['PROPERTY_'.$sku['SKU_PROPERTY_ID'].'_VALUE']);
3423 if ($parentID <= 0)
3424 return false;
3425 if (!isset(self::$arCacheProduct[$parentID]))
3426 {
3427 $parent = array('ID' => $parentID, 'IBLOCK_ID' => $sku['PRODUCT_IBLOCK_ID']);
3428 if (!self::__GenerateFields($parent))
3429 return false;
3430 self::$arCacheProduct[$parentID] = $parent;
3431 }
3432 else
3433 {
3434 $parent = self::$arCacheProduct[$parentID];
3435 }
3436 foreach ($parent as $key => $value)
3437 {
3438 if ($key == 'SECTION_ID')
3439 {
3440 $product[$key] = array_merge($product[$key], $value);
3441 }
3442 elseif (strncmp($key, 'PROPERTY_', 9) == 0)
3443 {
3444 $product[$key] = $value;
3445 }
3446 elseif (strncmp($key, 'CATALOG_', 8) != 0)
3447 {
3448 $product['PARENT_'.$key] = $value;
3449 }
3450 }
3451 unset($value, $key, $parent);
3452 return true;
3453 }
3454
3455 protected static function __ParseArrays(&$arFields)
3456 {
3457 global $APPLICATION;
3458
3459 $arMsg = array();
3460 $boolResult = true;
3461
3462 $arResult = array(
3463 );
3464
3465 if (!self::__CheckOneEntity($arFields, 'GROUP_IDS'))
3466 {
3467 $arMsg[] = array('id' => 'GROUP_IDS', "text" => Loc::getMessage('BT_MOD_CATALOG_DISC_ERR_PARSE_USER_GROUP'));
3468 $boolResult = false;
3469 }
3470 if (!self::__CheckOneEntity($arFields, 'CATALOG_GROUP_IDS'))
3471 {
3472 $arMsg[] = array('id' => 'CATALOG_GROUP_IDS', "text" => Loc::getMessage('BT_MOD_CATALOG_DISC_ERR_PARSE_PRICE_TYPE'));
3473 $boolResult = false;
3474 }
3475
3476 if ($boolResult)
3477 {
3478 $arTempo = array(
3479 'USER_GROUP_ID' => $arFields['GROUP_IDS'],
3480 'PRICE_TYPE_ID' => $arFields['CATALOG_GROUP_IDS'],
3481 );
3482
3483 $arOrder = array(
3484 'USER_GROUP_ID',
3485 'PRICE_TYPE_ID',
3486 );
3487
3488 self::__ArrayMultiple($arOrder, $arResult, $arTempo);
3489 unset($arTempo);
3490 }
3491
3492 if (!$boolResult)
3493 {
3494 $obError = new CAdminException($arMsg);
3495 $APPLICATION->ResetException();
3496 $APPLICATION->ThrowException($obError);
3497 return $boolResult;
3498 }
3499 else
3500 {
3501 return $arResult;
3502 }
3503 }
3504
3505 protected static function __CheckOneEntity(&$arFields, $strEntityID)
3506 {
3507 $boolResult = false;
3508 $strEntityID = trim(strval($strEntityID));
3509 if (!empty($strEntityID))
3510 {
3511 if (is_array($arFields) && !empty($arFields))
3512 {
3513 if (is_set($arFields, $strEntityID))
3514 {
3515 if (!is_array($arFields[$strEntityID]))
3516 $arFields[$strEntityID] = array($arFields[$strEntityID]);
3517 $arValid = array();
3518 foreach ($arFields[$strEntityID] as &$value)
3519 {
3520 $value = (int)$value;
3521 if ($value > 0)
3522 $arValid[] = $value;
3523 }
3524 if (isset($value))
3525 unset($value);
3526 if (!empty($arValid))
3527 {
3528 $arValid = array_unique($arValid);
3529 }
3530 $arFields[$strEntityID] = $arValid;
3531
3532 if (empty($arFields[$strEntityID]))
3533 {
3534 $arFields[$strEntityID] = array(-1);
3535 }
3536 }
3537 else
3538 {
3539 $arFields[$strEntityID] = array(-1);
3540 }
3541 }
3542 else
3543 {
3544 $arFields[$strEntityID] = array(-1);
3545 }
3546 $boolResult = true;
3547 }
3548 return $boolResult;
3549 }
3550
3551 protected static function __ArrayMultiple($arOrder, &$arResult, $arTuple, $arTemp = array())
3552 {
3553 if (empty($arTuple))
3554 {
3555 $arResult[] = array(
3556 'EQUAL' => array_combine($arOrder, $arTemp),
3557 );
3558 }
3559 else
3560 {
3561 $head = array_shift($arTuple);
3562 $arTemp[] = false;
3563 if (is_array($head))
3564 {
3565 if (empty($head))
3566 {
3567 $arTemp[count($arTemp)-1] = -1;
3568 self::__ArrayMultiple($arOrder, $arResult, $arTuple, $arTemp);
3569 }
3570 else
3571 {
3572 foreach ($head as &$value)
3573 {
3574 $arTemp[count($arTemp)-1] = $value;
3575 self::__ArrayMultiple($arOrder, $arResult, $arTuple, $arTemp);
3576 }
3577 if (isset($value))
3578 unset($value);
3579 }
3580 }
3581 else
3582 {
3583 $arTemp[count($arTemp)-1] = $head;
3584 self::__ArrayMultiple($arOrder, $arResult, $arTuple, $arTemp);
3585 }
3586 }
3587 }
3588
3589 protected static function __Unpack($arProduct, $strUnpack)
3590 {
3591 if (empty($strUnpack))
3592 return false;
3593 return eval('return '.$strUnpack.';');
3594 }
3595
3596 protected static function __ConvertOldConditions($strAction, &$arFields)
3597 {
3598 $strAction = mb_strtoupper($strAction);
3599 if (!is_set($arFields, 'CONDITIONS'))
3600 {
3601 $arConditions = array(
3602 'CLASS_ID' => 'CondGroup',
3603 'DATA' => array(
3604 'All' => 'AND',
3605 'True' => 'True',
3606 ),
3607 'CHILDREN' => array(),
3608 );
3609 $intEntityCount = 0;
3610
3611 $arIBlockList = self::__ConvertOldOneEntity($arFields, 'IBLOCK_IDS');
3612 if (!empty($arIBlockList))
3613 {
3614 $intEntityCount++;
3615 }
3616
3617 $arSectionList = self::__ConvertOldOneEntity($arFields, 'SECTION_IDS');
3618 if (!empty($arSectionList))
3619 {
3620 $intEntityCount++;
3621 }
3622
3623 $arElementList = self::__ConvertOldOneEntity($arFields, 'PRODUCT_IDS');
3624 if (!empty($arElementList))
3625 {
3626 $intEntityCount++;
3627 }
3628
3629 if (0 < $intEntityCount)
3630 {
3631 self::__AddOldOneEntity($arConditions, 'CondIBIBlock', $arIBlockList, (1 == $intEntityCount));
3632 self::__AddOldOneEntity($arConditions, 'CondIBSection', $arSectionList, (1 == $intEntityCount));
3633 self::__AddOldOneEntity($arConditions, 'CondIBElement', $arElementList, (1 == $intEntityCount));
3634 }
3635
3636 if ('ADD' == $strAction)
3637 {
3638 $arFields['CONDITIONS'] = $arConditions;
3639 }
3640 else
3641 {
3642 if (0 < $intEntityCount)
3643 {
3644 $arFields['CONDITIONS'] = $arConditions;
3645 }
3646 }
3647 }
3648 }
3649
3650 protected static function __ConvertOldOneEntity(&$arFields, $strEntityID)
3651 {
3652 $arResult = false;
3653 if (!empty($strEntityID))
3654 {
3655 $arResult = array();
3656 if (isset($arFields[$strEntityID]))
3657 {
3658 if (!is_array($arFields[$strEntityID]))
3659 $arFields[$strEntityID] = array($arFields[$strEntityID]);
3660 foreach ($arFields[$strEntityID] as &$value)
3661 {
3662 $value = (int)$value;
3663 if ($value > 0)
3664 $arResult[] = $value;
3665 }
3666 if (isset($value))
3667 unset($value);
3668 if (!empty($arResult))
3669 {
3670 $arResult = array_values(array_unique($arResult));
3671 }
3672 }
3673 }
3674 return $arResult;
3675 }
3676
3677 protected static function __AddOldOneEntity(&$arConditions, $strCondID, $arEntityValues, $boolOneEntity)
3678 {
3679 if (!empty($strCondID))
3680 {
3681 $boolOneEntity = (true == $boolOneEntity ? true : false);
3682 if (!empty($arEntityValues))
3683 {
3684 if (1 < count($arEntityValues))
3685 {
3686 $arList = array();
3687 foreach ($arEntityValues as &$intItemID)
3688 {
3689 $arList[] = array(
3690 'CLASS_ID' => $strCondID,
3691 'DATA' => array(
3692 'logic' => 'Equal',
3693 'value' => $intItemID
3694 ),
3695 );
3696 }
3697 if (isset($intItemID))
3698 unset($intItemID);
3699 if ($boolOneEntity)
3700 {
3701 $arConditions = array(
3702 'CLASS_ID' => 'CondGroup',
3703 'DATA' => array(
3704 'All' => 'OR',
3705 'True' => 'True',
3706 ),
3707 'CHILDREN' => $arList,
3708 );
3709 }
3710 else
3711 {
3712 $arConditions['CHILDREN'][] = array(
3713 'CLASS_ID' => 'CondGroup',
3714 'DATA' => array(
3715 'All' => 'OR',
3716 'True' => 'True',
3717 ),
3718 'CHILDREN' => $arList,
3719 );
3720 }
3721 }
3722 else
3723 {
3724 $arConditions['CHILDREN'][] = array(
3725 'CLASS_ID' => $strCondID,
3726 'DATA' => array(
3727 'logic' => 'Equal',
3728 'value' => current($arEntityValues)
3729 ),
3730 );
3731 }
3732 }
3733 }
3734 }
3735
3736 protected static function __GetConditionValues(&$arFields)
3737 {
3738 $arResult = false;
3739 if (isset($arFields['CONDITIONS']) && !empty($arFields['CONDITIONS']))
3740 {
3741 $arConditions = false;
3742 if (!is_array($arFields['CONDITIONS']))
3743 {
3744 if (CheckSerializedData($arFields['CONDITIONS']))
3745 {
3746 $arConditions = unserialize($arFields['CONDITIONS'], ['allowed_classes' => false]);
3747 }
3748 }
3749 else
3750 {
3751 $arConditions = $arFields['CONDITIONS'];
3752 }
3753
3754 if (is_array($arConditions) && !empty($arConditions))
3755 {
3756 $obCond = new CCatalogCondTree();
3757 $boolCond = $obCond->Init(BT_COND_MODE_SEARCH, BT_COND_BUILD_CATALOG, array());
3758 if ($boolCond)
3759 {
3760 $arResult = $obCond->GetConditionValues($arConditions);
3761 }
3762 }
3763 }
3764 return $arResult;
3765 }
3766
3767 protected static function __GetOldOneEntity(&$arFields, &$arCondList, $strEntityID, $strCondID)
3768 {
3769 if (is_array($arCondList) && !empty($arCondList))
3770 {
3771 $arFields[$strEntityID] = array();
3772 if (isset($arCondList[$strCondID]) && !empty($arCondList[$strCondID]) && is_array($arCondList[$strCondID]))
3773 {
3774 if (isset($arCondList[$strCondID]['VALUES']) && !empty($arCondList[$strCondID]['VALUES']) && is_array($arCondList[$strCondID]['VALUES']))
3775 {
3776 $arCheck = array();
3777 foreach ($arCondList[$strCondID]['VALUES'] as &$intValue)
3778 {
3779 $intValue = (int)$intValue;
3780 if (0 < $intValue)
3781 $arCheck[] = $intValue;
3782 }
3783 if (isset($intValue))
3784 unset($intValue);
3785 $arCheck = array_values(array_unique($arCheck));
3786 $arFields[$strEntityID] = $arCheck;
3787 }
3788 }
3789 }
3790 }
3791
3792 protected static function __UpdateOldOneEntity($intID, &$arFields, $arParams, $boolUpdate)
3793 {
3794 global $DB;
3795
3796 $boolUpdate = (false === $boolUpdate ? false : true);
3797 $intID = (int)$intID;
3798 if ($intID <= 0)
3799 return;
3800 if (!empty($arParams) && is_array($arParams))
3801 {
3802 if (!empty($arParams['ENTITY_ID']) && !empty($arParams['TABLE_ID']) && !empty($arParams['FIELD_ID']))
3803 {
3804 if (isset($arFields[$arParams['ENTITY_ID']]))
3805 {
3806 if ($boolUpdate)
3807 {
3808 $DB->Query("DELETE FROM ".$arParams['TABLE_ID']." WHERE DISCOUNT_ID = ".$intID);
3809 }
3810 if (!empty($arFields[$arParams['ENTITY_ID']]))
3811 {
3812 foreach ($arFields[$arParams['ENTITY_ID']] as &$intValue)
3813 {
3814 $strSql = "INSERT INTO ".$arParams['TABLE_ID']."(DISCOUNT_ID, ".$arParams['FIELD_ID'].") VALUES(".$intID.", ".$intValue.")";
3815 $DB->Query($strSql);
3816 }
3817 if (isset($intValue))
3818 unset($intValue);
3819 }
3820 }
3821 }
3822 }
3823 }
3824
3825 public static function SetDiscountFilterCache($arDiscountIDs, $arCatalogGroups, $arUserGroups)
3826 {
3827 if (!is_array($arDiscountIDs))
3828 return false;
3830
3831 if (!is_array($arCatalogGroups))
3832 return false;
3834 if (empty($arCatalogGroups))
3835 return false;
3836
3837 if (!is_array($arUserGroups))
3838 return false;
3840 if (empty($arUserGroups))
3841 return false;
3842
3843 $strCacheKey = md5('C'.implode('_', $arCatalogGroups).'-'.'U'.implode('_', $arUserGroups));
3844 self::$arCacheDiscountFilter[$strCacheKey] = $arDiscountIDs;
3845
3846 return true;
3847 }
3848
3849 public static function SetAllDiscountFilterCache($arDiscountCache, $boolNeedClear = true)
3850 {
3851 if (empty($arDiscountCache) || !is_array($arDiscountCache))
3852 return false;
3853 $boolNeedClear = !!$boolNeedClear;
3854 foreach ($arDiscountCache as $strCacheKey => $arDiscountIDs)
3855 {
3856 if (!is_array($arDiscountIDs))
3857 continue;
3858 if ($boolNeedClear)
3860 self::$arCacheDiscountFilter[$strCacheKey] = $arDiscountIDs;
3861 }
3862 return true;
3863 }
3864
3865 public static function GetDiscountFilterCache($arCatalogGroups, $arUserGroups)
3866 {
3867 if (!is_array($arCatalogGroups))
3868 return false;
3870 if (empty($arCatalogGroups))
3871 return false;
3872
3873 if (!is_array($arUserGroups))
3874 return false;
3876 if (empty($arUserGroups))
3877 return false;
3878
3879 $strCacheKey = md5('C'.implode('_', $arCatalogGroups).'-'.'U'.implode('_', $arUserGroups));
3880 return (isset(self::$arCacheDiscountFilter[$strCacheKey]) ? self::$arCacheDiscountFilter[$strCacheKey] : false);
3881 }
3882
3883 public static function IsExistsDiscountFilterCache($arCatalogGroups, $arUserGroups)
3884 {
3885 if (!is_array($arCatalogGroups))
3886 return false;
3888 if (empty($arCatalogGroups))
3889 return false;
3890
3891 if (!is_array($arUserGroups))
3892 return false;
3894 if (empty($arUserGroups))
3895 return false;
3896
3897 $strCacheKey = md5('C'.implode('_', $arCatalogGroups).'-'.'U'.implode('_', $arUserGroups));
3898 return isset(self::$arCacheDiscountFilter[$strCacheKey]);
3899 }
3900
3901 public static function GetDiscountFilterCacheByKey($strCacheKey)
3902 {
3903 if (empty($strCacheKey))
3904 return false;
3905 $strCacheKey = md5($strCacheKey);
3906 return (isset(self::$arCacheDiscountFilter[$strCacheKey]) ? self::$arCacheDiscountFilter[$strCacheKey] : false);
3907 }
3908
3909 public static function IsExistsDiscountFilterCacheByKey($strCacheKey)
3910 {
3911 if (empty($strCacheKey))
3912 return false;
3913 $strCacheKey = md5($strCacheKey);
3914 return isset(self::$arCacheDiscountFilter[$strCacheKey]);
3915 }
3916
3917 public static function GetDiscountFilterCacheKey($arCatalogGroups, $arUserGroups, $boolNeedClear = true)
3918 {
3919 $boolNeedClear = !!$boolNeedClear;
3920 if ($boolNeedClear)
3921 {
3922 if (!is_array($arCatalogGroups))
3923 return false;
3925 if (empty($arCatalogGroups))
3926 return false;
3927
3928 if (!is_array($arUserGroups))
3929 return false;
3931 if (empty($arUserGroups))
3932 return false;
3933 }
3934
3935 return md5('C'.implode('_', $arCatalogGroups).'-'.'U'.implode('_', $arUserGroups));
3936 }
3937
3938 public static function SetDiscountResultCache($arDiscountList, $arDiscountIDs, $strSiteID, $strRenewal)
3939 {
3940 if (!is_array($arDiscountList))
3941 return false;
3942 if (!is_array($arDiscountIDs))
3943 return false;
3945 if (empty($arDiscountIDs))
3946 return false;
3947 if ('' == $strSiteID)
3948 return false;
3949 $strRenewal = ('Y' == $strRenewal ? 'Y' : 'N');
3950 $strCacheKey = md5('D'.implode('_', $arDiscountIDs).'-'.'S'.$strSiteID.'-R'.$strRenewal);
3951 self::$arCacheDiscountResult[$strCacheKey] = $arDiscountIDs;
3952
3953 return true;
3954 }
3955
3956 public static function SetAllDiscountResultCache($arDiscountResultCache)
3957 {
3958 if (empty($arDiscountResultCache) || !is_array($arDiscountResultCache))
3959 return false;
3960 foreach ($arDiscountResultCache as $strCacheKey => $arDiscountIDs)
3961 {
3962 self::$arCacheDiscountResult[$strCacheKey] = $arDiscountIDs;
3963 }
3964 return true;
3965
3966 }
3967
3968 public static function GetDiscountResultCacheKey($arDiscountIDs, $strSiteID, $strRenewal, $boolNeedClear = true)
3969 {
3970 $boolNeedClear = !!$boolNeedClear;
3971 if ($boolNeedClear)
3972 {
3973 if (!is_array($arDiscountIDs))
3974 return false;
3976 if (empty($arDiscountIDs))
3977 return false;
3978
3979 if ('' == $strSiteID)
3980 return false;
3981 $strRenewal = ('Y' == $strRenewal ? 'Y' : 'N');
3982 }
3983 return md5('D'.implode('_', $arDiscountIDs).'-'.'S'.$strSiteID.'-R'.$strRenewal);
3984 }
3985
3986 public static function SetDiscountProductCache($arItem, $arParams = array())
3987 {
3988 if (empty($arItem) || !is_array($arItem))
3989 return;
3990
3991 if(self::isUsedSaleDiscountOnly())
3992 {
3993 global $USER;
3995 return;
3996 }
3997
3998 if (!empty($arParams) && isset($arParams['GET_BY_ID']) && $arParams['GET_BY_ID'] == 'Y')
3999 {
4000 $filter = array('ID' => $arItem);
4001 if (isset($arParams['IBLOCK_ID']))
4002 $filter['IBLOCK_ID'] = $arParams['IBLOCK_ID'];
4003
4004 $select = array('ID', 'IBLOCK_ID', 'CODE', 'XML_ID', 'NAME', 'ACTIVE', 'DATE_ACTIVE_FROM', 'DATE_ACTIVE_TO',
4005 'SORT', 'PREVIEW_TEXT', 'DETAIL_TEXT', 'DATE_CREATE', 'DATE_CREATE_UNIX', 'CREATED_BY', 'TIMESTAMP_X', 'TIMESTAMP_X_UNIX',
4006 'MODIFIED_BY', 'TAGS', 'CATALOG_QUANTITY'
4007 );
4008 CTimeZone::Disable();
4009 $rsProducts = CIBlockElement::GetList(array(), $filter, false, false, $select);
4010 CTimeZone::Enable();
4011 while ($arProductFields = $rsProducts->GetNext(false, true))
4012 {
4013 $arProduct = array();
4014
4015 $arProduct['ID'] = (int)$arProductFields['ID'];
4016 $arProduct['IBLOCK_ID'] = (int)$arProductFields['IBLOCK_ID'];
4017
4018 $arProduct['SECTION_ID'] = array();
4019 $arProductSections = self::__GetSectionList($arProduct['IBLOCK_ID'], $arProduct['ID']);
4020 if (false !== $arProductSections)
4021 $arProduct['SECTION_ID'] = $arProductSections;
4022
4023 $arProduct['CODE'] = (string)$arProductFields['~CODE'];
4024 $arProduct['XML_ID'] = (string)$arProductFields['~XML_ID'];
4025 $arProduct['NAME'] = $arProductFields['~NAME'];
4026
4027 $arProduct['ACTIVE'] = $arProductFields['ACTIVE'];
4028
4029 $arProduct['DATE_ACTIVE_FROM'] = (string)$arProductFields['DATE_ACTIVE_FROM'];
4030 if (!empty($arProduct['DATE_ACTIVE_FROM']))
4031 $arProduct['DATE_ACTIVE_FROM'] = (int)MakeTimeStamp($arProduct['DATE_ACTIVE_FROM']);
4032
4033 $arProduct['DATE_ACTIVE_TO'] = (string)$arProductFields['DATE_ACTIVE_TO'];
4034 if (!empty($arProduct['DATE_ACTIVE_TO']))
4035 $arProduct['DATE_ACTIVE_TO'] = (int)MakeTimeStamp($arProduct['DATE_ACTIVE_TO']);
4036
4037 $arProduct['SORT'] = (int)$arProductFields['SORT'];
4038
4039 $arProduct['PREVIEW_TEXT'] = (string)$arProductFields['~PREVIEW_TEXT'];
4040 $arProduct['DETAIL_TEXT'] = (string)$arProductFields['~DETAIL_TEXT'];
4041 $arProduct['TAGS'] = (string)$arProductFields['~TAGS'];
4042
4043 if (isset($arProductFields['DATE_CREATE_UNIX']))
4044 {
4045 $arProduct['DATE_CREATE'] = (string)$arProductFields['DATE_CREATE_UNIX'];
4046 if ('' != $arProduct['DATE_CREATE'])
4047 $arProduct['DATE_CREATE'] = (int)$arProduct['DATE_CREATE'];
4048 }
4049 else
4050 {
4051 $arProduct['DATE_CREATE'] = (string)$arProductFields['DATE_CREATE'];
4052 if ('' != $arProduct['DATE_CREATE'])
4053 $arProduct['DATE_CREATE'] = (int)MakeTimeStamp($arProduct['DATE_CREATE']);
4054 }
4055
4056 if (isset($arProductFields['TIMESTAMP_X_UNIX']))
4057 {
4058 $arProduct['TIMESTAMP_X'] = (string)$arProductFields['TIMESTAMP_X_UNIX'];
4059 if ('' != $arProduct['TIMESTAMP_X'])
4060 $arProduct['TIMESTAMP_X'] = (int)$arProduct['TIMESTAMP_X'];
4061 }
4062 else
4063 {
4064 $arProduct['TIMESTAMP_X'] = (string)$arProductFields['TIMESTAMP_X'];
4065 if ('' != $arProduct['TIMESTAMP_X'])
4066 $arProduct['TIMESTAMP_X'] = (int)MakeTimeStamp($arProduct['TIMESTAMP_X']);
4067 }
4068
4069 $arProduct['CREATED_BY'] = (int)$arProductFields['CREATED_BY'];
4070 $arProduct['MODIFIED_BY'] = (int)$arProductFields['MODIFIED_BY'];
4071
4072 $arProduct['CATALOG_QUANTITY'] = (string)$arProductFields['CATALOG_QUANTITY'];
4073 if ('' != $arProduct['CATALOG_QUANTITY'])
4074 $arProduct['CATALOG_QUANTITY'] = doubleval($arProduct['CATALOG_QUANTITY']);
4075 $arProduct['CATALOG_WEIGHT'] = (string)$arProductFields['CATALOG_WEIGHT'];
4076 if ('' != $arProduct['CATALOG_WEIGHT'])
4077 $arProduct['CATALOG_WEIGHT'] = doubleval($arProduct['CATALOG_WEIGHT']);
4078
4079 $arProduct['CATALOG_VAT_ID'] = (string)$arProductFields['CATALOG_VAT_ID'];
4080 if ('' != $arProduct['CATALOG_VAT_ID'])
4081 $arProduct['CATALOG_VAT_ID'] = (int)$arProduct['CATALOG_VAT_ID'];
4082
4083 $arProduct['CATALOG_VAT_INCLUDED'] = (string)$arProductFields['CATALOG_VAT_INCLUDED'];
4084
4085 if (!isset(self::$arCacheProductProperties[$arProduct['ID']]))
4086 {
4087 $propsList = array(
4088 $arProduct['ID'] => array()
4089 );
4090 CIBlockElement::GetPropertyValuesArray(
4091 $propsList,
4092 $arProduct['IBLOCK_ID'],
4093 array('ID' => $arProduct['ID'], 'IBLOCK_ID' => $arProduct['IBLOCK_ID']),
4094 array(),
4095 array(
4096 'ID' => true,
4097 'PROPERTY_TYPE' => true,
4098 'MULTIPLE' => true,
4099 'USER_TYPE' => true,
4100 )
4101 );
4102 self::$arCacheProductProperties[$arProduct['ID']] = $propsList[$arProduct['ID']];
4103 unset($propsList);
4104 }
4105 $arProps = self::$arCacheProductProperties[$arProduct['ID']];
4106
4107 self::__ConvertProperties($arProduct, $arProps, array('TIME_ZONE' => 'N'));
4108 if (isset(self::$arCacheProductProperties[$arProduct['ID']]))
4109 unset(self::$arCacheProductProperties[$arProduct['ID']]);
4110 if (isset(self::$arCacheProductSections[$arProduct['ID']]))
4111 unset(self::$arCacheProductSections[$arProduct['ID']]);
4112
4113 $sku = CCatalogSku::GetInfoByOfferIBlock($arProduct['IBLOCK_ID']);
4114 if (!empty($sku))
4115 self::__GenerateParent($arProduct, $sku);
4116 self::$arCacheProduct[$arProduct['ID']] = $arProduct;
4117 }
4118 }
4119 else
4120 {
4121 if (!isset(self::$arCacheProduct[$arItem['ID']]))
4122 {
4123 $arParams = array(
4124 'PRODUCT' => 'Y'
4125 );
4126 if (!self::__GenerateFields($arItem, $arParams))
4127 return;
4128
4129 $sku = CCatalogSku::GetInfoByOfferIBlock($arItem['IBLOCK_ID']);
4130 if (!empty($sku))
4131 self::__GenerateParent($arItem, $sku);
4132 self::$arCacheProduct[$arItem['ID']] = $arItem;
4133 }
4134 }
4135 }
4136
4137 public static function getCachedProductData($productId)
4138 {
4139 if(!isset(self::$arCacheProduct[$productId]))
4140 {
4141 return null;
4142 }
4143
4144 return self::$arCacheProduct[$productId];
4145 }
4146
4147 public static function SetProductSectionsCache($arItemIDs)
4148 {
4149 if (empty($arItemIDs) || !is_array($arItemIDs))
4150 return;
4152 if (empty($arItemIDs))
4153 return;
4154
4155 if (empty(self::$arCacheProductSections))
4156 {
4157 self::$arCacheProductSections = array_fill_keys($arItemIDs, array());
4158 }
4159 else
4160 {
4161 foreach ($arItemIDs as $intOneID)
4162 self::$arCacheProductSections[$intOneID] = array();
4163 unset($intOneID);
4164 }
4165
4166 foreach (array_chunk($arItemIDs, 500) as $pageIds)
4167 {
4168 $rsSections = CIBlockElement::GetElementGroups(
4169 $pageIds,
4170 true,
4171 array("ID", "IBLOCK_SECTION_ID", "IBLOCK_ELEMENT_ID")
4172 );
4173 while ($arSection = $rsSections->Fetch())
4174 {
4175 $arSection['ID'] = (int)$arSection['ID'];
4176 $arSection['IBLOCK_SECTION_ID'] = (int)$arSection['IBLOCK_SECTION_ID'];
4177 $arSection['IBLOCK_ELEMENT_ID'] = (int)$arSection['IBLOCK_ELEMENT_ID'];
4178 self::$arCacheProductSections[$arSection['IBLOCK_ELEMENT_ID']][] = $arSection;
4179 }
4180 unset($arSection, $rsSections);
4181 }
4182 unset($pageIds);
4183 }
4184
4185 public static function SetProductPropertiesCache($intProductID, $arProps)
4186 {
4187 $intProductID = (int)$intProductID;
4188 if ($intProductID <= 0)
4189 return;
4190 if (!is_array($arProps))
4191 return;
4192
4193 $whiteList = array(
4194 'ID' => true,
4195 '~ID' => true,
4196 'PROPERTY_TYPE' => true,
4197 '~PROPERTY_TYPE' => true,
4198 'MULTIPLE' => true,
4199 '~MULTIPLE' => true,
4200 'USER_TYPE' => true,
4201 '~USER_TYPE' => true,
4202 'VALUE' => true,
4203 '~VALUE' => true,
4204 'VALUE_ENUM_ID' => true,
4205 '~VALUE_ENUM_ID' => true
4206 );
4207 if (!empty($arProps))
4208 {
4209 foreach (array_keys($arProps) as $index)
4210 {
4211 $arProps[$index] = array_intersect_key($arProps[$index], $whiteList);
4212 if (empty($arProps[$index]))
4213 unset($arProps[$index]);
4214 }
4215 unset($index);
4216 }
4217
4218 if (self::isUsedSaleDiscountOnly())
4220 else
4221 self::$arCacheProductProperties[$intProductID] = $arProps;
4222 }
4223
4224 public static function ClearDiscountCache($arTypes)
4225 {
4226 if (empty($arTypes) || !is_array($arTypes))
4227 return;
4228
4229 if (self::isUsedSaleDiscountOnly())
4230 {
4234 }
4235
4236 if (isset($arTypes['PRODUCT']))
4237 self::$arCacheProduct = array();
4238 if (isset($arTypes['SECTIONS']))
4239 self::$arCacheProductSections = array();
4240 if (isset($arTypes['SECTION_CHAINS']))
4241 self::$arCacheProductSectionChain = array();
4242 if (isset($arTypes['PROPERTIES']))
4243 self::$arCacheProductProperties = array();
4244 }
4245
4246 public static function isUsedSaleDiscountOnly()
4247 {
4248 if (self::$useSaleDiscount === null)
4250
4251 return self::$useSaleDiscount;
4252 }
4253
4254 protected static function primaryDiscountFilter($price, $currency, &$discountList, &$priceDiscountList, &$accumulativeDiscountList)
4255 {
4256 $price = (float)$price;
4258 if ($price <= 0 || $currency === false)
4259 return;
4260
4261 $priceDiscountList = array();
4262 $accumulativeDiscountList = array();
4263 foreach ($discountList as $oneDiscount)
4264 {
4265 $oneDiscount['PRIORITY'] = (int)$oneDiscount['PRIORITY'];
4266 $oneDiscount['VALUE_TYPE'] = (string)$oneDiscount['VALUE_TYPE'];
4267 $oneDiscount['VALUE'] = (float)$oneDiscount['VALUE'];
4268 $oneDiscount['TYPE'] = (int)$oneDiscount['TYPE'];
4269 $changeData = ($oneDiscount['CURRENCY'] != $currency);
4270 switch ($oneDiscount['VALUE_TYPE'])
4271 {
4272 case self::TYPE_FIX:
4273 $discountValue = (
4274 !$changeData
4275 ? $oneDiscount['VALUE']
4277 CCurrencyRates::ConvertCurrency($oneDiscount['VALUE'], $oneDiscount['CURRENCY'], $currency)
4278 )
4279 );
4280 $validDiscount = ($price >= $discountValue);
4281 if ($validDiscount)
4282 {
4283 $oneDiscount['DISCOUNT_CONVERT'] = $discountValue;
4284 if ($changeData)
4285 $oneDiscount['VALUE'] = $oneDiscount['DISCOUNT_CONVERT'];
4286 }
4287 break;
4288 case self::TYPE_SALE:
4289 $discountValue = (
4290 !$changeData
4291 ? $oneDiscount['VALUE']
4293 CCurrencyRates::ConvertCurrency($oneDiscount['VALUE'], $oneDiscount['CURRENCY'], $currency)
4294 )
4295 );
4296 $validDiscount = ($price > $discountValue);
4297 if ($validDiscount)
4298 {
4299 $oneDiscount['DISCOUNT_CONVERT'] = $discountValue;
4300 if ($changeData)
4301 $oneDiscount['VALUE'] = $oneDiscount['DISCOUNT_CONVERT'];
4302 }
4303 break;
4304 case self::TYPE_PERCENT:
4305 $validDiscount = ($oneDiscount['VALUE'] <= 100);
4306 if ($validDiscount)
4307 {
4308 $oneDiscount['MAX_DISCOUNT'] = (float)$oneDiscount['MAX_DISCOUNT'];
4309 if ($oneDiscount['TYPE'] == self::ENTITY_ID && $oneDiscount['MAX_DISCOUNT'] > 0)
4310 {
4311 $oneDiscount['DISCOUNT_CONVERT'] = (
4312 !$changeData
4313 ? $oneDiscount['MAX_DISCOUNT']
4315 CCurrencyRates::ConvertCurrency($oneDiscount['MAX_DISCOUNT'], $oneDiscount['CURRENCY'], $currency)
4316 )
4317 );
4318 if ($changeData)
4319 $oneDiscount['MAX_DISCOUNT'] = $oneDiscount['DISCOUNT_CONVERT'];
4320 }
4321 }
4322 break;
4323 default:
4324 $validDiscount = false;
4325 }
4326 if (!$validDiscount)
4327 continue;
4328 if ($changeData)
4329 $oneDiscount['CURRENCY'] = $currency;
4330 if ($oneDiscount['TYPE'] == CCatalogDiscountSave::ENTITY_ID)
4331 {
4332 $accumulativeDiscountList[] = $oneDiscount;
4333 }
4334 elseif ($oneDiscount['TYPE'] == self::ENTITY_ID)
4335 {
4336 if (!isset($priceDiscountList[$oneDiscount['PRIORITY']]))
4337 $priceDiscountList[$oneDiscount['PRIORITY']] = array();
4338 $priceDiscountList[$oneDiscount['PRIORITY']][] = $oneDiscount;
4339 }
4340 }
4341 unset($oneDiscount);
4342
4343 if (!empty($priceDiscountList))
4344 krsort($priceDiscountList);
4345 }
4346
4347 protected static function calculatePriorityLevel($basePrice, $price, $currency, &$discountList, &$resultDiscount)
4348 {
4349 $basePrice = (float)$basePrice;
4350 $price = (float)$price;
4352 if ($basePrice <= 0 || $price <= 0 || $currency === false)
4353 return false;
4354
4355 if (!is_array($resultDiscount))
4356 $resultDiscount = array();
4357
4358 $currentPrice = $price;
4359 do
4360 {
4361 $minPrice = false;
4362 $minIndex = -1;
4363 foreach ($discountList as $discountIndex => $oneDiscount)
4364 {
4365 $calculatePrice = self::calculatePriceByDiscount($basePrice, $currentPrice, $oneDiscount, $needErase);
4366 if ($needErase)
4367 {
4368 unset($discountList[$discountIndex]);
4369 }
4370 else
4371 {
4372 $apply = ($minPrice === false || $minPrice > $calculatePrice);
4373 if ($apply)
4374 {
4375 $minPrice = $calculatePrice;
4376 $minIndex = $discountIndex;
4377 }
4378 unset($apply);
4379 }
4380 unset($calculatePrice);
4381 }
4382 unset($oneDiscount, $discountIndex);
4383
4384 if ($minPrice !== false)
4385 {
4386 $currentPrice = $minPrice;
4387 $resultDiscount[] = $discountList[$minIndex];
4388 if ($discountList[$minIndex]['LAST_DISCOUNT'] == 'Y')
4389 {
4390 $discountList = array();
4391 }
4392 else
4393 {
4394 unset($discountList[$minIndex]);
4395 }
4396 }
4397 }
4398 while (!empty($discountList));
4399
4400 return $currentPrice;
4401 }
4402
4403 protected static function calculateDiscSave($basePrice, $price, $currency, &$discsaveList, &$resultDiscount)
4404 {
4405 $basePrice = (float)$basePrice;
4406 $price = (float)$price;
4408 if ($basePrice <= 0 || $price <= 0 || $currency === false)
4409 return false;
4410
4411 $currentPrice = $price;
4412 $minPrice = false;
4413 $minIndex = -1;
4414 foreach ($discsaveList as $discountIndex => $oneDiscount)
4415 {
4416 $calculatePrice = false;
4417 switch($oneDiscount['VALUE_TYPE'])
4418 {
4420 $discountValue = Price\Calculation::roundPrecision((
4421 self::$getPercentFromBasePrice
4422 ? $basePrice
4423 : $currentPrice
4424 )*$oneDiscount['VALUE']/100
4425 );
4426 $needErase = ($currentPrice < $discountValue);
4427 if (!$needErase)
4428 $calculatePrice = $currentPrice - $discountValue;
4429 unset($discountValue);
4430 break;
4432 $needErase = ($oneDiscount['DISCOUNT_CONVERT'] > $currentPrice);
4433 if (!$needErase)
4434 $calculatePrice = $currentPrice - $oneDiscount['DISCOUNT_CONVERT'];
4435 break;
4436 default:
4437 $needErase = true;
4438 break;
4439 }
4440 if (!$needErase)
4441 {
4442 $apply = ($minPrice === false || $minPrice > $calculatePrice);
4443 if ($apply)
4444 {
4445 $minPrice = $calculatePrice;
4446 $minIndex = $discountIndex;
4447 }
4448 unset($apply);
4449 }
4450 }
4451 if ($minPrice !== false && isset($discsaveList[$minIndex]))
4452 {
4453 $currentPrice = $minPrice;
4454 $resultDiscount[] = $discsaveList[$minIndex];
4455 }
4456
4457 return $currentPrice;
4458 }
4459
4460 protected static function clearFields($value)
4461 {
4462 return ($value !== null);
4463 }
4464
4465 protected static function initDiscountSettings()
4466 {
4467 $saleInstalled = ModuleManager::isModuleInstalled('sale');
4468 if (self::$useSaleDiscount === null)
4469 self::$useSaleDiscount = $saleInstalled && (string)Option::get('sale', 'use_sale_discount_only') == 'Y';
4470 if (self::$getPercentFromBasePrice === null)
4471 {
4472 $moduleID = ($saleInstalled ? 'sale' : 'catalog');
4473 self::$getPercentFromBasePrice = (string)Option::get($moduleID, 'get_discount_percent_from_base_price') == 'Y';
4474 }
4475 if (self::$existCouponsManager === null)
4476 self::$existCouponsManager = $saleInstalled;
4477 }
4478}
$arParams
Определения access_dialog.php:21
$arTypes
Определения options.php:23
global $APPLICATION
Определения include.php:80
while($arIBlock=$rsIBlocks->Fetch()) $catalogIterator
Определения options.php:1934
$arResult
Определения generate_coupon.php:16
const BT_COND_MODE_GENERATE
Определения catalog_cond.php:20
const BT_COND_MODE_SEARCH
Определения catalog_cond.php:22
const BT_COND_BUILD_CATALOG
Определения catalog_cond.php:24
static getPriceDataByProductId(int $productId, int $catalogGroupId)
Определения discountmanager.php:499
static preloadProductDataToExtendOrder(array $productIds, array $userGroups)
Определения discountmanager.php:626
static setProductPropertiesCache($productId, $props)
Определения discountmanager.php:517
const VALUE_TYPE_PERCENT
Определения discount.php:73
static compare($firstValue, $secondValue, $operator)
Определения calculation.php:161
static roundPrecision($value)
Определения calculation.php:148
static setConfig(array $config)
Определения calculation.php:46
const TYPE_ELEMENT
Определения propertytable.php:68
const TYPE_FILE
Определения propertytable.php:67
const TYPE_LIST
Определения propertytable.php:70
const TYPE_SECTION
Определения propertytable.php:69
static get($moduleId, $name, $default="", $siteId=false)
Определения option.php:30
Определения loader.php:13
static includeModule($moduleName)
Определения loader.php:67
static loadLanguageFile($file, $language=null, $normalize=true)
Определения loc.php:225
static getMessage($code, $replace=null, $language=null)
Определения loc.php:30
static isModuleInstalled($moduleName)
Определения modulemanager.php:125
static getList(array $parameters=array())
Определения datamanager.php:431
static delete($primary)
Определения datamanager.php:1644
static add(array $data)
Определения datamanager.php:877
static update($primary, array $data)
Определения datamanager.php:1256
static normalizeArrayValuesByInt(&$map, $sorted=true)
Определения collection.php:150
static Delete($ID)
Определения admin_notify.php:113
const TYPE_NORMAL
Определения admin_notify.php:7
static Add($arFields)
Определения admin_notify.php:22
static GetList($arSort=[], $arFilter=[])
Определения admin_notify.php:207
static OnSetCouponList($intUserID, $arCoupons, $arModules)
Определения discount_coupon.php:497
static GetCouponsByManage($intUserID)
Определения discount_coupon.php:366
static OnDeleteCouponList($intUserID, $arModules)
Определения discount_coupon.php:636
static EraseCoupon($strCoupon)
Определения discount_coupon.php:241
static ClearCoupon()
Определения discount_coupon.php:283
static SetCoupon($coupon)
Определения discount_coupon.php:161
static EraseCouponByManage($intUserID, $strCoupon)
Определения discount_coupon.php:408
static SetCouponByManage($intUserID, $strCoupon)
Определения discount_coupon.php:311
static ClearCouponsByManage($intUserID)
Определения discount_coupon.php:456
static OnClearCouponList($intUserID, $arCoupons, $arModules)
Определения discount_coupon.php:568
static GetCoupons()
Определения discount_coupon.php:207
Определения discount.php:17
static isUsedSaleDiscountOnly()
Определения discount.php:4246
static SetDiscountProductCache($arItem, $arParams=array())
Определения discount.php:3986
static __Unpack($arProduct, $strUnpack)
Определения discount.php:3589
static initDiscountSettings()
Определения discount.php:4465
static __ConvertOldConditions($strAction, &$arFields)
Определения discount.php:3596
static OnSetCouponList($intUserID, $arCoupons, $arModules)
Определения discount.php:1899
static GetDiscountFilterCacheByKey($strCacheKey)
Определения discount.php:3901
static OnGroupDelete($GroupID)
Определения discount.php:978
static $useSaleDiscount
Определения discount.php:38
static setUseBasePrice($useBasePrice)
Определения discount.php:194
static SetDiscountFilterCache($arDiscountIDs, $arCatalogGroups, $arUserGroups)
Определения discount.php:3825
static SetAllDiscountFilterCache($arDiscountCache, $boolNeedClear=true)
Определения discount.php:3849
static ClearFile($ID, $strDataFileName=false)
Определения discount.php:1005
static primaryDiscountFilter($price, $currency, &$discountList, &$priceDiscountList, &$accumulativeDiscountList)
Определения discount.php:4254
static GetCouponsByManage($intUserID)
Определения discount.php:932
static __GetConditionValues(&$arFields)
Определения discount.php:3736
static GetDiscountByPrice($productPriceID, $arUserGroups=array(), $renewal="N", $siteID=false, $arDiscountCoupons=false)
Определения discount.php:1009
static HaveCoupons($ID, $excludeID=0)
Определения discount.php:1871
const ENTITY_ID
Определения discount.php:22
static calculateDiscSave($basePrice, $price, $currency, &$discsaveList, &$resultDiscount)
Определения discount.php:4403
static OnDeleteCouponList($intUserID, $arModules)
Определения discount.php:1928
static getDiscountDescription(array $discount)
Определения discount.php:2449
static Add($arFields)
Определения discount.php:583
static $arCacheProduct
Определения discount.php:28
static calculateDiscountList($priceData, $currency, &$discountList, $getWithVat=true)
Определения discount.php:2311
static IsExistsDiscountFilterCacheByKey($strCacheKey)
Определения discount.php:3909
static GetDiscountFilterCacheKey($arCatalogGroups, $arUserGroups, $boolNeedClear=true)
Определения discount.php:3917
static SetProductSectionsCache($arItemIDs)
Определения discount.php:4147
static ClearDiscountCache($arTypes)
Определения discount.php:4224
static setSaleDiscountFilter($priceTypesOnly=false)
Определения discount.php:167
static EraseCoupon($strCoupon)
Определения discount.php:893
static SetProductPropertiesCache($intProductID, $arProps)
Определения discount.php:4185
static CheckDiscount($arProduct, $arDiscount)
Определения discount.php:2164
const TYPE_PERCENT
Определения discount.php:18
static $cacheDiscountHandlers
Определения discount.php:34
static getAllUserGroups()
Определения discount.php:2112
static ClearCoupon()
Определения discount.php:905
static __ConvertOldOneEntity(&$arFields, $strEntityID)
Определения discount.php:3650
static getCachedProductData($productId)
Определения discount.php:4137
static OnCurrencyDelete($Currency)
Определения discount.php:965
static __ParseArrays(&$arFields)
Определения discount.php:3455
static CheckFields($ACTION, &$arFields, $ID=0)
Определения discount.php:201
static __ConvertProperties(&$arProduct, &$arProps, $arParams=false)
Определения discount.php:3196
static $arCacheProductSections
Определения discount.php:32
static GenerateDataFile($ID)
Определения discount.php:994
static SetDiscountResultCache($arDiscountList, $arDiscountIDs, $strSiteID, $strRenewal)
Определения discount.php:3938
static SetCoupon($coupon)
Определения discount.php:868
static __GenerateParent(&$product, $sku)
Определения discount.php:3416
static applyDiscountList($price, $currency, &$discountList)
Определения discount.php:2173
static __GetSectionList($intIBlockID, $intProductID)
Определения discount.php:3124
static EraseCouponByManage($intUserID, $strCoupon)
Определения discount.php:946
static $usedModules
Определения discount.php:35
static GetDiscountResultCacheKey($arDiscountIDs, $strSiteID, $strRenewal, $boolNeedClear=true)
Определения discount.php:3968
static __AddOldOneEntity(&$arConditions, $strCondID, $arEntityValues, $boolOneEntity)
Определения discount.php:3677
static $existCouponsManager
Определения discount.php:37
static GetDiscountFilterCache($arCatalogGroups, $arUserGroups)
Определения discount.php:3865
const OLD_FORMAT
Определения discount.php:24
static $getPriceTypesOnly
Определения discount.php:39
static SetCouponByManage($intUserID, $strCoupon)
Определения discount.php:919
static ClearCouponsByManage($intUserID)
Определения discount.php:959
static OnClearCouponList($intUserID, $arCoupons, $arModules)
Определения discount.php:1914
static GetDiscountTypes($boolFull=false)
Определения discount.php:149
static GetDiscountForProduct($arProduct, $arParams=false)
Определения discount.php:1939
static __CheckOneEntity(&$arFields, $strEntityID)
Определения discount.php:3505
static GetDiscountByProduct($productID=0, $arUserGroups=array(), $renewal="N", $arCatalogGroups=array(), $siteID=false, $arDiscountCoupons=false)
Определения discount.php:1053
static $arCacheProductProperties
Определения discount.php:33
static SetAllDiscountResultCache($arDiscountResultCache)
Определения discount.php:3956
static IsExistsDiscountFilterCache($arCatalogGroups, $arUserGroups)
Определения discount.php:3883
static __ArrayMultiple($arOrder, &$arResult, $arTuple, $arTemp=array())
Определения discount.php:3551
static $arCacheProductSectionChain
Определения discount.php:31
static GetCoupons()
Определения discount.php:880
static __GenerateFields(&$arProduct, $arParams=false)
Определения discount.php:2848
static $arCacheDiscountFilter
Определения discount.php:29
static execAgent()
Определения discount.php:89
static $getPercentFromBasePrice
Определения discount.php:40
static getUseBasePrice()
Определения discount.php:181
const TYPE_SALE
Определения discount.php:20
static $arCacheDiscountResult
Определения discount.php:30
static __UpdateOldOneEntity($intID, &$arFields, $arParams, $boolUpdate)
Определения discount.php:3792
const TYPE_FIX
Определения discount.php:19
const CURRENT_FORMAT
Определения discount.php:23
static Update($ID, $arFields)
Определения discount.php:694
static calculatePriorityLevel($basePrice, $price, $currency, &$discountList, &$resultDiscount)
Определения discount.php:4347
static __GetOldOneEntity(&$arFields, &$arCondList, $strEntityID, $strCondID)
Определения discount.php:3767
static clearFields($value)
Определения discount.php:4460
static GetRestrictions($arParams, $boolKeys=true, $boolRevert=true)
Определения discount.php:2128
const APPLY_MODE_REPLACE
Определения discount_save.php:23
const ENTITY_ID
Определения discount_save.php:10
const TYPE_PERCENT
Определения discount_save.php:12
const APPLY_MODE_ADD
Определения discount_save.php:24
static GetDiscount($arParams=array(), $getAll=false)
Определения discount_save.php:443
const TYPE_FIX
Определения discount_save.php:13
const APPLY_MODE_DISABLE
Определения discount_save.php:25
static GetListArray()
Определения cataloggroup.php:291
static IsUserExists()
Определения catalog.php:1812
static checkCurrencyID($currency)
Определения currency.php:714
static ConvertCurrency($valSum, $curFrom, $curTo, $valDate="")
Определения currency_rate.php:393
static GetListEx($arOrder=["ID"=> "DESC"], $arFilter=[], $arGroupBy=false, $arNavStartParams=false, $arSelectFields=[])
Определения group.php:736
static GetPropertyValuesArray(&$result, $iblockID, $filter, $propertyFilter=array(), $options=array())
Определения iblockelement.php:6383
static GetList($arOrder=array(), $arFilter=array(), $arGroupBy=false, $arNavStartParams=false, $arSelectFields=array())
Определения discount_coupon.php:254
static Add($arFields, $bAffectDataFile=true)
Определения discount_coupon.php:11
static _Add(&$arFields)
Определения discount.php:10
static __UpdateSubdiscount($intDiscountID, &$arConditions, $active='')
Определения discount.php:766
static Delete($ID)
Определения discount.php:77
static GetList($arOrder=array(), $arFilter=array(), $arGroupBy=false, $arNavStartParams=false, $arSelectFields=array())
Определения discount.php:190
static getDiscountHandlers($discountList)
Определения discount.php:1057
static _Update($ID, &$arFields)
Определения discount.php:30
static __GetDiscountID($arFilter)
Определения discount.php:834
static __UpdateOldEntities($ID, &$arFields, $boolUpdate)
Определения discount.php:958
static __FillArrays($intDiscountID, &$arFields, $strEntityID)
Определения discount.php:989
static GetGroupsList($arFilter=array())
Определения cataloggroup.php:461
static GetList($arOrder=array(), $arFilter=array(), $arGroupBy=false, $arNavStartParams=false, $arSelectFields=array())
Определения product.php:23
static GetInfoByOfferIBlock($intIBlockID)
Определения catalog_sku.php:111
static getProductList($offerID, $iblockID=0)
Определения catalog_sku.php:694
static GetList($arOrder=array("SORT"=>"ASC"), $arFilter=array(), $arGroupBy=false, $arNavStartParams=false, $arSelectFields=array())
Определения iblockelement.php:658
static GetListEx($arOrder=array(), $arFilter=array(), $arGroupBy=false, $arNavStartParams=false, $arSelectFields=array())
Определения price.php:178
static Disable()
Определения time.php:31
static Enable()
Определения time.php:36
$moduleID
Определения options.php:7
$arValues
Определения component_props.php:25
$arFields
Определения dblapprove.php:5
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$res
Определения filter_act.php:7
$result
Определения get_property_values.php:14
if($ajaxMode) $ID
Определения get_user.php:27
$entity
$iblockId
Определения iblock_catalog_edit.php:30
$defaultValues
Определения iblock_catalog_edit.php:124
$catalog
Определения iblock_catalog_edit.php:135
$select
Определения iblock_catalog_list.php:194
$filter
Определения iblock_catalog_list.php:54
global $DB
Определения cron_frame.php:29
$siteID
Определения cron_frame.php:12
global $USER
Определения csv_new_run.php:40
$ACTION
Определения csv_new_setup.php:27
const FORMAT_DATETIME
Определения include.php:64
const FORMAT_DATE
Определения include.php:63
$groups
Определения options.php:30
$siteId
Определения ajax.php:8
CheckSerializedData($str, $max_depth=200)
Определения tools.php:4949
ExecuteModuleEventEx($arEvent, $arParams=[])
Определения tools.php:5214
GetModuleEvents($MODULE_ID, $MESSAGE_ID, $bReturnArray=false)
Определения tools.php:5177
is_set($a, $k=false)
Определения tools.php:2133
MakeTimeStamp($datetime, $format=false)
Определения tools.php:538
Определения basket.php:2
$order
Определения payment.php:8
return false
Определения prolog_main_admin.php:185
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$config
Определения quickway.php:69
if(empty($signedUserToken)) $key
Определения quickway.php:257
$discount
Определения waybill.php:788
</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
$messages
Определения template.php:8
$currency
Определения template.php:266
$siteList
Определения options.php:47
const SITE_ID
Определения sonet_set_content_view.php:12
$arFilter
Определения user_search.php:106
if(!AccessController::getCurrent() ->check(ActionDictionary::ACTION_CATALOG_EXPORT_EDIT)) if((!isset($_REQUEST['IBLOCK_ID']))||($_REQUEST['IBLOCK_ID']=='')) $intIBlockID
Определения yandex_detail.php:44
$dbRes
Определения yandex_detail.php:168
$iterator
Определения yandex_run.php:610
$fields
Определения yandex_run.php:501