6require_once(
$_SERVER[
"DOCUMENT_ROOT"].
"/bitrix/modules/catalog/general/product_set.php");
14 foreach (
GetModuleEvents(
"catalog",
"OnBeforeProductSetAdd",
true) as $arEvent)
20 if (!self::checkFields(
'ADD',
$arFields, 0))
24 unset($arSet[
'ITEMS']);
25 $arInsert =
$DB->PrepareInsert(
"b_catalog_product_sets",
$arFields);
26 $strSql =
"insert into b_catalog_product_sets(".$arInsert[0].
") values(".$arInsert[1].
")";
28 $intID = (int)
$DB->LastID();
31 foreach (
$arFields[
'ITEMS'] as &$arOneItem)
33 $arOneItem[
'SET_ID'] = $intID;
34 $arInsert =
$DB->PrepareInsert(
"b_catalog_product_sets", $arOneItem);
35 $strSql =
"insert into b_catalog_product_sets(".$arInsert[0].
") values(".$arInsert[1].
")";
39 switch ($arSet[
'TYPE'])
46 case self::TYPE_GROUP:
52 foreach (
GetModuleEvents(
"catalog",
"OnProductSetAdd",
true) as $arEvent)
65 foreach (
GetModuleEvents(
"catalog",
"OnBeforeProductSetUpdate",
true) as $arEvent)
71 if (!self::checkFields(
'UPDATE',
$arFields, $intID))
79 $boolItems = array_key_exists(
'ITEMS',
$arFields);
81 unset($arSet[
'ITEMS']);
82 $strUpdate =
$DB->PrepareUpdate(
"b_catalog_product_sets", $arSet);
83 if (!empty($strUpdate))
85 $strSql =
"update b_catalog_product_sets set ".$strUpdate.
" where ID = ".$intID;
91 foreach (
$arFields[
'ITEMS'] as &$arOneItem)
93 if (isset($arOneItem[
'ID']))
95 $intSubID = $arOneItem[
'ID'];
96 unset($arOneItem[
'ID']);
97 $strUpdate =
$DB->PrepareUpdate(
"b_catalog_product_sets", $arOneItem);
98 if (!empty($strUpdate))
100 $strSql =
"update b_catalog_product_sets set ".$strUpdate.
" where ID = ".$intSubID;
106 $arInsert =
$DB->PrepareInsert(
"b_catalog_product_sets", $arOneItem);
107 $strSql =
"insert into b_catalog_product_sets(".$arInsert[0].
") values(".$arInsert[1].
")";
109 $intSubID = (int)
$DB->LastID();
111 $arOneItem[
'ID'] = $intSubID;
112 $arIDs[] = $intSubID;
118 $strSql =
"select ID, ITEM_ID, TYPE from b_catalog_product_sets where ID = ".$intID;
119 $rsSets =
$DB->Query($strSql);
120 if ($arSet = $rsSets->Fetch())
122 switch ($arSet[
'TYPE'])
129 case self::TYPE_GROUP:
136 foreach (
GetModuleEvents(
"catalog",
"OnProductSetUpdate",
true) as $arEvent)
145 public static function delete($intID)
149 $intID = (int)$intID;
153 foreach (
GetModuleEvents(
"catalog",
"OnBeforeProductSetDelete",
true) as $arEvent)
160 if (!empty($arItem) && is_array($arItem))
162 $strSql =
"delete from b_catalog_product_sets where SET_ID=".$arItem[
'ID'];
164 $strSql =
"delete from b_catalog_product_sets where ID=".$arItem[
'ID'];
166 switch ($arItem[
'TYPE'])
172 case self::TYPE_GROUP:
173 if (!static::isProductHaveSet($arItem[
'ITEM_ID'], self::TYPE_GROUP))
181 foreach (
GetModuleEvents(
"catalog",
"OnProductSetDelete",
true) as $arEvent)
196 'ID' =>
array(
'FIELD' =>
'CPS.ID',
'TYPE' =>
'int'),
197 'TYPE' =>
array(
'FIELD' =>
'CPS.TYPE',
'TYPE' =>
'int'),
198 'SET_ID' =>
array(
'FIELD' =>
'CPS.SET_ID',
'TYPE' =>
'int'),
199 'ACTIVE' =>
array(
'FIELD' =>
'CPS.ACTIVE',
'TYPE' =>
'char'),
200 'OWNER_ID' =>
array(
'FIELD' =>
'CPS.OWNER_ID',
'TYPE' =>
'int'),
201 'ITEM_ID' =>
array(
'FIELD' =>
'CPS.ITEM_ID',
'TYPE' =>
'int'),
202 'QUANTITY' =>
array(
'FIELD' =>
'CPS.QUANTITY',
'TYPE' =>
'double'),
203 'MEASURE' =>
array(
'FIELD' =>
'CPS.MEASURE',
'TYPE' =>
'int'),
204 'DISCOUNT_PERCENT' =>
array(
'FIELD' =>
'CPS.DISCOUNT_PERCENT',
'TYPE' =>
'double'),
205 'SORT' =>
array(
'FIELD' =>
'CPS.SORT',
'TYPE' =>
'int'),
206 'CREATED_BY' =>
array(
'FIELD' =>
'CPS.CREATED_BY',
'TYPE' =>
'int'),
207 'DATE_CREATE' =>
array(
'FIELD' =>
'CPS.DATE_CREATE',
'TYPE' =>
'datetime'),
208 'MODIFIED_BY' =>
array(
'FIELD' =>
'CPS.MODIFIED_BY',
'TYPE' =>
'int'),
209 'TIMESTAMP_X' =>
array(
'FIELD' =>
'CPS.TIMESTAMP_X',
'TYPE' =>
'datetime'),
210 'XML_ID' =>
array(
'FIELD' =>
'CPS.XML_ID',
'TYPE' =>
'string')
215 $arSqls[
"SELECT"] = str_replace(
"%%_DISTINCT_%%",
"", $arSqls[
"SELECT"]);
217 if (empty($arGroupBy) && is_array($arGroupBy))
219 $strSql =
"select ".$arSqls[
"SELECT"].
" from b_catalog_product_sets CPS ".$arSqls[
"FROM"];
220 if (!empty($arSqls[
"WHERE"]))
221 $strSql .=
" where ".$arSqls[
"WHERE"];
222 if (!empty($arSqls[
"GROUPBY"]))
223 $strSql .=
" group by ".$arSqls[
"GROUPBY"];
232 $strSql =
"select ".$arSqls[
"SELECT"].
" from b_catalog_product_sets CPS ".$arSqls[
"FROM"];
233 if (!empty($arSqls[
"WHERE"]))
234 $strSql .=
" where ".$arSqls[
"WHERE"];
235 if (!empty($arSqls[
"GROUPBY"]))
236 $strSql .=
" group by ".$arSqls[
"GROUPBY"];
237 if (!empty($arSqls[
"ORDERBY"]))
238 $strSql .=
" order by ".$arSqls[
"ORDERBY"];
241 $boolNavStartParams = (!empty($arNavStartParams) && is_array($arNavStartParams));
242 if ($boolNavStartParams && isset($arNavStartParams[
'nTopCount']))
244 $intTopCount = (int)$arNavStartParams[
"nTopCount"];
246 if ($boolNavStartParams && 0 >= $intTopCount)
248 $strSql_tmp =
"select COUNT('x') as CNT from b_catalog_product_sets CPS ".$arSqls[
"FROM"];
249 if (!empty($arSqls[
"WHERE"]))
250 $strSql_tmp .=
" where ".$arSqls[
"WHERE"];
251 if (!empty($arSqls[
"GROUPBY"]))
252 $strSql_tmp .=
" group by ".$arSqls[
"GROUPBY"];
256 if (empty($arSqls[
"GROUPBY"]))
263 $cnt =
$dbRes->SelectedRowsCount();
268 $dbRes->NavQuery($strSql, $cnt, $arNavStartParams);
272 if ($boolNavStartParams && 0 < $intTopCount)
274 $strSql .=
" limit ".$intTopCount;
291 $intProductID = (int)$intProductID;
292 if (0 >= $intProductID)
294 $intSetType = (int)$intSetType;
295 $strSql =
'select ID from b_catalog_product_sets where ITEM_ID='.$intProductID;
296 if (self::TYPE_SET == $intSetType || self::TYPE_GROUP == $intSetType)
297 $strSql .=
' and TYPE='.$intSetType;
298 $strSql .=
' limit 1';
299 $rsRes =
$DB->Query($strSql);
300 if (
$arRes = $rsRes->Fetch())
317 if (!is_array($arProductID))
318 $arProductID =
array($arProductID);
320 if (empty($arProductID))
322 $intSetType = (int)$intSetType;
324 $strSql =
'select ID from b_catalog_product_sets where OWNER_ID in('.implode(
', ', $arProductID).
')';
325 if (self::TYPE_SET == $intSetType || self::TYPE_GROUP == $intSetType)
326 $strSql .=
' and TYPE='.$intSetType;
327 $strSql .=
' limit 1';
328 $rsRes =
$DB->Query($strSql);
329 if (
$arRes = $rsRes->Fetch())
345 $intProductID = (int)$intProductID;
346 if (0 >= $intProductID)
348 $intSetType = (int)$intSetType;
349 if (self::TYPE_SET != $intSetType && self::TYPE_GROUP != $intSetType)
352 $arEmptySet = static::getEmptySet($intSetType);
354 $boolSet = self::TYPE_SET == $intSetType;
357 $strSql =
"select CPS.ID, CPS.SET_ID, CPS.ACTIVE, CPS.OWNER_ID, CPS.ITEM_ID, CPS.SORT, CPS.QUANTITY, CP.MEASURE";
359 $strSql .=
", CPS.DISCOUNT_PERCENT";
360 $strSql .=
" from b_catalog_product_sets CPS".
361 " left join b_catalog_product CP on (CP.ID = CPS.ITEM_ID)".
362 " where CPS.OWNER_ID=".$intProductID.
" and CPS.TYPE=".$intSetType;
363 $rsItems =
$DB->Query($strSql);
364 while ($arItem = $rsItems->Fetch())
366 $arItem[
'ID'] = (int)$arItem[
'ID'];
367 $arItem[
'SET_ID'] = (int)$arItem[
'SET_ID'];
368 $arItem[
'OWNER_ID'] = (int)$arItem[
'OWNER_ID'];
369 $arItem[
'ITEM_ID'] = (int)$arItem[
'ITEM_ID'];
370 $arItem[
'SORT'] = (int)$arItem[
'SORT'];
372 $boolProduct = $arItem[
'ITEM_ID'] == $arItem[
'OWNER_ID'];
373 $intSetID = ($boolProduct ? $arItem[
'ID'] : $arItem[
'SET_ID']);
376 $arItem[
'QUANTITY'] = ($arItem[
'QUANTITY'] ===
null ?
false : (float)$arItem[
'QUANTITY']);
377 $arItem[
'MEASURE'] = ($arItem[
'MEASURE'] ===
null ?
false : (int)$arItem[
'MEASURE']);
378 $arItem[
'DISCOUNT_PERCENT'] = ($arItem[
'DISCOUNT_PERCENT'] ===
null ?
false : $arItem[
'DISCOUNT_PERCENT']);
382 unset($arItem[
'OWNER_ID']);
383 unset($arItem[
'SET_ID']);
384 unset($arItem[
'ID']);
389 unset($arItem[
'SET_ID']);
390 unset($arItem[
'OWNER_ID']);
391 unset($arItem[
'ACTIVE']);
396 $arResult[$intSetID][
'SET_ID'] = $intSetID;
404 $arResult[$intSetID][
'ITEMS'][$arItem[
'ID']] = $arItem;
419 $intID = (int)$intID;
424 $strSql =
"select CPS.ID, CPS.SET_ID, CPS.ACTIVE, CPS.OWNER_ID, CPS.ITEM_ID, CPS.SORT, CPS.QUANTITY, CP.MEASURE".
425 ", CPS.DISCOUNT_PERCENT, CPS.TYPE";
426 $strSql .=
" from b_catalog_product_sets CPS".
427 " left join b_catalog_product CP on (CP.ID = CPS.ITEM_ID)".
428 " where CPS.ID=".$intID;
429 $rsItems =
$DB->Query($strSql);
430 if ($arItem = $rsItems->Fetch())
432 $arItem[
'ID'] = (int)$arItem[
'ID'];
433 $arItem[
'TYPE'] = (int)$arItem[
'TYPE'];
434 $arItem[
'SET_ID'] = (int)$arItem[
'SET_ID'];
435 $arItem[
'OWNER_ID'] = (int)$arItem[
'OWNER_ID'];
436 $arItem[
'ITEM_ID'] = (int)$arItem[
'ITEM_ID'];
437 $arItem[
'SORT'] = (int)$arItem[
'SORT'];
438 $arItem[
'QUANTITY'] = ($arItem[
'QUANTITY'] ===
null ?
false : (float)$arItem[
'QUANTITY']);
439 $arItem[
'MEASURE'] = ($arItem[
'MEASURE'] ===
null ?
false : (int)$arItem[
'MEASURE']);
440 $arItem[
'DISCOUNT_PERCENT'] = ($arItem[
'DISCOUNT_PERCENT'] ===
null ?
false : (float)$arItem[
'DISCOUNT_PERCENT']);
444 $strSql =
"select CPS.ID, CPS.SET_ID, CPS.ACTIVE, CPS.OWNER_ID, CPS.ITEM_ID, CPS.SORT, CPS.QUANTITY, CP.MEASURE".
445 ", CPS.DISCOUNT_PERCENT, CPS.TYPE";
446 $strSql .=
" from b_catalog_product_sets CPS".
447 " left join b_catalog_product CP on (CP.ID = CPS.ITEM_ID)".
448 " where CPS.SET_ID=".$intID;
449 $rsSubs =
$DB->Query($strSql);
450 while ($arSub = $rsSubs->Fetch())
452 $arSub[
'ID'] = (int)$arSub[
'ID'];
453 $arSub[
'TYPE'] = (int)$arSub[
'TYPE'];
454 $arSub[
'SET_ID'] = (int)$arSub[
'SET_ID'];
455 $arSub[
'OWNER_ID'] = (int)$arSub[
'OWNER_ID'];
456 $arSub[
'ITEM_ID'] = (int)$arSub[
'ITEM_ID'];
457 $arSub[
'SORT'] = (int)$arSub[
'SORT'];
458 $arSub[
'QUANTITY'] = ($arSub[
'QUANTITY'] ===
null ?
false: (float)$arSub[
'QUANTITY']);
459 $arSub[
'MEASURE'] = ($arSub[
'MEASURE'] ===
null ?
false: (int)$arSub[
'MEASURE']);
460 $arSub[
'DISCOUNT_PERCENT'] = ($arSub[
'DISCOUNT_PERCENT'] ===
null ?
false : (float)$arSub[
'DISCOUNT_PERCENT']);
462 $arResult[
'ITEMS'][$arSub[
'ID']] = $arSub;
476 if (!static::isEnabledRecalculateSet())
481 $product = (int)$product;
482 $query =
'select SET_ID, OWNER_ID, ITEM_ID from b_catalog_product_sets where ITEM_ID='.$product.
' and TYPE='.self::TYPE_SET;
484 while ($setItem = $setIterator->Fetch())
486 $setItem[
'SET_ID'] = (int)$setItem[
'SET_ID'];
487 $setItem[
'OWNER_ID'] = (int)$setItem[
'OWNER_ID'];
488 $setItem[
'ITEM_ID'] = (int)$setItem[
'ITEM_ID'];
489 if ($setItem[
'ITEM_ID'] === $setItem[
'OWNER_ID'])
491 $setsList[$setItem[
'OWNER_ID']] =
array();
492 $setsID[] = $setItem[
'SET_ID'];
494 unset($setItem, $setIterator,
$query);
498 $productMap =
array();
500 $query =
'select SET_ID, OWNER_ID, ITEM_ID, QUANTITY as QUANTITY_IN_SET from b_catalog_product_sets where SET_ID IN('.implode(
',', $setsID).
')';
502 while ($setItem = $setIterator->Fetch())
504 $setItem[
'SET_ID'] = (int)$setItem[
'SET_ID'];
505 $setItem[
'OWNER_ID'] = (int)$setItem[
'OWNER_ID'];
506 $setItem[
'ITEM_ID'] = (int)$setItem[
'ITEM_ID'];
507 if ($setItem[
'ITEM_ID'] === $setItem[
'OWNER_ID'])
509 if (!isset($setsList[$setItem[
'OWNER_ID']]))
510 $setsList[$setItem[
'OWNER_ID']] =
array();
511 $setsList[$setItem[
'OWNER_ID']][$setItem[
'ITEM_ID']] = $setItem;
512 if (!isset($productMap[$setItem[
'ITEM_ID']]))
513 $productMap[$setItem[
'ITEM_ID']] =
array();
514 $productMap[$setItem[
'ITEM_ID']][] = $setItem[
'OWNER_ID'];
515 $productIds[$setItem[
'ITEM_ID']] = $setItem[
'ITEM_ID'];
517 unset($setItem, $setIterator,
$query);
520 foreach (array_chunk($productIds, 500) as $rowIds)
523 'select' => [
'ID',
'QUANTITY',
'QUANTITY_TRACE',
'CAN_BUY_ZERO',
'WEIGHT'],
524 'filter' => [
'@ID' => $rowIds]
528 $item[
'ID'] = (int)$item[
'ID'];
529 if (!isset($productMap[$item[
'ID']]))
531 foreach ($productMap[$item[
'ID']] as &$setKey)
532 $setsList[$setKey][$item[
'ID']] = array_merge($setsList[$setKey][$item[
'ID']], $item);
539 $setsList = array_filter($setsList);
540 if (!empty($setsList))
542 foreach ($setsList as $setKey => $oneSet)
543 static::calculateSetParams($setKey, $oneSet);
544 unset($setKey, $oneSet);
553 $intID = (int)$intID;
557 $strSql =
"select ID, TYPE, SET_ID, OWNER_ID, ITEM_ID from b_catalog_product_sets where ID=".$intID;
558 $rsItems =
$DB->Query($strSql);
559 if ($arItem = $rsItems->Fetch())
561 $arItem[
'ID'] = (int)$arItem[
'ID'];
562 $arItem[
'SET_ID'] = (int)$arItem[
'SET_ID'];
563 $arItem[
'OWNER_ID'] = (int)$arItem[
'OWNER_ID'];
564 $arItem[
'ITEM_ID'] = (int)$arItem[
'ITEM_ID'];
565 $arItem[
'TYPE'] = (int)$arItem[
'TYPE'];
566 if ($arItem[
'OWNER_ID'] == $arItem[
'ITEM_ID'] && 0 == $arItem[
'SET_ID'])
578 $intID = (int)$intID;
585 $strSql =
"delete from b_catalog_product_sets where SET_ID=".$intID.
" and ID NOT IN(".implode(
', ', $arEx).
")";
597 $quantityTrace =
'N';
603 $tracedItems = array_filter(
$items, [__CLASS__,
'isTracedItem']);
604 if (empty($tracedItems))
611 $quantityTrace =
'Y';
613 foreach (
$items as &$oneItem)
614 $weight += $oneItem[
'WEIGHT']*$oneItem[
'QUANTITY_IN_SET'];
617 foreach ($tracedItems as &$oneItem)
619 if ($oneItem[
'QUANTITY'] <= 0)
622 $itemQuantity = (int)floor($oneItem[
'QUANTITY']/$oneItem[
'QUANTITY_IN_SET']);
624 if ($quantity ===
null || $quantity > $itemQuantity)
625 $quantity = $itemQuantity;
627 $weight += $oneItem[
'WEIGHT']*$oneItem[
'QUANTITY_IN_SET'];
631 $measure = CCatalogMeasure::getDefaultMeasure(
true,
false);
635 'QUANTITY' => $quantity,
636 'QUANTITY_TRACE' => $quantityTrace,
637 'CAN_BUY_ZERO' => $canBuyZero,
638 'MEASURE' => $measure[
'ID'],
648 $fields[
'SUBSCRIBE'] = $productData[
'SUBSCRIBE'];
653 foreach(
GetModuleEvents(
'catalog',
'OnBeforeProductSetAvailableUpdate',
true) as $arEvent)
656 $update =
$DB->PrepareUpdate(
'b_catalog_product',
$fields);
658 $query =
"update b_catalog_product set ".$update.
" where ID = ".$productID;
663 foreach (
GetModuleEvents(
'catalog',
'OnProductSetAvailableUpdate',
true) as $arEvent)
666 $query =
"delete from b_catalog_measure_ratio where PRODUCT_ID = ".$productID;
669 'PRODUCT_ID' => $productID,
673 $insert =
$DB->PrepareInsert(
'b_catalog_measure_ratio',
$fields);
674 $query =
"insert into b_catalog_measure_ratio (".$insert[0].
") values(".$insert[1].
")";
685 $getProductID = ($getProductID ===
true);
692 $query =
'select ID, ITEM_ID, QUANTITY from b_catalog_product_sets where SET_ID = '.$setID.
' or ID = '.$setID;
694 while ($item = $setIterator->Fetch())
696 $item[
'ID'] = (int)$item[
'ID'];
697 if ($item[
'ID'] == $setID)
699 $result[
'ITEM_ID'] = $item[
'ID'];
703 $item[
'ITEM_ID'] = (int)$item[
'ITEM_ID'];
705 'QUANTITY_IN_SET' => $item[
'QUANTITY']
712 $query =
'select ITEM_ID, QUANTITY from b_catalog_product_sets where SET_ID = '.$setID;
714 while ($item = $setIterator->Fetch())
716 $item[
'ITEM_ID'] = (int)$item[
'ITEM_ID'];
718 'QUANTITY_IN_SET' => $item[
'QUANTITY']
static update($id, array $data)
static onProductSetAvailableUpdate($productId, $fields)
static checkPermissionSubscribe($subscribe)
static setOldProductAvailable($productId, $available)
static getRowById($id, array $parameters=[])
static getList(array $parameters=array())
static normalizeArrayValuesByInt(&$map, $sorted=true)
static PrepareSql(&$arFields, $arOrder, $arFilter, $arGroupBy, $arSelectFields)
static isAvailable($product)
static fillSetItemsParams(&$items)
static createSetItemsParamsFromAdd($items)
static calculateSetParams($productID, $items)
static update($intID, $arFields)
static isProductInSet($intProductID, $intSetType=0)
static deleteFromSet($intID, $arEx)
static getAllSetsByProduct($intProductID, $intSetType)
static getList($arOrder=array(), $arFilter=array(), $arGroupBy=false, $arNavStartParams=false, $arSelect=array())
static isProductHaveSet($arProductID, $intSetType=0)
static createSetItemsParamsFromUpdate($setID, $getProductID=false)
static getSetByID($intID)
static recalculateSetsByProduct($product)
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
$_SERVER["DOCUMENT_ROOT"]
ExecuteModuleEventEx($arEvent, $arParams=[])
GetModuleEvents($MODULE_ID, $MESSAGE_ID, $bReturnArray=false)