7use Bitrix\Catalog\Controller\Product\SkuDeferredCalculations;
22 use SkuDeferredCalculations;
33 'getSkuTreeProperties' => [
46 if ($action->getName() ===
'add')
50 else if ($action->getName() ===
'update')
57 $this->addErrors($r->getErrors());
67 return parent::processBeforeAction($action);
85 return parent::processAfterAction($action, $result);
98 $arguments = $action->getArguments();
100 $fields = $arguments[
'fields'];
101 $productId = $arguments[
'id'];
104 $iblockIdOrigin = $fields[
'iblockId'] ??
null;
105 if ($iblockIdOrigin !==
null)
107 $iblockIdOrigin = (int)$iblockIdOrigin;
110 if ($iblockIdOrigin && $iblockIdOrigin !== $iblockId)
115 'Product - %d is not exists in catalog - %d', $productId , $iblockIdOrigin
130 public function getFieldsByFilterAction($filter): ?array
133 $view = $this->getViewManager()
135 $r = $view->getFieldsByFilter($filter);
139 $this->addErrors($r->getErrors());
144 return [$this->getServiceItemName() =>$view->prepareFieldInfos(
150 static protected function perfGetList(array $select, array $filter, array $order, $pageNavigation =
null): array
155 $rsData = \CIBlockElement::GetList(
159 $pageNavigation ??
false,
160 array(
'ID',
'IBLOCK_ID')
162 while($row = $rsData->Fetch())
164 $rawRows[$row[
'ID']] = $row;
165 $elementIds[] = $row[
'ID'];
168 foreach (array_chunk($elementIds, \IRestService::LIST_LIMIT) as $pageIds)
171 'IBLOCK_ID' => $filter[
'IBLOCK_ID'],
174 $iterator = \CIBlockElement::GetList([], $elementFilter,
false,
false, $select);
175 while ($row = $iterator->Fetch())
177 $rawRows[$row[
'ID']] += $row;
199 $order = empty($order)? [
'ID'=>
'ASC']:$order;
204 $allProperties = isset($groupFields[
'elementFields'][
'PROPERTY_*']);
207 unset($groupFields[
'elementFields'][
'PROPERTY_*']);
210 $productFields = array_keys($groupFields[
'productFields']);
211 $elementFields = array_keys($groupFields[
'elementFields']);
212 $propertyFields = $groupFields[
'propertyFields'];
215 $propertyIds = array_keys($propertyFields);
216 $list = self::perfGetList(array_merge($productFields, $elementFields), $filter, $order, self::getNavData($pageNavigation->
getOffset()));
220 if ($allProperties || !empty($propertyIds))
225 foreach ($list as $row)
233 return (
int)\CIBlockElement::GetList([], $filter, []);
238 $this->addErrors($r->getErrors());
255 if($r->isSuccess() ===
false)
257 $this->addErrors($r->getErrors());
267 if (isset($fields[
'IBLOCK_SECTION_ID']) && (
int)$fields[
'IBLOCK_SECTION_ID'] > 0)
276 $element = new \CIBlockElement();
283 $productFields = $groupFields[
'productFields'];
284 $propertyFields = $groupFields[
'propertyFields'];
285 $elementFields = $groupFields[
'elementFields'];
289 $elementFieldsAdd = count($propertyFields)>0 ? array_merge($elementFields, [
'PROPERTY_VALUES'=>$propertyFields]):$elementFields;
291 $id = $element->Add($elementFieldsAdd);
292 if($element->LAST_ERROR<>
'')
294 $r->addError(
new Error($element->LAST_ERROR));
298 $productFields[
'ID'] = $id;
300 $r = \Bitrix\Catalog\Model\Product::add($productFields);
301 if($r->isSuccess() ===
false)
303 $element::Delete($id);
311 $this->addErrors($r->getErrors());
316 return [
'ELEMENT'=>$this->
get($id)];
326 if (isset($fields[
'IBLOCK_SECTION_ID']) && (
int)$fields[
'IBLOCK_SECTION_ID'] > 0)
334 $element = new \CIBlockElement();
338 $productFields = $groupFields[
'productFields'];
339 $propertyFields = $groupFields[
'propertyFields'];
340 $elementFields = $groupFields[
'elementFields'];
348 $elementFieldsUpdate = count($propertyFields)>0 ? array_merge($elementFields, [
'PROPERTY_VALUES'=>$propertyFields]):$elementFields;
356 $element->Update($id, $elementFieldsUpdate);
357 if($element->LAST_ERROR<>
'')
359 $r->addError(
new Error($element->LAST_ERROR));
361 elseif (!empty($productFields))
363 $r = \Bitrix\Catalog\Model\Product::update($id, $productFields);
371 return [
'ELEMENT'=>$this->
get($id)];
375 $this->addErrors($r->getErrors());
389 if (!\CIBlockElement::Delete($id))
391 if ($ex = self::getApplication()->GetException())
392 $r->addError(
new Error($ex->GetString(), $ex->GetId()));
394 $r->addError(
new Error(
'delete iBlockElement error'));
404 $this->addErrors($r->getErrors());
411 $productId = $fields[
'PRODUCT_ID'];
412 $fieldName = $fields[
'FIELD_NAME'];
413 $id = $fields[
'FILE_ID'];
416 $r = $this->
exists($productId);
419 $iblockId = $this->
get($productId)[
'IBLOCK_ID'];
424 $iBlock = \CIBlock::GetArrayByID($iblockId);
428 $element = \CIBlockElement::GetList(
431 "CATALOG_ID" => $iBlock[
"ID"],
433 "CHECK_PERMISSIONS" =>
"N",
437 array(
"ID", $fieldName)
439 while ($res = $element->GetNext())
441 if (isset($res[$fieldName]))
443 $files[] = $res[$fieldName];
445 elseif (isset($res[$fieldName.
"_VALUE"]))
447 if (is_array($res[$fieldName.
"_VALUE"]))
449 $files = array_merge($files, $res[$fieldName.
"_VALUE"]);
453 $files[] = $res[$fieldName.
"_VALUE"];
459 if (!in_array($id, $files))
461 $r->addError(
new Error(
'Product file wrong'));
465 $file = \CFile::GetFileArray($id);
466 if (is_array($file) ==
false)
468 $r->addError(
new Error(
'Product is empty'));
474 $r->addError(
new Error(
'Name file field is not available'));
480 return \Bitrix\Main\Engine\Response\BFile::createByFileId($file[
'ID']);
484 $this->addErrors($r->getErrors());
492 return \Bitrix\Catalog\Model\Product::getTabletClassName();
499 $propertyFields = [];
501 foreach($fields as $name=>$value)
505 $productFields[$name] = $value;
509 if (preg_match(
'/^(PROPERTY_\d+)$/', $name))
511 $propertyFields[$name] = $value;
515 $elementFields[$name] = $value;
521 'productFields'=>$productFields,
522 'propertyFields'=>$propertyFields,
523 'elementFields'=>$elementFields
531 if (UseStore::isUsed())
533 unset($result[
'QUANTITY_TRACE']);
544 foreach($fields as $name=>$value)
546 if (preg_match(
'/^(PROPERTY_)(\d+)$/', $name, $matches))
548 $result[$matches[2]] = $value;
560 foreach ($fields as $propertyId=>$value)
564 if(isset($value[
'VALUE']))
566 if(isset($value[
'VALUE_ID']))
569 $valueId=$value[
'VALUE_ID'];
570 unset($value[
'VALUE_ID']);
571 $property[$valueId]=$value;
583 if(is_array($value) && count($value)>0)
585 foreach ($value as $item)
587 if(isset($item[
'VALUE_ID']))
590 $valueId = $item[
'VALUE_ID'];
591 unset($item[
'VALUE_ID']);
592 $property[$valueId]=$item;
603 if(count($property)>0)
605 $result[$propertyId]=$property;
614 $fields = $propertyValues;
616 if ($id > 0 && $iblockId > 0 && !empty($propertyValues))
618 $r = \CIBlockElement::GetProperty(
624 'CHECK_PERMISSIONS' =>
'N',
627 while ($property = $r->Fetch())
630 $property[
'PROPERTY_TYPE'] !==
Iblock\PropertyTable::TYPE_FILE
631 && !array_key_exists($property[
'ID'], $propertyValues)
634 $fields[$property[
'ID']] ??= [];
636 $fields[$property[
'ID']][] = [
637 'VALUE_ID' => $property[
'PROPERTY_VALUE_ID'],
638 'VALUE' => $property[
'VALUE'],
639 'DESCRIPTION' => $property[
'DESCRIPTION'],
643 unset($property, $r);
652 if (isset($this->
get($id)[
'ID']) ==
false)
654 $r->addError(
new Error(
'Product is not exists'));
660 protected function get($id)
662 $row = \CIBlockElement::getList(
684 return $result[$row[
'ID']];
701 if (isset($fields[
'SECTION_ID']))
703 $section = \CIBlockSection::GetByID($fields[
'SECTION_ID'])->Fetch();
704 if (!isset($section[
'ID']))
706 $r->addError(
new Error(
'Section is not exists'));
709 if (isset($fields[
'MODIFIED_BY']))
711 $user = \CUser::GetByID($fields[
'MODIFIED_BY'])->Fetch();
712 if (!isset($user[
'ID']))
714 $r->addError(
new Error(
'User modifiedBy is not exists'));
717 if (isset($fields[
'CREATED_BY']))
719 $user = \CUser::GetByID($fields[
'CREATED_BY'])->Fetch();
720 if (!isset($user[
'ID']))
722 $r->addError(
new Error(
'User createdBy is not exists'));
725 if (isset($fields[
'PURCHASING_CURRENCY']))
727 $currency = \CCurrency::GetByID($fields[
'PURCHASING_CURRENCY']);
728 if (!isset($currency[
'CURRENCY']))
730 $r->addError(
new Error(
'Currency purchasingCurrency is not exists'));
733 if (isset($fields[
'VAT_ID']))
735 $user = \CCatalogVat::GetByID($fields[
'VAT_ID'])->Fetch();
736 if (!isset($user[
'ID']))
738 $r->addError(
new Error(
'VAT vatId is not exists'));
758 $propertyFilter = !empty($propertyIds) ? [
'ID' => $propertyIds] : [];
760 $propertyValues = [];
761 \CIBlockElement::getPropertyValuesArray(
764 [
'ID' => array_keys($result)],
766 [
'USE_PROPERTY_ID' =>
'Y']
769 foreach ($result as $k => $v)
771 if (isset($propertyValues[$k]))
773 foreach ($propertyValues[$k] as $propId => $fields)
777 if (isset($fields[
'PROPERTY_VALUE_ID']))
779 if ($fields[
'PROPERTY_TYPE'] ===
Iblock\PropertyTable::TYPE_LIST)
781 if ($fields[
'MULTIPLE'] ===
'Y')
783 if (is_array($fields[
'PROPERTY_VALUE_ID']))
785 foreach ($fields[
'PROPERTY_VALUE_ID'] as $i => $item)
788 'VALUE' => $fields[
'VALUE_ENUM_ID'][$i],
789 'VALUE_ENUM' => $fields[
'VALUE_ENUM'][$i],
790 'VALUE_ID' => $fields[
'PROPERTY_VALUE_ID'][$i],
798 'VALUE' => $fields[
'VALUE_ENUM_ID'],
799 'VALUE_ENUM' => $fields[
'VALUE_ENUM'],
800 'VALUE_ID' => $fields[
'PROPERTY_VALUE_ID']
806 if ($fields[
'MULTIPLE'] ===
'Y')
808 if (is_array($fields[
'PROPERTY_VALUE_ID']))
810 foreach ($fields[
'PROPERTY_VALUE_ID'] as $i => $item)
813 'VALUE' => $fields[
'VALUE'][$i],
814 'VALUE_ID' => $fields[
'PROPERTY_VALUE_ID'][$i]
822 'VALUE' => $fields[
'VALUE'],
823 'VALUE_ID' => $fields[
'PROPERTY_VALUE_ID']
829 $result[$k][
'PROPERTY_' . $propId] = $value;
832 elseif (!empty($propertyIds))
838 foreach ($propertyIds as $propId)
840 $result[$k][
'PROPERTY_' . $propId] =
null;
848 $name = mb_strtolower($name);
850 if($name ==
'getfieldsbyfilter'
851 || $name ==
'download'
858 $r = parent::checkPermissionEntity($name);
886 'RECUR_SCHEME_LENGTH',
890 'QUANTITY_TRACE_RAW',
896 if ($this->accessController->check(ActionDictionary::ACTION_PRODUCT_PURCHASE_INFO_VIEW))
898 array_push($result,
'PURCHASING_PRICE',
'PURCHASING_CURRENCY');
906 $name = $fields[
'NAME'];
907 $iblockId = $fields[
'IBLOCK_ID'];
909 if ($name ===
"DETAIL_PICTURE")
911 elseif ($name ===
"PREVIEW_PICTURE")
913 elseif ($name ===
"PICTURE")
915 elseif (!preg_match(
"/^PROPERTY_(.+)\$/", $name, $match))
919 $db_prop = \CIBlockProperty::GetPropertyArray($match[1], $iblockId);
920 if(is_array($db_prop) && $db_prop[
"PROPERTY_TYPE"] ===
"F")
931 $this->addErrors($r->getErrors());
935 $iblockProperty = new \CIBlockProperty();
937 $propertyFields = array(
939 'IBLOCK_ID' => $fields[
'IBLOCK_ID'],
940 'NAME' => $fields[
'NAME'],
941 'SORT' => $fields[
'SORT'] ?? 100,
942 'CODE' => $fields[
'CODE'] ??
'',
943 'MULTIPLE' => ($fields[
'MULTIPLE'] ===
'Y') ?
'Y' :
'N',
944 'IS_REQUIRED'=> ($fields[
'IS_REQUIRED'] ===
'Y') ?
'Y' :
'N',
945 'SECTION_PROPERTY'=>
'N',
948 $newID = (int)($iblockProperty->Add($propertyFields));
951 $this->addError(
new \
Bitrix\Main\
Error($iblockProperty->LAST_ERROR));
957 'CONTROL_ID' =>
'PROPERTY_'.$newID
972 !$this->accessController->check(ActionDictionary::ACTION_CATALOG_READ)
973 && !$this->accessController->check(ActionDictionary::ACTION_PRICE_EDIT)
974 && !$this->accessController->check(ActionDictionary::ACTION_CATALOG_VIEW)
977 $r->addError(
new Error(
'Access Denied', 200040300010));
988 $arIBlock = \CIBlock::GetArrayByID($iblockId,
'NAME');
989 if (empty($arIBlock))
991 $result->addError(
new Error(
'Iblock Not Found', 200040300000));
1015 if (!$this->accessController->check(ActionDictionary::ACTION_PRODUCT_ADD))
1017 $result->addError(
new Error(
'Access Denied', 200040300040));
1047 if (!$this->accessController->check(ActionDictionary::ACTION_PRODUCT_EDIT))
1049 $result->addError(
new Error(
'Access Denied', 200040300040));
1057 $iblockId = \CIBlockElement::GetIBlockByID($elementId);
1064 $iblockId = (int)$iblockId;
1067 if (!$r->isSuccess())
1072 if (!\CIBlockRights::UserHasRightTo($iblockId, $iblockId, self::IBLOCK_EDIT))
1074 $r->addError(
new Error(
'Access Denied', 200040300040));
1082 $iblockId = (int)$iblockId;
1085 if (!$r->isSuccess())
1092 $bBadBlock = !\CIBlockElementRights::UserHasRightTo($iblockId, $elementId, self::IBLOCK_ELEMENT_EDIT);
1096 $bBadBlock = !\CIBlockRights::UserHasRightTo($iblockId, $iblockId, self::IBLOCK_ELEMENT_EDIT);
1101 $r->addError(
new Error(
'Access Denied', 200040300043));
1125 if (!$this->accessController->check(ActionDictionary::ACTION_PRODUCT_DELETE))
1127 $result->addError(
new Error(
'Access Denied', 200040300040));
1135 $iblockId = (int)\CIBlockElement::GetIBlockByID($elementId);
1138 if (!$r->isSuccess())
1143 if (!\CIBlockElementRights::UserHasRightTo($iblockId, $elementId, self::IBLOCK_ELEMENT_DELETE))
1145 $r->addError(
new Error(
'Access Denied', 200040300040));
1153 $iblockId = (int)\CIBlockElement::GetIBlockByID($elementId);
1155 if (!$r->isSuccess())
1160 if (!\CIBlockElementRights::UserHasRightTo($iblockId, $elementId, self::IBLOCK_ELEMENT_READ))
1162 $r->addError(
new Error(
'Access Denied', 200040300040));
1170 $iblockId = (int)$iblockId;
1172 if (!$r->isSuccess())
1177 if (!\CIBlockRights::UserHasRightTo($iblockId, $iblockId, self::IBLOCK_READ))
1179 $r->addError(
new Error(
'Access Denied', 200040300030));
1187 $iblockId = (int)$iblockId;
1189 if (!$r->isSuccess())
1194 if (!\CIBlockSectionRights::UserHasRightTo(
1197 self::IBLOCK_ELEMENT_SECTION_BIND
1200 $r->addError(
new Error(
'Access Denied', 200040300050));
1215 $section = \CIBlockSection::GetList(
1226 $res = $section->Fetch();
1229 return (
int)($res[
'IBLOCK_ID'] ?? 0);
1239 return [self::class,
'processItemEvent'];
1245 $event = $arParams[0] ??
null;
1249 throw new RestException(
'event object not found trying to process event');
1252 if($event instanceof
Event)
1254 $id = $event->getParameter(
'id');
1258 $item = $event->getParameter(
'id');
1259 $id = is_array($item) ? $item[
'ID']: $item;
1264 throw new RestException(
'id not found trying to process event');
1267 $product = \Bitrix\Catalog\Model\Product::getCacheItem($id);
1269 $type = $product[
'TYPE'] ??
null;
1273 throw new RestException(
'type is not specified trying to process event');
1286 $entity = (
new static())->getEntity();
1287 $class = $entity->getNamespace() . $entity->getName();
1288 $model = \Bitrix\Catalog\Model\Product::class;
1291 Event::makeEventName($model,DataManager::EVENT_ON_AFTER_ADD) => $entity->getModule().
'.'.$entity->getName().
'.on.add',
1292 Event::makeEventName($model,DataManager::EVENT_ON_AFTER_UPDATE) => $entity->getModule().
'.'.$entity->getName().
'.on.update',
1293 Event::makeEventName($class,DataManager::EVENT_ON_DELETE) => $entity->getModule().
'.'.$entity->getName().
'.on.delete',
1308 $iblockId = \CIBlockElement::GetIBlockByID($productId);
checkPermissionIBlockElementModify($iblockId, $elementId)
checkModifyPermissionEntity()
static getCallbackRestEvent()
splitFieldsByEntity($fields)
checkPermissionIBlockElementGet($elementId)
checkReadPermissionEntity()
checkPermissionCatalogProductDelete(int $elementId)
attachPropertyValues(array &$result, int $iblockId, array $propertyIds=[])
getIBlockBySectionId($id)
processBeforeAdd(Engine\Action $action)
preparePropertyFieldsUpdate($fields)
checkPermissionIBlockElementAdd(int $iblockId)
processBeforeAction(Engine\Action $action)
checkPermissionIBlockModify($iblockId)
processBeforeUpdate(Engine\Action $action)
downloadAction(array $fields)
checkFieldsDownload($fields)
processAfterAction(Engine\Action $action, $result)
checkPermissionIBlockElementUpdate(int $elementId)
checkPermissionIBlockElementList($iblockId)
updateAction(int $id, array $fields)
preparePropertyFields($fields)
listAction(PageNavigation $pageNavigation, array $select=[], array $filter=[], array $order=[])
fillPropertyFieldsDefaultPropertyValues($id, $iblockId, $propertyValues)
checkPermissionIBlockElementDelete(int $elementId)
prepareProductFields(array $fields)
existsIblock(int $iblockId)
checkPermissionCatalogProductUpdate(int $elementId)
static processItemEvent(array $arParams, array $arHandler)
checkPermissionIBlockElementSectionBindUpdate($iblockSectionId)
checkPermissionEntity($name, $arguments=[])
checkPermissionAdd(int $iblockId)
checkPermissionDelete(int $elementId)
checkPermissionUpdate(int $elementId)
addPropertyAction($fields)
getAllowedFieldsProduct()
checkPermissionIBlockElementSectionBindModify($iblockId, $iblockSectionId)
static getProductIblockId(int $productId)
static perfGetList(array $select, array $filter, array $order, $pageNavigation=null)
checkPermissionCatalogProductAdd()
isActionWithDefferedCalculation(Action $action)
processAfterDeferredCalculationAction()
processBeforeDeferredCalculationAction()