Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
sku.php
1<?php
3
7
14class Sku
15{
16 public const OFFERS_ERROR = 0x0000;
17 public const OFFERS_NOT_EXIST = 0x0001;
18 public const OFFERS_NOT_AVAILABLE = 0x0002;
19 public const OFFERS_AVAILABLE = 0x0004;
20
21 protected const ACTION_AVAILABLE = 'AVAILABLE';
22 protected const ACTION_PRICE = 'PRICE';
23 protected const ACTION_ELEMENT_TIMESTAMP = 'ELEMENT_TIMESTAMP';
24
25 protected static int $allowUpdateAvailable = 0;
26 protected static int $allowPropertyHandler = 0;
27
28 protected static array $productIds = [];
29 protected static array $offers = [];
30 private static array $changeActive = [];
31 private static array $currentActive = [];
32
33 private static ?bool $separateSkuMode = null;
34
35 private static int $deferredCalculation = -1;
36
37 private static bool $calculateAvailable = false;
38 private static array $calculatePriceTypes = [];
39
40 private static array $deferredSku = [];
41 private static array $deferredOffers = [];
42 private static array $deferredUnknown = [];
43
44 private static array $skuExist = [];
45 private static array $skuAvailable = [];
46 private static array $offersIds = [];
47 private static array $offersMap = [];
48 private static array $skuPrices = [];
49
50 private static ?string $queryElementTimestamp = null;
51
57 public static function enableUpdateAvailable()
58 {
59 self::$allowUpdateAvailable++;
60 }
61
67 public static function disableUpdateAvailable()
68 {
69 self::$allowUpdateAvailable--;
70 }
71
77 public static function allowedUpdateAvailable(): bool
78 {
79 return (self::$allowUpdateAvailable >= 0);
80 }
81
87 public static function enableDeferredCalculation()
88 {
89 self::$deferredCalculation++;
90 }
91
97 public static function disableDeferredCalculation()
98 {
99 self::$deferredCalculation--;
100 }
101
107 public static function usedDeferredCalculation(): bool
108 {
109 return (self::$deferredCalculation >= 0);
110 }
111
118 public static function getParentProductFieldsByState(int $offerState): array
119 {
120 return self::getDefaultParentSettings($offerState, true);
121 }
122
130 public static function getDefaultParentSettings(int $state, bool $productIblock = false): array
131 {
132 switch ($state)
133 {
135 $result = [
136 'TYPE' => $productIblock
137 ? Catalog\ProductTable::TYPE_EMPTY_SKU
138 : Catalog\ProductTable::TYPE_PRODUCT
139 ,
140 'AVAILABLE' => Catalog\ProductTable::STATUS_NO,
141 'QUANTITY' => 0,
142 'QUANTITY_TRACE' => Catalog\ProductTable::STATUS_YES,
143 'CAN_BUY_ZERO' => Catalog\ProductTable::STATUS_NO
144 ];
145 break;
147 $result = [
148 'TYPE' => Catalog\ProductTable::TYPE_SKU,
149 'AVAILABLE' => Catalog\ProductTable::STATUS_NO,
150 'QUANTITY' => 0,
151 'QUANTITY_TRACE' => Catalog\ProductTable::STATUS_YES,
152 'CAN_BUY_ZERO' => Catalog\ProductTable::STATUS_NO
153 ];
154 break;
156 $result = [
157 'TYPE' => Catalog\ProductTable::TYPE_SKU,
158 'AVAILABLE' => Catalog\ProductTable::STATUS_YES,
159 'QUANTITY' => 0,
160 'QUANTITY_TRACE' => Catalog\ProductTable::STATUS_NO,
161 'CAN_BUY_ZERO' => Catalog\ProductTable::STATUS_YES,
162 ];
163 break;
164 default:
165 $result = [];
166 break;
167 }
168
169 return $result;
170 }
171
185 public static function updateAvailable($productId, $iblockId = 0, array $productFields = array())
186 {
187 if (!self::allowedUpdateAvailable())
188 return true;
189 static::disableUpdateAvailable();
190
191 $result = true;
192 $process = true;
193 $iblockData = false;
194 $fields = array();
195 $parentId = 0;
196 $parentIblockId = 0;
197
198 $productId = (int)$productId;
199 if ($productId <= 0)
200 {
201 $process = false;
202 $result = false;
203 }
204 if ($process)
205 {
206 $iblockId = (int)$iblockId;
207 if ($iblockId <= 0)
208 $iblockId = (int)\CIBlockElement::GetIBlockByID($productId);
209 if ($iblockId <= 0)
210 {
211 $process = false;
212 $result = false;
213 }
214 }
215
216 if ($process)
217 {
218 $iblockData = \CCatalogSku::GetInfoByIBlock($iblockId);
219 if (empty($iblockData))
220 {
221 $process = false;
222 $result = false;
223 }
224 }
225
226 if ($process)
227 {
228 switch ($iblockData['CATALOG_TYPE'])
229 {
230 case \CCatalogSku::TYPE_PRODUCT:
231 $fields = (self::isSeparateSkuMode()
232 ? static::getParentDataAsProduct($productId, $productFields)
233 : static::getParentProductFieldsByState(static::getOfferState($productId, $iblockId))
234 );
235 break;
236 case \CCatalogSku::TYPE_FULL:
237 $offerState = static::getOfferState($productId, $iblockId);
238 if ($offerState !== self::OFFERS_ERROR)
239 {
240 switch ($offerState)
241 {
244 $fields = (self::isSeparateSkuMode()
245 ? static::getParentDataAsProduct($productId, $productFields)
246 : static::getParentProductFieldsByState($offerState)
247 );
248 break;
250 $product = Catalog\Model\Product::getCacheItem($productId, true);
251 if (!empty($product))
252 {
253 switch ($product['TYPE'])
254 {
255 case Catalog\ProductTable::TYPE_SKU:
256 $fields = static::getDefaultParentSettings($offerState, false);
257 break;
258 case Catalog\ProductTable::TYPE_EMPTY_SKU:
259 $fields = static::getParentProductFieldsByState($offerState);
260 break;
261 case Catalog\ProductTable::TYPE_PRODUCT:
262 case Catalog\ProductTable::TYPE_SET:
263 $fields['AVAILABLE'] = Catalog\ProductTable::calculateAvailable($product);
264 break;
265 default:
266 break;
267 }
268 }
269 unset($product);
270 break;
271 }
272 }
273 break;
274 case \CCatalogSku::TYPE_OFFERS:
275 $parent = \CCatalogSku::getProductList($productId, $iblockId);
276 if (!isset($parent[$productId]))
277 {
278 $fields = [
279 'TYPE' => Catalog\ProductTable::TYPE_FREE_OFFER,
280 ];
281 }
282 else
283 {
284 $fields = [
285 'TYPE' => Catalog\ProductTable::TYPE_OFFER,
286 ];
287 $parentId = $parent[$productId]['ID'];
288 $parentIblockId = $parent[$productId]['IBLOCK_ID'];
289 }
290 $fields = array_merge(
291 self::getProductAvailable($productId, $productFields),
292 $fields
293 );
294 break;
295 case \CCatalogSku::TYPE_CATALOG:
296 $fields = self::getProductAvailable($productId, $productFields);
297 break;
298 }
299 }
300
301 if (
302 $process
303 && !empty($fields)
304 )
305 {
306 $updateResult = Catalog\ProductTable::update($productId, $fields);
307 if (!$updateResult->isSuccess())
308 {
309 $process = false;
310 $result = false;
311 }
312 unset($updateResult);
313 }
314
315 if (
316 $process
317 && $parentId > 0
318 && $parentIblockId > 0
319 )
320 {
321 $result = self::updateParentAvailable($parentId, $parentIblockId);
322 if (!$result)
323 $process = false;
324 }
325 unset($parentIblockId, $parentId, $fields, $iblockData);
326 unset($process);
327 static::enableUpdateAvailable();
328
329 return $result;
330 }
331
341 public static function calculateComplete($id, $iblockId = null, $type = null)
342 {
343 if (!self::allowedUpdateAvailable())
344 return;
345
346 $id = (int)$id;
347 if ($id <= 0)
348 return;
349
350 if (
351 $type == Catalog\ProductTable::TYPE_FREE_OFFER
352 || ($type == Catalog\ProductTable::TYPE_PRODUCT && !self::isSeparateSkuMode())
353 || $type == Catalog\ProductTable::TYPE_SET
354 )
355 return;
356
357 if ($iblockId !== null)
358 {
359 $iblockId = (int)$iblockId;
360 if ($iblockId <= 0)
361 $iblockId = null;
362 }
363
364 switch ($type)
365 {
366 case Catalog\ProductTable::TYPE_SKU:
367 case Catalog\ProductTable::TYPE_EMPTY_SKU:
368 self::setCalculateData(self::$deferredSku, $id, $iblockId);
369 break;
370 case Catalog\ProductTable::TYPE_OFFER:
371 self::setCalculateData(self::$deferredOffers, $id, $iblockId);
372 break;
373 default:
374 if (isset(self::$deferredSku[$id]))
375 self::setCalculateData(self::$deferredSku, $id, $iblockId);
376 elseif (isset(self::$deferredOffers[$id]))
377 self::setCalculateData(self::$deferredOffers, $id, $iblockId);
378 else
379 self::setCalculateData(self::$deferredUnknown, $id, $iblockId);
380 break;
381 }
382 if (!self::usedDeferredCalculation())
384 }
385
396 public static function calculatePrice($id, $iblockId = null, $type = null, array $priceTypes = [])
397 {
398 if (!self::allowedUpdateAvailable())
399 return;
400
401 if (self::isSeparateSkuMode())
402 return;
403
404 $id = (int)$id;
405 if ($id <= 0)
406 return;
407
408 if (
409 $type == Catalog\ProductTable::TYPE_FREE_OFFER
410 || $type == Catalog\ProductTable::TYPE_PRODUCT
411 || $type == Catalog\ProductTable::TYPE_SET
412 )
413 return;
414
415 if ($iblockId !== null)
416 {
417 $iblockId = (int)$iblockId;
418 if ($iblockId <= 0)
419 $iblockId = null;
420 }
421
422 switch ($type)
423 {
424 case Catalog\ProductTable::TYPE_SKU:
425 case Catalog\ProductTable::TYPE_EMPTY_SKU:
426 self::setCalculatePriceTypes(self::$deferredSku, $id, $iblockId, $priceTypes);
427 break;
428 case Catalog\ProductTable::TYPE_OFFER:
429 self::setCalculatePriceTypes(self::$deferredOffers, $id, $iblockId, $priceTypes);
430 break;
431 default:
432 if (isset(self::$deferredSku[$id]))
433 self::setCalculatePriceTypes(self::$deferredSku, $id, $iblockId, $priceTypes);
434 elseif (isset(self::$deferredOffers[$id]))
435 self::setCalculatePriceTypes(self::$deferredOffers, $id, $iblockId, $priceTypes);
436 else
437 self::setCalculatePriceTypes(self::$deferredUnknown, $id, $iblockId, $priceTypes);
438 break;
439 }
440
441 if (!self::usedDeferredCalculation())
443 }
444
450 public static function calculate()
451 {
452 if (!self::allowedUpdateAvailable())
453 return;
454
455 static::disableUpdateAvailable();
456
457 self::updateDeferredSkuList();
458
459 if (!empty(self::$deferredSku))
460 {
461 self::clearStepData();
462
463 self::$calculatePriceTypes = array_keys(self::$calculatePriceTypes);
464 if (!empty(self::$calculatePriceTypes))
465 sort(self::$calculatePriceTypes);
466
467 self::loadProductIblocks();
468
469 $list = array_keys(self::$deferredSku);
470 sort($list);
471
472 foreach (array_chunk($list, 100) as $pageIds)
473 {
474 self::loadProductData($pageIds);
475 self::updateProductData($pageIds);
476 self::updateElements($pageIds);
477 self::updateProductFacetIndex($pageIds);
478 }
479 unset($pageIds, $list);
480
481 self::clearStepData();
482
483 self::$deferredSku = array();
484 }
485
486 self::$calculateAvailable = false;
487 self::$calculatePriceTypes = array();
488
489 static::enableUpdateAvailable();
490 }
491
498 public static function handlerIblockElementAdd($fields)
499 {
500 static::disablePropertyHandler();
501 }
502
510 public static function handlerAfterIblockElementAdd(&$fields)
511 {
512 static::enablePropertyHandler();
513 }
514
523 public static function handlerIblockElementUpdate($newFields, $oldFields)
524 {
525 static::disablePropertyHandler();
526
527 $iblockData = \CCatalogSku::GetInfoByOfferIBlock($newFields['IBLOCK_ID']);
528 if (empty($iblockData))
529 return;
530
531 if (isset($newFields['ACTIVE']) && $newFields['ACTIVE'] != $oldFields['ACTIVE'])
532 self::$changeActive[$newFields['ID']] = $newFields['ACTIVE'];
533 self::$currentActive[$newFields['ID']] = $oldFields['ACTIVE'];
534 }
535
543 public static function handlerAfterIblockElementUpdate(&$fields)
544 {
545 $process = true;
546 $modifyActive = false;
547 $modifyProperty = false;
548 $iblockData = false;
549 $elementId = 0;
550
551 if (!$fields['RESULT'])
552 $process = false;
553 else
554 $elementId = $fields['ID'];
555
556 if ($process)
557 {
558 $modifyActive = isset(self::$changeActive[$elementId]);
559 $modifyProperty = (
560 isset(self::$offers[$elementId])
561 && self::$offers[$elementId]['CURRENT_PRODUCT'] != self::$offers[$elementId]['NEW_PRODUCT']
562 );
563 $process = $modifyActive || $modifyProperty;
564 }
565
566 if ($process)
567 {
568 $iblockData = \CCatalogSku::GetInfoByOfferIBlock($fields['IBLOCK_ID']);
569 $process = !empty($iblockData);
570 }
571
572 if ($process)
573 {
574 if ($modifyActive && !isset(self::$offers[$elementId]))
575 {
576 $parent = \CCatalogSku::getProductList($elementId, $fields['IBLOCK_ID']);
577 if (!empty($parent[$elementId]))
578 self::$offers[$elementId] = array(
579 'CURRENT_PRODUCT' => $parent[$elementId]['ID'],
580 'NEW_PRODUCT' => $parent[$elementId]['ID'],
581 'PRODUCT_IBLOCK_ID' => $parent[$elementId]['IBLOCK_ID']
582 );
583 unset($parent);
584 }
585
586 if (isset(self::$offers[$elementId]))
587 {
588 $offerDescr = self::$offers[$elementId];
589
590 if ($offerDescr['CURRENT_PRODUCT'] > 0)
591 {
592 if ($modifyActive || $modifyProperty)
593 {
595 $offerDescr['CURRENT_PRODUCT'],
596 $iblockData['PRODUCT_IBLOCK_ID'],
598 );
599 }
600 }
601 if ($offerDescr['NEW_PRODUCT'] > 0)
602 {
603 $elementActive = (
604 $modifyActive
605 ? self::$changeActive[$elementId]
606 : self::$currentActive[$elementId]
607 );
608 if ($modifyProperty && $elementActive == 'Y')
609 {
611 $offerDescr['NEW_PRODUCT'],
612 $iblockData['PRODUCT_IBLOCK_ID'],
614 );
615 }
616 }
617
618 if ($offerDescr['CURRENT_PRODUCT'] == 0 || $offerDescr['NEW_PRODUCT'] == 0)
619 {
620 $type = (
621 $offerDescr['NEW_PRODUCT'] > 0
622 ? Catalog\ProductTable::TYPE_OFFER
623 : Catalog\ProductTable::TYPE_FREE_OFFER
624 );
626 $result = Catalog\Model\Product::update($elementId, array('TYPE' => $type));
627 unset($result);
629 unset($type);
630 }
631
632 unset($offerDescr);
633 }
634 else
635 {
637 $result = Catalog\Model\Product::update($elementId, array('TYPE' => Catalog\ProductTable::TYPE_FREE_OFFER));
638 unset($result);
640 }
641 }
642 if (isset(self::$offers[$elementId]))
643 unset(self::$offers[$elementId]);
644 if (isset(self::$currentActive[$elementId]))
645 unset(self::$currentActive[$elementId]);
646 if (isset(self::$changeActive[$elementId]))
647 unset(self::$changeActive[$elementId]);
648 static::enablePropertyHandler();
649 }
650
659 public static function handlerIblockElementDelete($elementId, $elementData)
660 {
661 if ((int)$elementData['WF_PARENT_ELEMENT_ID'] > 0)
662 return;
663
664 $iblockData = \CCatalogSku::GetInfoByOfferIBlock($elementData['IBLOCK_ID']);
665 if (empty($iblockData))
666 return;
667
668 $parent = \CCatalogSku::getProductList($elementId, $elementData['IBLOCK_ID']);
669 if (!empty($parent[$elementId]))
670 self::$offers[$elementId] = array(
671 'CURRENT_PRODUCT' => $parent[$elementId]['ID'],
672 'NEW_PRODUCT' => 0,
673 'PRODUCT_IBLOCK_ID' => $parent[$elementId]['IBLOCK_ID']
674 );
675 unset($parent);
676 }
677
685 public static function handlerAfterIblockElementDelete($elementData)
686 {
687 $elementId = $elementData['ID'];
688 if (!isset(self::$offers[$elementId]))
689 return;
690
692 self::$offers[$elementId]['CURRENT_PRODUCT'],
693 self::$offers[$elementId]['PRODUCT_IBLOCK_ID'],
695 );
696
697 if (isset(self::$offers[$elementId]))
698 unset(self::$offers[$elementId]);
699 }
700
714 $elementId,
715 $iblockId,
716 $newValues,
717 $propertyIdentifyer,
718 $propertyList,
719 $currentValues
720 )
721 {
722 $iblockData = \CCatalogSku::GetInfoByOfferIBlock($iblockId);
723 if (empty($iblockData))
724 return;
725
726 $skuPropertyId = $iblockData['SKU_PROPERTY_ID'];
727 if (!isset($propertyList[$skuPropertyId]))
728 return;
729 $skuPropertyCode = (string)$propertyList[$skuPropertyId]['CODE'];
730 if ($skuPropertyCode === '')
731 $skuPropertyCode = (string)$skuPropertyId;
732
733 $foundValue = false;
734 $skuValue = null;
735 if ($propertyIdentifyer)
736 {
737 if (is_int($propertyIdentifyer))
738 {
739 $propertyId = $propertyIdentifyer;
740 }
741 else
742 {
743 $propertyId = (int)$propertyIdentifyer;
744 if ($propertyId.'' != $propertyIdentifyer)
745 $propertyId = ($skuPropertyCode == $propertyIdentifyer ? $skuPropertyId : 0);
746 }
747 if ($propertyId == $skuPropertyId)
748 {
749 $skuValue = $newValues;
750 $foundValue = true;
751 }
752 unset($propertyId);
753 }
754 else
755 {
756 if (array_key_exists($skuPropertyId, $newValues))
757 {
758 $skuValue = $newValues[$skuPropertyId];
759 $foundValue = true;
760 }
761 elseif (array_key_exists($skuPropertyCode, $newValues))
762 {
763 $skuValue = $newValues[$skuPropertyCode];
764 $foundValue = true;
765 }
766 }
767 if (!$foundValue)
768 return;
769 unset($foundValue);
770
771 $newSkuPropertyValue = 0;
772 if (!empty($skuValue))
773 {
774 if (!is_array($skuValue))
775 {
776 $newSkuPropertyValue = (int)$skuValue;
777 }
778 else
779 {
780 $skuValue = current($skuValue);
781 if (!is_array($skuValue))
782 $newSkuPropertyValue = (int)$skuValue;
783 elseif (!empty($skuValue['VALUE']))
784 $newSkuPropertyValue = (int)$skuValue['VALUE'];
785 }
786 }
787 unset($skuValue);
788 if ($newSkuPropertyValue < 0)
789 $newSkuPropertyValue = 0;
790
791 $currentSkuPropertyValue = 0;
792 if (!empty($currentValues[$skuPropertyId]) && is_array($currentValues[$skuPropertyId]))
793 {
794 $currentSkuProperty = current($currentValues[$skuPropertyId]);
795 if (!empty($currentSkuProperty['VALUE']))
796 $currentSkuPropertyValue = (int)$currentSkuProperty['VALUE'];
797 unset($currentSkuProperty);
798 }
799 if ($currentSkuPropertyValue < 0)
800 $currentSkuPropertyValue = 0;
801
802 // no error - first condition for event OnAfterIblockElementUpdate handler
803 if (!static::allowedPropertyHandler() || ($currentSkuPropertyValue != $newSkuPropertyValue))
804 {
805 self::$offers[$elementId] = array(
806 'CURRENT_PRODUCT' => $currentSkuPropertyValue,
807 'NEW_PRODUCT' => $newSkuPropertyValue,
808 'PRODUCT_IBLOCK_ID' => $iblockData['PRODUCT_IBLOCK_ID']
809 );
810 }
811 }
812
824 $elementId,
825 $iblockId,
826 $newValues,
827 $propertyIdentifyer
828 )
829 {
830 if (!static::allowedPropertyHandler())
831 return;
832
833 self::calculateOfferChange((int)$elementId, (int)$iblockId);
834 }
835
848 $elementId,
849 $iblockId,
850 $newValues,
851 $propertyList,
852 $currentValues
853 )
854 {
855 $iblockData = \CCatalogSku::GetInfoByOfferIBlock($iblockId);
856 if (empty($iblockData))
857 return;
858
859 $skuPropertyId = $iblockData['SKU_PROPERTY_ID'];
860 if (!isset($propertyList[$skuPropertyId]))
861 return;
862 $skuPropertyCode = (string)$propertyList[$skuPropertyId]['CODE'];
863 if ($skuPropertyCode === '')
864 $skuPropertyCode = (string)$skuPropertyId;
865
866 $foundValue = false;
867 $skuValue = null;
868 if (array_key_exists($skuPropertyId, $newValues))
869 {
870 $skuValue = $newValues[$skuPropertyId];
871 $foundValue = true;
872 }
873 elseif (array_key_exists($skuPropertyCode, $newValues))
874 {
875 $skuValue = $newValues[$skuPropertyCode];
876 $foundValue = true;
877 }
878 if (!$foundValue)
879 return;
880 unset($foundValue);
881
882 $newSkuPropertyValue = 0;
883 if (!empty($skuValue))
884 {
885 if (!is_array($skuValue))
886 {
887 $newSkuPropertyValue = (int)$skuValue;
888 }
889 else
890 {
891 if (array_key_exists('VALUE', $skuValue))
892 {
893 $newSkuPropertyValue = (int)$skuValue['VALUE'];
894 }
895 else
896 {
897 foreach($skuValue as $row)
898 {
899 if (!is_array($row))
900 $newSkuPropertyValue = (int)$row;
901 elseif (array_key_exists('VALUE', $row))
902 $newSkuPropertyValue = (int)$row['VALUE'];
903 }
904 unset($row);
905 }
906 }
907 }
908 unset($skuValue);
909 if ($newSkuPropertyValue < 0)
910 $newSkuPropertyValue = 0;
911
912 $currentSkuPropertyValue = 0;
913 if (!empty($currentValues[$skuPropertyId]) && is_array($currentValues[$skuPropertyId]))
914 {
915 $currentSkuProperty = current($currentValues[$skuPropertyId]);
916 if (!empty($currentSkuProperty['VALUE']))
917 $currentSkuPropertyValue = (int)$currentSkuProperty['VALUE'];
918 unset($currentSkuProperty);
919 }
920 if ($currentSkuPropertyValue < 0)
921 $currentSkuPropertyValue = 0;
922
923 if (!static::allowedPropertyHandler() || ($currentSkuPropertyValue != $newSkuPropertyValue))
924 {
925 self::$offers[$elementId] = [
926 'CURRENT_PRODUCT' => $currentSkuPropertyValue,
927 'NEW_PRODUCT' => $newSkuPropertyValue,
928 'PRODUCT_IBLOCK_ID' => $iblockData['PRODUCT_IBLOCK_ID']
929 ];
930 }
931 }
932
944 $elementId,
945 $iblockId,
946 $newValues,
947 $flags
948 )
949 {
950 self::calculateOfferChange((int)$elementId, (int)$iblockId);
951 }
952
963 public static function getOfferState($productId, $iblockId = 0)
964 {
965 $result = self::OFFERS_ERROR;
966 $productId = (int)$productId;
967 if ($productId <= 0)
968 return $result;
969 $iblockId = (int)$iblockId;
970 if ($iblockId <= 0)
971 $iblockId = (int)\CIBlockElement::GetIBlockByID($productId);
972 if ($iblockId <= 0)
973 return $result;
974
975 $result = self::OFFERS_NOT_EXIST;
976 $offerList = \CCatalogSku::getOffersList($productId, $iblockId, array(), array('ID', 'ACTIVE'));
977 if (!empty($offerList[$productId]))
978 {
980 $activeOffers = array_filter($offerList[$productId], '\Bitrix\Catalog\Product\Sku::filterActive');
981 if (!empty($activeOffers))
982 {
983 $existOffers = Catalog\ProductTable::getList(array(
984 'select' => array('ID', 'AVAILABLE'),
985 'filter' => array('@ID' => array_keys($activeOffers), '=AVAILABLE' => Catalog\ProductTable::STATUS_YES),
986 'limit' => 1
987 ))->fetch();
988 if (!empty($existOffers))
989 $result = self::OFFERS_AVAILABLE;
990 unset($existOffers);
991 }
992 unset($activeOffers);
993 }
994 unset($offerList);
995
996 return $result;
997 }
998
1009 protected static function updateProductAvailable($productId, $iblockId)
1010 {
1011 $productId = (int)$productId;
1012 if ($productId <= 0)
1013 return false;
1014
1015 self::calculateComplete($productId, $iblockId, Catalog\ProductTable::TYPE_SKU);
1016
1017 return true;
1018 }
1019
1032 protected static function updateOfferType($offerId, $type)
1033 {
1034 $offerId = (int)$offerId;
1035 $type = (int)$type;
1036 if ($offerId <= 0 || ($type != Catalog\ProductTable::TYPE_OFFER && $type != Catalog\ProductTable::TYPE_FREE_OFFER))
1037 return false;
1038 static::disableUpdateAvailable();
1039 $updateResult = Catalog\Model\Product::update($offerId, array('TYPE' => $type));
1040 $result = $updateResult->isSuccess();
1041 static::enableUpdateAvailable();
1042 return $result;
1043 }
1044
1050 protected static function enablePropertyHandler()
1051 {
1052 self::$allowPropertyHandler++;
1053 }
1054
1060 protected static function disablePropertyHandler()
1061 {
1062 self::$allowPropertyHandler--;
1063 }
1064
1070 protected static function allowedPropertyHandler(): bool
1071 {
1072 return (self::$allowPropertyHandler >= 0);
1073 }
1074
1082 protected static function filterActive(array $row): bool
1083 {
1084 return (isset($row['ACTIVE']) && $row['ACTIVE'] == 'Y');
1085 }
1086
1093 private static function isSeparateSkuMode(): bool
1094 {
1095 if (self::$separateSkuMode === null)
1096 {
1097 self::$separateSkuMode = Main\Config\Option::get('catalog', 'show_catalog_tab_with_offers') === 'Y';
1098 }
1099
1100 return self::$separateSkuMode;
1101 }
1102
1112 private static function getParentDataAsProduct($productId, array $productFields = array())
1113 {
1114 if (!isset($productFields['QUANTITY'])
1115 || !isset($productFields['QUANTITY_TRACE'])
1116 || !isset($productFields['CAN_BUY_ZERO'])
1117 )
1118 $productFields = array_merge(Catalog\Model\Product::getCacheItem($productId, true), $productFields);
1119
1120 return array(
1121 'TYPE' => Catalog\ProductTable::TYPE_SKU,
1122 'AVAILABLE' => Catalog\ProductTable::calculateAvailable($productFields)
1123 );
1124 }
1125
1135 private static function getProductAvailable($productId, array $productFields)
1136 {
1137 $fields = array();
1138
1139 if (isset($productFields['AVAILABLE']))
1140 return $fields;
1141
1142 if (
1143 isset($productFields['QUANTITY'])
1144 || isset($productFields['QUANTITY_TRACE'])
1145 || isset($productFields['CAN_BUY_ZERO'])
1146 )
1147 {
1148 if (
1149 !isset($productFields['QUANTITY'])
1150 || !isset($productFields['QUANTITY_TRACE'])
1151 || !isset($productFields['CAN_BUY_ZERO'])
1152 )
1153 $productFields = array_merge(Catalog\Model\Product::getCacheItem($productId, true), $productFields);
1154 $fields['AVAILABLE'] = Catalog\ProductTable::calculateAvailable($productFields);
1155 }
1156
1157 return $fields;
1158 }
1159
1169 private static function updateParentAvailable(int $parentId, int $parentIblockId): bool
1170 {
1171 $parentIBlock = \CCatalogSku::GetInfoByIblock($parentIblockId);
1172 if (
1173 empty($parentIBlock)
1174 || (self::isSeparateSkuMode() && $parentIBlock['CATALOG_TYPE'] === \CCatalogSku::TYPE_FULL)
1175 )
1176 {
1177 return true;
1178 }
1179
1180 $parentFields = static::getDefaultParentSettings(static::getOfferState(
1181 $parentId,
1182 $parentIblockId
1183 ));
1184
1186 $iterator = Catalog\Model\Product::getList([
1187 'select' => [
1188 'ID',
1189 ],
1190 'filter' => [
1191 '=ID' => $parentId,
1192 ],
1193 ]);
1194 $row = $iterator->fetch();
1195 if (!empty($row))
1196 {
1197 $updateResult = Catalog\Model\Product::update($parentId, $parentFields);
1198 }
1199 else
1200 {
1201 $parentFields['ID'] = $parentId;
1202 $updateResult = Catalog\Model\Product::add($parentFields);
1203 }
1204
1205 $result = $updateResult->isSuccess();
1206 unset($updateResult);
1207
1209
1210 return $result;
1211 }
1212
1221 private static function updateDeferredSkuList()
1222 {
1223 if (!empty(self::$deferredUnknown))
1224 {
1225 $list = array_keys(self::$deferredUnknown);
1226 sort($list);
1227 foreach (array_chunk($list, 500) as $pageIds)
1228 {
1229 $iterator = Catalog\ProductTable::getList(array(
1230 'select' => array('ID', 'TYPE'),
1231 'filter' => array(
1232 '@ID' => $pageIds,
1233 '@TYPE' => array(Catalog\ProductTable::TYPE_SKU, Catalog\ProductTable::TYPE_OFFER)
1234 )
1235 ));
1236 while ($row = $iterator->fetch())
1237 {
1238 $row['ID'] = (int)$row['ID'];
1239 if ($row['TYPE'] == Catalog\ProductTable::TYPE_SKU)
1240 self::migrateCalculateData(self::$deferredUnknown, self::$deferredSku, $row['ID']);
1241 else
1242 self::migrateCalculateData(self::$deferredUnknown, self::$deferredOffers, $row['ID']);
1243 }
1244 }
1245 unset($row, $iterator, $pageIds, $list);
1246
1247 self::$deferredUnknown = array();
1248 }
1249 if (!empty(self::$deferredOffers))
1250 {
1251 $productList = \CCatalogSku::getProductList(array_keys(self::$deferredOffers));
1252 if (!empty($productList))
1253 {
1254 foreach ($productList as $id => $row)
1255 self::transferCalculationData(self::$deferredOffers, self::$deferredSku, $id, $row['ID'], $row['IBLOCK_ID']);
1256 unset($id, $row);
1257 }
1258 unset($productList);
1259
1260 self::$deferredOffers = array();
1261 }
1262 }
1263
1274 private static function setCalculateData(array &$list, $id, $iblockId)
1275 {
1276 static $priceTypes = null,
1277 $priceTypeKeys;
1278
1279 self::$calculateAvailable = true;
1280
1281 if ($priceTypes === null)
1282 {
1283 $priceTypes = array_keys(Catalog\GroupTable::getTypeList());
1284 $priceTypeKeys = array_fill_keys($priceTypes, true);
1285 }
1286 self::$calculatePriceTypes = $priceTypeKeys;
1287
1288 if ($iblockId === null)
1289 {
1290 if (isset($list[$id]))
1291 {
1292 $iblockId = $list[$id]['IBLOCK_ID'];
1293 }
1294 }
1295
1296 $list[$id] = [
1297 'IBLOCK_ID' => $iblockId,
1298 self::ACTION_AVAILABLE => true,
1299 self::ACTION_PRICE => self::$calculatePriceTypes,
1300 self::ACTION_ELEMENT_TIMESTAMP => true,
1301 ];
1302 }
1303
1315 private static function setCalculatePriceTypes(array &$list, $id, $iblockId, array $priceTypes)
1316 {
1317 static $allPriceTypes = null;
1318
1319 if ($allPriceTypes === null)
1320 {
1321 $allPriceTypes = array_keys(Catalog\GroupTable::getTypeList());
1322 }
1323
1324 if (empty($priceTypes))
1325 {
1326 $priceTypes = $allPriceTypes;
1327 }
1328
1329 foreach ($priceTypes as $typeId)
1330 {
1331 self::$calculatePriceTypes[$typeId] = true;
1332 }
1333
1334 if ($iblockId === null)
1335 {
1336 if (isset($list[$id]))
1337 {
1338 $iblockId = $list[$id]['IBLOCK_ID'];
1339 }
1340 }
1341
1342 if (!isset($list[$id]))
1343 {
1344 $list[$id] = [
1345 'IBLOCK_ID' => $iblockId,
1346 self::ACTION_PRICE => array_fill_keys($priceTypes, true),
1347 self::ACTION_ELEMENT_TIMESTAMP => true,
1348 ];
1349 }
1350 elseif (!isset($list[$id][self::ACTION_PRICE]))
1351 {
1352 if ($iblockId !== null)
1353 {
1354 $list[$id]['IBLOCK_ID'] = $iblockId;
1355 }
1356 $list[$id][self::ACTION_PRICE] = array_fill_keys($priceTypes, true);
1357 $list[$id][self::ACTION_ELEMENT_TIMESTAMP] = true;
1358 }
1359 else
1360 {
1361 if ($iblockId !== null)
1362 {
1363 $list[$id]['IBLOCK_ID'] = $iblockId;
1364 }
1365 foreach ($priceTypes as $typeId)
1366 {
1367 $list[$id][self::ACTION_PRICE][$typeId] = true;
1368 }
1369 $list[$id][self::ACTION_ELEMENT_TIMESTAMP] = true;
1370 }
1371
1372 unset($typeId);
1373 }
1374
1385 private static function migrateCalculateData(array &$source, array &$destination, $id)
1386 {
1387 if (!isset($source[$id]))
1388 return;
1389
1390 if (isset($destination[$id]))
1391 {
1392 if (isset($source[$id][self::ACTION_AVAILABLE]))
1393 self::setCalculateData($destination, $id, $source[$id]['IBLOCK_ID']);
1394 elseif (isset($source[$id][self::ACTION_PRICE]))
1395 self::setCalculatePriceTypes($destination, $id, $source[$id]['IBLOCK_ID'], array_keys($source[$id][self::ACTION_PRICE]));
1396 }
1397 else
1398 {
1399 $destination[$id] = $source[$id];
1400 }
1401 unset($source[$id]);
1402 }
1403
1416 private static function transferCalculationData(array &$source, array &$destination, $sourceId, $destinationId, $iblockId)
1417 {
1418 if (!isset($source[$sourceId]))
1419 return;
1420
1421 if (isset($destination[$destinationId]))
1422 {
1423 if (isset($source[$sourceId][self::ACTION_AVAILABLE]))
1424 self::setCalculateData($destination, $destinationId, $iblockId);
1425 elseif (isset($source[$sourceId][self::ACTION_PRICE]))
1426 self::setCalculatePriceTypes($destination, $destinationId, $iblockId, array_keys($source[$sourceId][self::ACTION_PRICE]));
1427 }
1428 else
1429 {
1430 $destination[$destinationId] = $source[$sourceId];
1431 $destination[$destinationId]['IBLOCK_ID'] = $iblockId;
1432 }
1433 unset($source[$sourceId]);
1434 }
1435
1442 private static function clearStepData()
1443 {
1444 self::$skuExist = array();
1445 self::$skuAvailable = array();
1446 self::$offersIds = array();
1447 self::$offersMap = array();
1448 self::$skuPrices = array();
1449 }
1450
1457 private static function loadProductIblocks()
1458 {
1459 $listIds = array();
1460 foreach (array_keys(self::$deferredSku) as $id)
1461 {
1462 if (self::$deferredSku[$id]['IBLOCK_ID'] === null)
1463 $listIds[] = $id;
1464 }
1465 unset($id);
1466 if (!empty($listIds))
1467 {
1468 $data = \CIBlockElement::GetIBlockByIDList($listIds);
1469 foreach ($data as $id => $iblockId)
1470 {
1471 self::$deferredSku[$id]['IBLOCK_ID'] = $iblockId;
1472 }
1473 unset($id, $iblockId);
1474 }
1475 unset($listIds);
1476 }
1477
1486 private static function loadProductData(array $listIds)
1487 {
1488 $iterator = Catalog\Model\Product::getList(array(
1489 'select' => array('ID'),
1490 'filter' => array('@ID' => $listIds)
1491 ));
1492 while ($row = $iterator->fetch())
1493 {
1494 $row['ID'] = (int)$row['ID'];
1495 self::$skuExist[$row['ID']] = true;
1496 }
1497 unset($row, $iterator);
1498 $offers = \CCatalogSku::getOffersList(
1499 $listIds,
1500 0,
1501 array(),
1502 array('ID', 'ACTIVE', 'AVAILABLE')
1503 );
1504 foreach ($listIds as $id)
1505 {
1506 self::$skuAvailable[$id] = self::OFFERS_NOT_EXIST;
1507 if (empty($offers[$id]))
1508 continue;
1509
1510 self::$skuAvailable[$id] = self::OFFERS_NOT_AVAILABLE;
1511 $allOffers = array();
1512 $availableOffers = array();
1513 foreach ($offers[$id] as $offerId => $row)
1514 {
1515 $allOffers[] = $offerId;
1516 if ($row['ACTIVE'] != 'Y' || $row['AVAILABLE'] != 'Y')
1517 continue;
1518 self::$skuAvailable[$id] = self::OFFERS_AVAILABLE;
1519 $availableOffers[] = $offerId;
1520 }
1521 self::$skuPrices[$id] = array();
1522 if (self::$skuAvailable[$id] == self::OFFERS_AVAILABLE)
1523 {
1524 foreach ($availableOffers as $offerId)
1525 {
1526 self::$offersMap[$offerId] = $id;
1527 self::$offersIds[] = $offerId;
1528 }
1529 }
1530 else
1531 {
1532 foreach ($allOffers as $offerId)
1533 {
1534 self::$offersMap[$offerId] = $id;
1535 self::$offersIds[] = $offerId;
1536 }
1537 }
1538 }
1539 unset($offerId, $availableOffers, $allOffers, $id);
1540
1541 if (!self::isSeparateSkuMode())
1542 self::loadProductPrices();
1543 }
1544
1553 private static function updateProductData(array $listIds): void
1554 {
1555 $separateMode = self::isSeparateSkuMode();
1556 if (self::$calculateAvailable)
1557 {
1558 $iblockData = false;
1559 $iblockId = null;
1560 foreach ($listIds as $id)
1561 {
1562 if (empty(self::$deferredSku[$id][self::ACTION_AVAILABLE]))
1563 continue;
1564 if (empty(self::$deferredSku[$id]['IBLOCK_ID']))
1565 continue;
1566 if (!isset(self::$skuAvailable[$id]))
1567 continue;
1568
1569 if ($iblockId !== self::$deferredSku[$id]['IBLOCK_ID'])
1570 {
1571 $iblockId = self::$deferredSku[$id]['IBLOCK_ID'];
1572 $iblockData = \CCatalogSku::GetInfoByIBlock(self::$deferredSku[$id]['IBLOCK_ID']);
1573 }
1574 if (empty($iblockData))
1575 {
1576 continue;
1577 }
1578
1580 self::$skuAvailable[$id],
1581 $iblockData['CATALOG_TYPE'] == \CCatalogSku::TYPE_PRODUCT
1582 );
1583 if (empty($fields))
1584 {
1585 continue;
1586 }
1587
1588 // for separate only
1589 if ($separateMode)
1590 {
1591 $fields = [
1592 'TYPE' => $fields['TYPE'],
1593 ];
1594 }
1595
1596 if (isset(self::$skuExist[$id]))
1597 {
1598 $result = Catalog\Model\Product::update($id, $fields);
1599 unset(self::$skuExist[$id]);
1600 }
1601 else
1602 {
1603 $fields['ID'] = $id;
1604 $result = Catalog\Model\Product::add($fields);
1605 }
1606 }
1607 unset($result, $id);
1608 }
1609
1610 if (!$separateMode)
1611 {
1612 self::updateProductPrices($listIds);
1613 }
1614 }
1615
1624 private static function loadProductPrices()
1625 {
1626 if (empty(self::$calculatePriceTypes) || empty(self::$offersIds))
1627 return;
1628
1629 sort(self::$offersIds);
1630 foreach (array_chunk(self::$offersIds, 500) as $pageOfferIds)
1631 {
1632 $filter = Main\Entity\Query::filter();
1633 $filter->whereIn('PRODUCT_ID', $pageOfferIds);
1634 $filter->whereIn('CATALOG_GROUP_ID', self::$calculatePriceTypes);
1635 $filter->where(Main\Entity\Query::filter()->logic('or')->where('QUANTITY_FROM', '<=', 1)->whereNull('QUANTITY_FROM'));
1636 $filter->where(Main\Entity\Query::filter()->logic('or')->where('QUANTITY_TO', '>=', 1)->whereNull('QUANTITY_TO'));
1637
1638 $iterator = Catalog\PriceTable::getList(array(
1639 'select' => array(
1640 'PRODUCT_ID', 'CATALOG_GROUP_ID', 'PRICE', 'CURRENCY',
1641 'PRICE_SCALE', 'TMP_ID' //TODO: add MEASURE_RATIO_ID
1642 ),
1643 'filter' => $filter,
1644 'order' => array('PRODUCT_ID' => 'ASC', 'CATALOG_GROUP_ID' => 'ASC')
1645 ));
1646 while ($row = $iterator->fetch())
1647 {
1648 /*
1649 if ($row['MEASURE_RATIO_ID'] !== null)
1650 continue;
1651 unset($row['MEASURE_RATIO_ID']);
1652 */
1653
1654 $typeId = (int)$row['CATALOG_GROUP_ID'];
1655 $offerId = (int)$row['PRODUCT_ID'];
1656 $productId = self::$offersMap[$offerId];
1657 if (!isset(self::$deferredSku[$productId][self::ACTION_PRICE][$typeId]))
1658 continue;
1659 unset($row['PRODUCT_ID']);
1660
1661 if (!isset(self::$skuPrices[$productId][$typeId]))
1662 self::$skuPrices[$productId][$typeId] = $row;
1663 elseif (self::$skuPrices[$productId][$typeId]['PRICE_SCALE'] > $row['PRICE_SCALE'])
1664 self::$skuPrices[$productId][$typeId] = $row;
1665 }
1666 unset($row, $iterator);
1667 unset($filter);
1668 }
1669 }
1670
1683 private static function updateProductPrices(array $listIds)
1684 {
1685 if (empty(self::$calculatePriceTypes))
1686 return;
1687
1688 $process = true;
1689
1690 if (!empty(self::$skuPrices))
1691 {
1692 $existIds = array();
1693 $existIdsByType = array();
1694 $iterator = Catalog\PriceTable::getList(array(
1695 'select' => array('ID', 'CATALOG_GROUP_ID', 'PRODUCT_ID'),
1696 'filter' => array('@PRODUCT_ID' => $listIds, '@CATALOG_GROUP_ID' => self::$calculatePriceTypes),
1697 'order' => array('ID' => 'ASC')
1698 ));
1699 while ($row = $iterator->fetch())
1700 {
1701 $row['ID'] = (int)$row['ID'];
1702 $priceTypeId = (int)$row['CATALOG_GROUP_ID'];
1703 $productId = (int)$row['PRODUCT_ID'];
1704 $existIds[$row['ID']] = $row['ID'];
1705 if (!isset($existIdsByType[$productId]))
1706 $existIdsByType[$productId] = array();
1707 if (!isset($existIdsByType[$productId][$priceTypeId]))
1708 $existIdsByType[$productId][$priceTypeId] = array();
1709 $existIdsByType[$productId][$priceTypeId][] = $row['ID'];
1710 }
1711 unset($row, $iterator);
1712 foreach ($listIds as $productId)
1713 {
1714 if (!isset(self::$skuPrices[$productId]))
1715 continue;
1716
1717 foreach (array_keys(self::$skuPrices[$productId]) as $resultPriceType)
1718 {
1719 $rowId = null;
1720 $row = self::$skuPrices[$productId][$resultPriceType];
1721 if (!empty($existIdsByType[$productId][$resultPriceType]))
1722 {
1723 $rowId = array_shift($existIdsByType[$productId][$resultPriceType]);
1724 unset($existIds[$rowId]);
1725 }
1726 if ($rowId === null)
1727 {
1728 $row['PRODUCT_ID'] = $productId;
1729 $row['CATALOG_GROUP_ID'] = $resultPriceType;
1730 $rowResult = Catalog\PriceTable::add($row);
1731 }
1732 else
1733 {
1734 $rowResult = Catalog\PriceTable::update($rowId, $row);
1735 }
1736 if (!$rowResult->isSuccess())
1737 {
1738 $process = false;
1739 break;
1740 }
1741 }
1742 }
1743 unset($row, $rowResult, $resultPriceType);
1744
1745 unset($existIdsByType);
1746
1747 if ($process)
1748 {
1749 if (!empty($existIds))
1750 {
1751 $conn = Main\Application::getConnection();
1752 $helper = $conn->getSqlHelper();
1753 $tableName = $helper->quote(Catalog\PriceTable::getTableName());
1754 foreach (array_chunk($existIds, 500) as $pageIds)
1755 {
1756 $conn->queryExecute(
1757 'delete from '.$tableName.' where '.$helper->quote('ID').' in ('.implode(',', $pageIds).')'
1758 );
1759 }
1760 unset($pageIds);
1761 unset($helper, $conn);
1762 }
1763 unset($existIds);
1764 }
1765 }
1766 else
1767 {
1768 $conn = Main\Application::getConnection();
1769 $helper = $conn->getSqlHelper();
1770 $conn->queryExecute(
1771 'delete from '.$helper->quote(Catalog\PriceTable::getTableName()).
1772 ' where '.$helper->quote('PRODUCT_ID').' in ('.implode(',', $listIds).')'.
1773 ' and '.$helper->quote('CATALOG_GROUP_ID').' in ('.implode(',', self::$calculatePriceTypes).')'
1774 );
1775 unset($helper, $conn);
1776 }
1777 }
1778
1779 private static function updateElements(array $listIds): void
1780 {
1781 if (self::isSeparateSkuMode())
1782 {
1783 return;
1784 }
1785 $conn = \Bitrix\Main\Application::getConnection();
1786 if (self::$queryElementTimestamp === null)
1787 {
1788 $helper = $conn->getSqlHelper();
1789 self::$queryElementTimestamp = 'update ' . $helper->quote(\Bitrix\Iblock\ElementTable::getTableName())
1790 . ' set ' . $helper->quote('TIMESTAMP_X') . ' = ' . $helper->getCurrentDateTimeFunction()
1791 . ' where ' . $helper->quote('ID') . '=';
1792 }
1793 foreach ($listIds as $id)
1794 {
1795 if (empty(self::$deferredSku[$id][self::ACTION_ELEMENT_TIMESTAMP]))
1796 continue;
1797 $conn->queryExecute(self::$queryElementTimestamp . $id);
1798 }
1799 }
1800
1809 private static function updateProductFacetIndex(array $listIds): void
1810 {
1811 foreach ($listIds as $id)
1812 {
1813 if (empty(self::$deferredSku[$id]['IBLOCK_ID']))
1814 continue;
1815 if (!isset(self::$skuAvailable[$id]))
1816 continue;
1817 Iblock\PropertyIndex\Manager::updateElementIndex(
1818 self::$deferredSku[$id]['IBLOCK_ID'],
1819 $id
1820 );
1821 }
1822 }
1823
1832 private static function calculateOfferChange(int $elementId, int $iblockId): void
1833 {
1834 if (!isset(self::$offers[$elementId]))
1835 return;
1836
1837 $iblockData = \CCatalogSku::GetInfoByOfferIBlock($iblockId);
1838 if (!empty($iblockData))
1839 {
1840 $offerDescr = self::$offers[$elementId];
1841 $existCurrentProduct = ($offerDescr['CURRENT_PRODUCT'] > 0);
1842 $existNewProduct = ($offerDescr['NEW_PRODUCT'] > 0);
1843 if ($existCurrentProduct)
1844 {
1846 $offerDescr['CURRENT_PRODUCT'],
1847 $iblockData['PRODUCT_IBLOCK_ID'],
1849 );
1850 }
1851 if ($existNewProduct)
1852 {
1854 $offerDescr['NEW_PRODUCT'],
1855 $iblockData['PRODUCT_IBLOCK_ID'],
1857 );
1858 }
1859 if (!$existCurrentProduct || !$existNewProduct)
1860 {
1862 $type = (
1863 $existNewProduct
1864 ? Catalog\ProductTable::TYPE_OFFER
1865 : Catalog\ProductTable::TYPE_FREE_OFFER
1866 );
1867 $result = Catalog\Model\Product::update($elementId, array('TYPE' => $type));
1868 unset($result);
1870 }
1871 unset($existNewProduct, $existCurrentProduct);
1872 unset($offerDescr);
1873 }
1874 unset(self::$offers[$elementId]);
1875 }
1876}
static getCacheItem($id, bool $load=false)
Definition entity.php:396
static getDefaultParentSettings(int $state, bool $productIblock=false)
Definition sku.php:130
static usedDeferredCalculation()
Definition sku.php:107
static disablePropertyHandler()
Definition sku.php:1060
const ACTION_ELEMENT_TIMESTAMP
Definition sku.php:23
static enablePropertyHandler()
Definition sku.php:1050
static int $allowUpdateAvailable
Definition sku.php:25
static calculatePrice($id, $iblockId=null, $type=null, array $priceTypes=[])
Definition sku.php:396
static handlerAfterIblockElementDelete($elementData)
Definition sku.php:685
static handlerIblockElementUpdate($newFields, $oldFields)
Definition sku.php:523
static handlerAfterIBlockElementSetPropertyValues( $elementId, $iblockId, $newValues, $propertyIdentifyer)
Definition sku.php:823
static handlerIblockElementAdd($fields)
Definition sku.php:498
static int $allowPropertyHandler
Definition sku.php:26
static updateOfferType($offerId, $type)
Definition sku.php:1032
static allowedUpdateAvailable()
Definition sku.php:77
static enableUpdateAvailable()
Definition sku.php:57
static disableUpdateAvailable()
Definition sku.php:67
static enableDeferredCalculation()
Definition sku.php:87
static handlerAfterIblockElementAdd(&$fields)
Definition sku.php:510
static updateAvailable($productId, $iblockId=0, array $productFields=array())
Definition sku.php:185
static handlerIblockElementDelete($elementId, $elementData)
Definition sku.php:659
static handlerIblockElementSetPropertyValues( $elementId, $iblockId, $newValues, $propertyIdentifyer, $propertyList, $currentValues)
Definition sku.php:713
static handlerAfterIblockElementUpdate(&$fields)
Definition sku.php:543
static handlerAfterIblockElementSetPropertyValuesEx( $elementId, $iblockId, $newValues, $flags)
Definition sku.php:943
static getOfferState($productId, $iblockId=0)
Definition sku.php:963
static getParentProductFieldsByState(int $offerState)
Definition sku.php:118
static allowedPropertyHandler()
Definition sku.php:1070
static disableDeferredCalculation()
Definition sku.php:97
static calculateComplete($id, $iblockId=null, $type=null)
Definition sku.php:341
static handlerIblockElementSetPropertyValuesEx( $elementId, $iblockId, $newValues, $propertyList, $currentValues)
Definition sku.php:847
static array $productIds
Definition sku.php:28
static filterActive(array $row)
Definition sku.php:1082
static updateProductAvailable($productId, $iblockId)
Definition sku.php:1009
static array $offers
Definition sku.php:29
static calculateAvailable($fields)
Definition product.php:737