Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
product.php
1<?php
2
4
7use Bitrix\Catalog\Controller\Product\SkuDeferredCalculations;
19
20class Product extends Controller implements EventBindInterface
21{
22 use SkuDeferredCalculations;
23
27 public function configureActions()
28 {
29 return [
30 'addProperty' => [
31 '+prefilters' => [new Scope(Scope::AJAX)]
32 ],
33 'getSkuTreeProperties' => [
34 '+prefilters' => [new Scope(Scope::AJAX)]
35 ],
36 ];
37 }
38
42 protected function processBeforeAction(Engine\Action $action)
43 {
44 $r = new Result();
45
46 if ($action->getName() === 'add')
47 {
48 $r = $this->processBeforeAdd($action);
49 }
50 else if ($action->getName() === 'update')
51 {
52 $r = $this->processBeforeUpdate($action);
53 }
54
55 if (!$r->isSuccess())
56 {
57 $this->addErrors($r->getErrors());
58
59 return null;
60 }
61
62 if ($this->isActionWithDefferedCalculation($action))
63 {
65 }
66
67 return parent::processBeforeAction($action);
68 }
69
78 protected function processAfterAction(Engine\Action $action, $result)
79 {
80 if ($this->isActionWithDefferedCalculation($action))
81 {
83 }
84
85 return parent::processAfterAction($action, $result);
86 }
87
94 protected function processBeforeUpdate(Engine\Action $action): Result
95 {
96 $r = new Result();
97
98 $arguments = $action->getArguments();
99
100 $fields = $arguments['fields'];
101 $productId = $arguments['id'];
102
103 $iblockId = $this->getProductIblockId($productId);
104 $iblockIdOrigin = $fields['iblockId'] ?? null;
105 if ($iblockIdOrigin !== null)
106 {
107 $iblockIdOrigin = (int)$iblockIdOrigin;
108 }
109
110 if ($iblockIdOrigin && $iblockIdOrigin !== $iblockId)
111 {
112 $r->addError(
113 new Error(
114 sprintf(
115 'Product - %d is not exists in catalog - %d', $productId , $iblockIdOrigin
116 )
117 )
118 );
119 }
120
121 return $r;
122 }
123
124 protected function processBeforeAdd(Engine\Action $action): Result
125 {
126 return new Result();
127 }
128
129 //region Actions
130 public function getFieldsByFilterAction($filter): ?array
131 {
133 $view = $this->getViewManager()
134 ->getView($this);
135 $r = $view->getFieldsByFilter($filter);
136
137 if(!$r->isSuccess())
138 {
139 $this->addErrors($r->getErrors());
140 return null;
141 }
142 else
143 {
144 return [$this->getServiceItemName() =>$view->prepareFieldInfos(
145 $r->getData()
146 )];
147 }
148 }
149
150 static protected function perfGetList(array $select, array $filter, array $order, $pageNavigation = null): array
151 {
152 $rawRows = [];
153 $elementIds = [];
154
155 $rsData = \CIBlockElement::GetList(
156 $order,
157 $filter,
158 false,
159 $pageNavigation ?? false,
160 array('ID', 'IBLOCK_ID')
161 );
162 while($row = $rsData->Fetch())
163 {
164 $rawRows[$row['ID']] = $row;
165 $elementIds[] = $row['ID'];
166 }
167
168 foreach (array_chunk($elementIds, \IRestService::LIST_LIMIT) as $pageIds)
169 {
170 $elementFilter = [
171 'IBLOCK_ID' => $filter['IBLOCK_ID'],
172 'ID' => $pageIds,
173 ];
174 $iterator = \CIBlockElement::GetList([], $elementFilter, false, false, $select);
175 while ($row = $iterator->Fetch())
176 {
177 $rawRows[$row['ID']] += $row;
178 }
179 }
180
181 return $rawRows;
182 }
183
191 public function listAction(PageNavigation $pageNavigation, array $select = [], array $filter = [], array $order = []): ?Page
192 {
193 $r = $this->checkPermissionIBlockElementList($filter['IBLOCK_ID']);
194 if($r->isSuccess())
195 {
196 $result = [];
197
198 $select = empty($select)? array_merge(['*'], $this->getAllowedFieldsProduct()):$select;
199 $order = empty($order)? ['ID'=>'ASC']:$order;
200
201 $groupFields = $this->splitFieldsByEntity(
202 array_flip($select)
203 );
204 $allProperties = isset($groupFields['elementFields']['PROPERTY_*']);
205 if ($allProperties)
206 {
207 unset($groupFields['elementFields']['PROPERTY_*']);
208 }
209
210 $productFields = array_keys($groupFields['productFields']);
211 $elementFields = array_keys($groupFields['elementFields']);
212 $propertyFields = $groupFields['propertyFields'];
213
214 $propertyFields = $this->preparePropertyFields($propertyFields);
215 $propertyIds = array_keys($propertyFields);
216 $list = self::perfGetList(array_merge($productFields, $elementFields), $filter, $order, self::getNavData($pageNavigation->getOffset()));
217
218 if (!empty($list))
219 {
220 if ($allProperties || !empty($propertyIds))
221 {
222 $this->attachPropertyValues($list, (int)$filter['IBLOCK_ID'], $propertyIds);
223 }
224
225 foreach ($list as $row)
226 {
227 $result[] = $row;
228 }
229 }
230
231 return new Page($this->getServiceListName(), $result, function() use ($filter)
232 {
233 return (int)\CIBlockElement::GetList([], $filter, []);
234 });
235 }
236 else
237 {
238 $this->addErrors($r->getErrors());
239 return null;
240 }
241 }
242
243 public function getAction($id)
244 {
245 $r = $this->checkPermissionIBlockElementGet($id);
246 if($r->isSuccess())
247 {
248 $r = $this->exists($id);
249 if($r->isSuccess())
250 {
251 return [$this->getServiceItemName() => $this->get($id)];
252 }
253 }
254
255 if($r->isSuccess() === false)
256 {
257 $this->addErrors($r->getErrors());
258 return null;
259 }
260 }
261
262 public function addAction(array $fields): ?array
263 {
264 $r = $this->checkPermissionAdd($fields['IBLOCK_ID']);
265 if($r->isSuccess())
266 {
267 if (isset($fields['IBLOCK_SECTION_ID']) && (int)$fields['IBLOCK_SECTION_ID'] > 0)
268 {
269 $r = $this->checkPermissionIBlockElementSectionBindUpdate($fields['IBLOCK_SECTION_ID']);
270 }
271 }
272
273 if($r->isSuccess())
274 {
275 $id = 0;
276 $element = new \CIBlockElement();
277
278 $r = $this->addValidate($fields);
279 if($r->isSuccess())
280 {
281 $groupFields = $this->splitFieldsByEntity($fields);
282
283 $productFields = $groupFields['productFields'];
284 $propertyFields = $groupFields['propertyFields'];
285 $elementFields = $groupFields['elementFields'];
286
287 $productFields = $this->prepareProductFields($productFields);
288 $propertyFields = $this->preparePropertyFields($propertyFields);
289 $elementFieldsAdd = count($propertyFields)>0 ? array_merge($elementFields, ['PROPERTY_VALUES'=>$propertyFields]):$elementFields;
290
291 $id = $element->Add($elementFieldsAdd);
292 if($element->LAST_ERROR<>'')
293 {
294 $r->addError(new Error($element->LAST_ERROR));
295 }
296 else
297 {
298 $productFields['ID'] = $id;
299
300 $r = \Bitrix\Catalog\Model\Product::add($productFields);
301 if($r->isSuccess() === false)
302 {
303 $element::Delete($id);
304 }
305 }
306 }
307 }
308
309 if(!$r->isSuccess())
310 {
311 $this->addErrors($r->getErrors());
312 return null;
313 }
314 else
315 {
316 return ['ELEMENT'=>$this->get($id)];
317 }
318 }
319
320 public function updateAction(int $id, array $fields): ?array
321 {
322 $fields['IBLOCK_ID'] ??= $this->getProductIblockId($id);
323 $r = $this->checkPermissionUpdate($id);
324 if($r->isSuccess())
325 {
326 if (isset($fields['IBLOCK_SECTION_ID']) && (int)$fields['IBLOCK_SECTION_ID'] > 0)
327 {
328 $r = $this->checkPermissionIBlockElementSectionBindUpdate($fields['IBLOCK_SECTION_ID']);
329 }
330 }
331
332 if($r->isSuccess())
333 {
334 $element = new \CIBlockElement();
335
336 $groupFields = $this->splitFieldsByEntity($fields);
337
338 $productFields = $groupFields['productFields'];
339 $propertyFields = $groupFields['propertyFields'];
340 $elementFields = $groupFields['elementFields'];
341
342 $productFields = $this->prepareProductFields($productFields);
343 $propertyFields = $this->preparePropertyFields($propertyFields);
344
345 $propertyFields = $this->fillPropertyFieldsDefaultPropertyValues($id, $fields['IBLOCK_ID'], $propertyFields);
346 $propertyFields = $this->preparePropertyFieldsUpdate($propertyFields);
347
348 $elementFieldsUpdate = count($propertyFields)>0 ? array_merge($elementFields, ['PROPERTY_VALUES'=>$propertyFields]):$elementFields;
349
350 $r = $this->exists($id);
351 if($r->isSuccess())
352 {
353 $r = $this->updateValidate($elementFieldsUpdate+['ID'=>$id]);
354 if($r->isSuccess())
355 {
356 $element->Update($id, $elementFieldsUpdate);
357 if($element->LAST_ERROR<>'')
358 {
359 $r->addError(new Error($element->LAST_ERROR));
360 }
361 elseif (!empty($productFields))
362 {
363 $r = \Bitrix\Catalog\Model\Product::update($id, $productFields);
364 }
365 }
366 }
367 }
368
369 if($r->isSuccess())
370 {
371 return ['ELEMENT'=>$this->get($id)];
372 }
373 else
374 {
375 $this->addErrors($r->getErrors());
376 return null;
377 }
378 }
379
380 public function deleteAction(int $id): ?bool
381 {
382 $r = $this->checkPermissionDelete($id);
383 if($r->isSuccess())
384 {
385 $r = $this->exists($id);
386 }
387 if($r->isSuccess())
388 {
389 if (!\CIBlockElement::Delete($id))
390 {
391 if ($ex = self::getApplication()->GetException())
392 $r->addError(new Error($ex->GetString(), $ex->GetId()));
393 else
394 $r->addError(new Error('delete iBlockElement error'));
395 }
396 }
397
398 if($r->isSuccess())
399 {
400 return true;
401 }
402 else
403 {
404 $this->addErrors($r->getErrors());
405 return null;
406 }
407 }
408
409 public function downloadAction(array $fields): ?Engine\Response\BFile
410 {
411 $productId = $fields['PRODUCT_ID'];
412 $fieldName = $fields['FIELD_NAME'];
413 $id = $fields['FILE_ID'];
414 $file = [];
415
416 $r = $this->exists($productId);
417 if($r->isSuccess())
418 {
419 $iblockId = $this->get($productId)['IBLOCK_ID'];
420
421 if($this->checkFieldsDownload(['NAME'=>$fieldName, 'IBLOCK_ID'=>$iblockId]) == true)
422 {
423 $files = [];
424 $iBlock = \CIBlock::GetArrayByID($iblockId);
425
426 if ($productId > 0)
427 {
428 $element = \CIBlockElement::GetList(
429 array(),
430 array(
431 "CATALOG_ID" => $iBlock["ID"],
432 "=ID" => $productId,
433 "CHECK_PERMISSIONS" => "N",
434 ),
435 false,
436 false,
437 array("ID", $fieldName)
438 );
439 while ($res = $element->GetNext())
440 {
441 if (isset($res[$fieldName]))
442 {
443 $files[] = $res[$fieldName];
444 }
445 elseif (isset($res[$fieldName."_VALUE"]))
446 {
447 if (is_array($res[$fieldName."_VALUE"]))
448 {
449 $files = array_merge($files, $res[$fieldName."_VALUE"]);
450 }
451 else
452 {
453 $files[] = $res[$fieldName."_VALUE"];
454 }
455 }
456 }
457 }
458
459 if (!in_array($id, $files))
460 {
461 $r->addError(new Error('Product file wrong'));
462 }
463 else
464 {
465 $file = \CFile::GetFileArray($id);
466 if (is_array($file) == false)
467 {
468 $r->addError(new Error('Product is empty'));
469 }
470 }
471 }
472 else
473 {
474 $r->addError(new Error('Name file field is not available'));
475 }
476 }
477
478 if($r->isSuccess())
479 {
480 return \Bitrix\Main\Engine\Response\BFile::createByFileId($file['ID']);
481 }
482 else
483 {
484 $this->addErrors($r->getErrors());
485 return null;
486 }
487 }
488 //endregion Actions
489
490 protected function getEntityTable()
491 {
492 return \Bitrix\Catalog\Model\Product::getTabletClassName();
493 }
494
495 protected function splitFieldsByEntity($fields): array
496 {
497 $productFields = [];
498 $elementFields = [];
499 $propertyFields = [];
500
501 foreach($fields as $name=>$value)
502 {
503 if(in_array($name, $this->getAllowedFieldsProduct()))
504 {
505 $productFields[$name] = $value;
506 }
507 else
508 {
509 if (preg_match('/^(PROPERTY_\d+)$/', $name))
510 {
511 $propertyFields[$name] = $value;
512 }
513 else
514 {
515 $elementFields[$name] = $value;
516 }
517 }
518 }
519
520 return [
521 'productFields'=>$productFields,
522 'propertyFields'=>$propertyFields,
523 'elementFields'=>$elementFields
524 ];
525 }
526
527 protected function prepareProductFields(array $fields): array
528 {
529 $result = $fields;
530
531 if (UseStore::isUsed())
532 {
533 unset($result['QUANTITY_TRACE']);
534 }
535
536 return $result;
537 }
538
539 protected function preparePropertyFields($fields)
540 {
541 $result = [];
542 $matches = [];
543
544 foreach($fields as $name=>$value)
545 {
546 if (preg_match('/^(PROPERTY_)(\d+)$/', $name, $matches))
547 {
548 $result[$matches[2]] = $value;
549 }
550 }
551 return $result;
552 }
553
554 protected function preparePropertyFieldsUpdate($fields): array
555 {
556 $result = [];
557
558 if(count($fields)>0)
559 {
560 foreach ($fields as $propertyId=>$value)
561 {
562 $property = [];
563 // single
564 if(isset($value['VALUE']))
565 {
566 if(isset($value['VALUE_ID']))
567 {
568 //update
569 $valueId=$value['VALUE_ID'];
570 unset($value['VALUE_ID']);
571 $property[$valueId]=$value;
572
573 }
574 else
575 {
576 //replace
577 $property[]=$value;
578 }
579 }
580 // multi
581 else
582 {
583 if(is_array($value) && count($value)>0)
584 {
585 foreach ($value as $item)
586 {
587 if(isset($item['VALUE_ID']))
588 {
589 //update
590 $valueId = $item['VALUE_ID'];
591 unset($item['VALUE_ID']);
592 $property[$valueId]=$item;
593 }
594 else
595 {
596 //replace
597 $property[]=$item;
598 }
599 }
600 }
601 }
602
603 if(count($property)>0)
604 {
605 $result[$propertyId]=$property;
606 }
607 }
608 }
609 return $result;
610 }
611
612 protected function fillPropertyFieldsDefaultPropertyValues($id, $iblockId, $propertyValues)
613 {
614 $fields = $propertyValues;
615
616 if ($id > 0 && $iblockId > 0 && !empty($propertyValues))
617 {
618 $r = \CIBlockElement::GetProperty(
619 $iblockId,
620 $id,
621 'SORT',
622 'ASC',
623 [
624 'CHECK_PERMISSIONS' => 'N',
625 ]
626 );
627 while ($property = $r->Fetch())
628 {
629 if (
630 $property['PROPERTY_TYPE'] !== Iblock\PropertyTable::TYPE_FILE
631 && !array_key_exists($property['ID'], $propertyValues)
632 )
633 {
634 $fields[$property['ID']] ??= [];
635
636 $fields[$property['ID']][] = [
637 'VALUE_ID' => $property['PROPERTY_VALUE_ID'],
638 'VALUE' => $property['VALUE'],
639 'DESCRIPTION' => $property['DESCRIPTION'],
640 ];
641 }
642 }
643 unset($property, $r);
644 }
645
646 return $fields;
647 }
648
649 protected function exists($id)
650 {
651 $r = new Result();
652 if (isset($this->get($id)['ID']) == false)
653 {
654 $r->addError(new Error('Product is not exists'));
655 }
656
657 return $r;
658 }
659
660 protected function get($id)
661 {
662 $row = \CIBlockElement::getList(
663 [],
664 ['ID' => $id],
665 false,
666 false,
667 [
668 '*',
669 ...$this->getAllowedFieldsProduct()
670 ]
671 )->fetch();
672
673 if (!$row)
674 {
675 return [];
676 }
677
678 $result = [
679 $row['ID'] => $row,
680 ];
681
682 $this->attachPropertyValues($result, (int)$row['IBLOCK_ID']);
683
684 return $result[$row['ID']];
685 }
686
687 protected function addValidate($fields)
688 {
689 return $this->checkFields($fields);
690 }
691
692 protected function updateValidate($fields)
693 {
694 return $this->checkFields($fields);
695 }
696
697 protected function checkFields($fields)
698 {
699 $r = new Result();
700
701 if (isset($fields['SECTION_ID']))
702 {
703 $section = \CIBlockSection::GetByID($fields['SECTION_ID'])->Fetch();
704 if (!isset($section['ID']))
705 {
706 $r->addError(new Error('Section is not exists'));
707 }
708 }
709 if (isset($fields['MODIFIED_BY']))
710 {
711 $user = \CUser::GetByID($fields['MODIFIED_BY'])->Fetch();
712 if (!isset($user['ID']))
713 {
714 $r->addError(new Error('User modifiedBy is not exists'));
715 }
716 }
717 if (isset($fields['CREATED_BY']))
718 {
719 $user = \CUser::GetByID($fields['CREATED_BY'])->Fetch();
720 if (!isset($user['ID']))
721 {
722 $r->addError(new Error('User createdBy is not exists'));
723 }
724 }
725 if (isset($fields['PURCHASING_CURRENCY']))
726 {
727 $currency = \CCurrency::GetByID($fields['PURCHASING_CURRENCY']);
728 if (!isset($currency['CURRENCY']))
729 {
730 $r->addError(new Error('Currency purchasingCurrency is not exists'));
731 }
732 }
733 if (isset($fields['VAT_ID']))
734 {
735 $user = \CCatalogVat::GetByID($fields['VAT_ID'])->Fetch();
736 if (!isset($user['ID']))
737 {
738 $r->addError(new Error('VAT vatId is not exists'));
739 }
740 }
741
742 return $r;
743 }
744
751 protected function attachPropertyValues(array &$result, int $iblockId, array $propertyIds = []): void
752 {
753 if ($iblockId <= 0)
754 {
755 return;
756 }
757
758 $propertyFilter = !empty($propertyIds) ? ['ID' => $propertyIds] : [];
759
760 $propertyValues = [];
761 \CIBlockElement::getPropertyValuesArray(
762 $propertyValues,
763 $iblockId,
764 ['ID' => array_keys($result)],
765 $propertyFilter,
766 ['USE_PROPERTY_ID' => 'Y']
767 );
768
769 foreach ($result as $k => $v)
770 {
771 if (isset($propertyValues[$k]))
772 {
773 foreach ($propertyValues[$k] as $propId => $fields)
774 {
775 $value = null;
776
777 if (isset($fields['PROPERTY_VALUE_ID']))
778 {
779 if ($fields['PROPERTY_TYPE'] === Iblock\PropertyTable::TYPE_LIST)
780 {
781 if ($fields['MULTIPLE'] === 'Y')
782 {
783 if (is_array($fields['PROPERTY_VALUE_ID']))
784 {
785 foreach ($fields['PROPERTY_VALUE_ID'] as $i => $item)
786 {
787 $value[] = [
788 'VALUE' => $fields['VALUE_ENUM_ID'][$i],
789 'VALUE_ENUM' => $fields['VALUE_ENUM'][$i],
790 'VALUE_ID' => $fields['PROPERTY_VALUE_ID'][$i],
791 ];
792 }
793 }
794 }
795 else
796 {
797 $value = [
798 'VALUE' => $fields['VALUE_ENUM_ID'],
799 'VALUE_ENUM' => $fields['VALUE_ENUM'],
800 'VALUE_ID' => $fields['PROPERTY_VALUE_ID']
801 ];
802 }
803 }
804 else
805 {
806 if ($fields['MULTIPLE'] === 'Y')
807 {
808 if (is_array($fields['PROPERTY_VALUE_ID']))
809 {
810 foreach ($fields['PROPERTY_VALUE_ID'] as $i => $item)
811 {
812 $value[] = [
813 'VALUE' => $fields['VALUE'][$i],
814 'VALUE_ID' => $fields['PROPERTY_VALUE_ID'][$i]
815 ];
816 }
817 }
818 }
819 else
820 {
821 $value = [
822 'VALUE' => $fields['VALUE'],
823 'VALUE_ID' => $fields['PROPERTY_VALUE_ID']
824 ];
825 }
826 }
827 }
828
829 $result[$k]['PROPERTY_' . $propId] = $value;
830 }
831 }
832 elseif (!empty($propertyIds))
833 {
838 foreach ($propertyIds as $propId)
839 {
840 $result[$k]['PROPERTY_' . $propId] = null;
841 }
842 }
843 }
844 }
845
846 protected function checkPermissionEntity($name, $arguments=[])
847 {
848 $name = mb_strtolower($name); //for ajax mode
849
850 if($name == 'getfieldsbyfilter'
851 || $name == 'download'
852 )
853 {
854 $r = $this->checkReadPermissionEntity();
855 }
856 else
857 {
858 $r = parent::checkPermissionEntity($name);
859 }
860
861 return $r;
862 }
863
867 protected function getAllowedFieldsProduct(): array
868 {
869 $result = [
870 'TYPE',
871 'AVAILABLE',
872 'BUNDLE',
873 'QUANTITY',
874 'QUANTITY_RESERVED',
875 'QUANTITY_TRACE',
876 'CAN_BUY_ZERO',
877 'SUBSCRIBE',
878 'VAT_ID',
879 'VAT_INCLUDED',
880 'BARCODE_MULTI',
881 'WEIGHT',
882 'LENGTH',
883 'WIDTH',
884 'HEIGHT',
885 'MEASURE',
886 'RECUR_SCHEME_LENGTH',
887 'RECUR_SCHEME_TYPE',
888 'TRIAL_PRICE_ID',
889 'WITHOUT_ORDER',
890 'QUANTITY_TRACE_RAW',
891 'PAYMENT_TYPE',
892 'SUBSCRIBE_RAW',
893 'CAN_BUY_ZERO_RAW'
894 ];
895
896 if ($this->accessController->check(ActionDictionary::ACTION_PRODUCT_PURCHASE_INFO_VIEW))
897 {
898 array_push($result, 'PURCHASING_PRICE', 'PURCHASING_CURRENCY');
899 }
900
901 return $result;
902 }
903
904 protected function checkFieldsDownload($fields)
905 {
906 $name = $fields['NAME'];
907 $iblockId = $fields['IBLOCK_ID'];
908
909 if ($name === "DETAIL_PICTURE")
910 return true;
911 elseif ($name === "PREVIEW_PICTURE")
912 return true;
913 elseif ($name === "PICTURE")
914 return true;
915 elseif (!preg_match("/^PROPERTY_(.+)\$/", $name, $match))
916 return false;
917 else
918 {
919 $db_prop = \CIBlockProperty::GetPropertyArray($match[1], $iblockId);
920 if(is_array($db_prop) && $db_prop["PROPERTY_TYPE"] === "F")
921 return true;
922 }
923 return false;
924 }
925
926 public function addPropertyAction($fields)
927 {
928 $r = $this->checkPermissionIBlockModify($fields['IBLOCK_ID']);
929 if(!$r->isSuccess())
930 {
931 $this->addErrors($r->getErrors());
932 return null;
933 }
934
935 $iblockProperty = new \CIBlockProperty();
936
937 $propertyFields = array(
938 'ACTIVE' => 'Y',
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',
946 );
947
948 $newID = (int)($iblockProperty->Add($propertyFields));
949 if ($newID === 0)
950 {
951 $this->addError(new \Bitrix\Main\Error($iblockProperty->LAST_ERROR));
952 return null;
953 }
954
955 return [
956 'ID' => $newID,
957 'CONTROL_ID' => 'PROPERTY_'.$newID
958 ];
959 }
960
961 //region checkPermissionController
962 protected function checkModifyPermissionEntity()
963 {
964 return $this->checkReadPermissionEntity();
965 }
966
967 protected function checkReadPermissionEntity()
968 {
969 $r = new Result();
970
971 if (
972 !$this->accessController->check(ActionDictionary::ACTION_CATALOG_READ)
973 && !$this->accessController->check(ActionDictionary::ACTION_PRICE_EDIT)
974 && !$this->accessController->check(ActionDictionary::ACTION_CATALOG_VIEW)
975 )
976 {
977 $r->addError(new Error('Access Denied', 200040300010));
978 }
979 return $r;
980 }
981 //endregion checkPermissionController
982
983 //region checkPermissionIBlock
984 protected function existsIblock(int $iblockId): Result
985 {
986 $result = new Result();
987
988 $arIBlock = \CIBlock::GetArrayByID($iblockId, 'NAME');
989 if (empty($arIBlock))
990 {
991 $result->addError(new Error('Iblock Not Found', 200040300000));
992 }
993
994 return $result;
995 }
996
997 protected function checkPermissionAdd(int $iblockId): Result
998 {
999 $result = new Result();
1000
1001 $result->addErrors(
1002 $this->checkPermissionIBlockElementAdd($iblockId)->getErrors()
1003 );
1004 $result->addErrors(
1006 );
1007
1008 return $result;
1009 }
1010
1012 {
1013 $result = new Result();
1014
1015 if (!$this->accessController->check(ActionDictionary::ACTION_PRODUCT_ADD))
1016 {
1017 $result->addError(new Error('Access Denied', 200040300040));
1018 }
1019
1020 return $result;
1021 }
1022
1023 protected function checkPermissionIBlockElementAdd(int $iblockId): Result
1024 {
1025 //return $this->checkPermissionIBlockElementList($iblockId);
1026 return $this->checkPermissionIBlockElementModify($iblockId, 0);
1027 }
1028
1029 protected function checkPermissionUpdate(int $elementId): Result
1030 {
1031 $result = new Result();
1032
1033 $result->addErrors(
1034 $this->checkPermissionIBlockElementUpdate($elementId)->getErrors()
1035 );
1036 $result->addErrors(
1038 );
1039
1040 return $result;
1041 }
1042
1043 protected function checkPermissionCatalogProductUpdate(int $elementId): Result
1044 {
1045 $result = new Result();
1046
1047 if (!$this->accessController->check(ActionDictionary::ACTION_PRODUCT_EDIT))
1048 {
1049 $result->addError(new Error('Access Denied', 200040300040));
1050 }
1051
1052 return $result;
1053 }
1054
1055 protected function checkPermissionIBlockElementUpdate(int $elementId): Result
1056 {
1057 $iblockId = \CIBlockElement::GetIBlockByID($elementId);
1058
1059 return $this->checkPermissionIBlockElementModify($iblockId, $elementId);
1060 }
1061
1062 protected function checkPermissionIBlockModify($iblockId): Result
1063 {
1064 $iblockId = (int)$iblockId;
1065
1066 $r = $this->existsIblock($iblockId);
1067 if (!$r->isSuccess())
1068 {
1069 return $r;
1070 }
1071
1072 if (!\CIBlockRights::UserHasRightTo($iblockId, $iblockId, self::IBLOCK_EDIT))
1073 {
1074 $r->addError(new Error('Access Denied', 200040300040));
1075 }
1076
1077 return $r;
1078 }
1079
1080 protected function checkPermissionIBlockElementModify($iblockId, $elementId): Result
1081 {
1082 $iblockId = (int)$iblockId;
1083
1084 $r = $this->existsIblock($iblockId);
1085 if (!$r->isSuccess())
1086 {
1087 return $r;
1088 }
1089
1090 if ($elementId > 0)
1091 {
1092 $bBadBlock = !\CIBlockElementRights::UserHasRightTo($iblockId, $elementId, self::IBLOCK_ELEMENT_EDIT); //access edit
1093 }
1094 else
1095 {
1096 $bBadBlock = !\CIBlockRights::UserHasRightTo($iblockId, $iblockId, self::IBLOCK_ELEMENT_EDIT);
1097 }
1098
1099 if($bBadBlock)
1100 {
1101 $r->addError(new Error('Access Denied', 200040300043));
1102 }
1103
1104 return $r;
1105 }
1106
1107 protected function checkPermissionDelete(int $elementId): Result
1108 {
1109 $result = new Result();
1110
1111 $result->addErrors(
1112 $this->checkPermissionIBlockElementDelete($elementId)->getErrors()
1113 );
1114 $result->addErrors(
1116 );
1117
1118 return $result;
1119 }
1120
1121 protected function checkPermissionCatalogProductDelete(int $elementId): Result
1122 {
1123 $result = new Result();
1124
1125 if (!$this->accessController->check(ActionDictionary::ACTION_PRODUCT_DELETE))
1126 {
1127 $result->addError(new Error('Access Denied', 200040300040));
1128 }
1129
1130 return $result;
1131 }
1132
1133 protected function checkPermissionIBlockElementDelete(int $elementId): Result
1134 {
1135 $iblockId = (int)\CIBlockElement::GetIBlockByID($elementId);
1136
1137 $r = $this->existsIblock($iblockId);
1138 if (!$r->isSuccess())
1139 {
1140 return $r;
1141 }
1142
1143 if (!\CIBlockElementRights::UserHasRightTo($iblockId, $elementId, self::IBLOCK_ELEMENT_DELETE)) //access delete
1144 {
1145 $r->addError(new Error('Access Denied', 200040300040));
1146 }
1147
1148 return $r;
1149 }
1150
1151 protected function checkPermissionIBlockElementGet($elementId): Result
1152 {
1153 $iblockId = (int)\CIBlockElement::GetIBlockByID($elementId);
1154 $r = $this->existsIblock($iblockId);
1155 if (!$r->isSuccess())
1156 {
1157 return $r;
1158 }
1159
1160 if (!\CIBlockElementRights::UserHasRightTo($iblockId, $elementId, self::IBLOCK_ELEMENT_READ)) //access read
1161 {
1162 $r->addError(new Error('Access Denied', 200040300040));
1163 }
1164
1165 return $r;
1166 }
1167
1168 protected function checkPermissionIBlockElementList($iblockId): Result
1169 {
1170 $iblockId = (int)$iblockId;
1171 $r = $this->existsIblock($iblockId);
1172 if (!$r->isSuccess())
1173 {
1174 return $r;
1175 }
1176
1177 if (!\CIBlockRights::UserHasRightTo($iblockId, $iblockId, self::IBLOCK_READ))
1178 {
1179 $r->addError(new Error('Access Denied', 200040300030));
1180 }
1181
1182 return $r;
1183 }
1184
1185 protected function checkPermissionIBlockElementSectionBindModify($iblockId, $iblockSectionId): Result
1186 {
1187 $iblockId = (int)$iblockId;
1188 $r = $this->existsIblock($iblockId);
1189 if (!$r->isSuccess())
1190 {
1191 return $r;
1192 }
1193
1194 if (!\CIBlockSectionRights::UserHasRightTo(
1195 $iblockId,
1196 $iblockSectionId,
1197 self::IBLOCK_ELEMENT_SECTION_BIND
1198 )) //access update
1199 {
1200 $r->addError(new Error('Access Denied', 200040300050));
1201 }
1202
1203 return $r;
1204 }
1205
1206 protected function checkPermissionIBlockElementSectionBindUpdate($iblockSectionId): Result
1207 {
1208 $iblockId = $this->getIBlockBySectionId($iblockSectionId);
1209
1210 return $this->checkPermissionIBlockElementSectionBindModify($iblockId, $iblockSectionId);
1211 }
1212
1213 protected function getIBlockBySectionId($id): int
1214 {
1215 $section = \CIBlockSection::GetList(
1216 [],
1217 [
1218 'ID' => (int)$id,
1219 ],
1220 false,
1221 [
1222 'ID',
1223 'IBLOCK_ID',
1224 ]
1225 );
1226 $res = $section->Fetch();
1227 unset($section);
1228
1229 return (int)($res['IBLOCK_ID'] ?? 0);
1230 }
1231 //endregion
1232
1233 // rest-event region
1237 public static function getCallbackRestEvent(): array
1238 {
1239 return [self::class, 'processItemEvent'];
1240 }
1241
1242 public static function processItemEvent(array $arParams, array $arHandler): array
1243 {
1244 $id = null;
1245 $event = $arParams[0] ?? null;
1246
1247 if (!$event)
1248 {
1249 throw new RestException('event object not found trying to process event');
1250 }
1251
1252 if($event instanceof Event) // update, add
1253 {
1254 $id = $event->getParameter('id');
1255 }
1256 else if($event instanceof \Bitrix\Main\ORM\Event) // delete
1257 {
1258 $item = $event->getParameter('id');
1259 $id = is_array($item) ? $item['ID']: $item;
1260 }
1261
1262 if (!$id)
1263 {
1264 throw new RestException('id not found trying to process event');
1265 }
1266
1267 $product = \Bitrix\Catalog\Model\Product::getCacheItem($id);
1268
1269 $type = $product['TYPE'] ?? null;
1270
1271 if (!$type)
1272 {
1273 throw new RestException('type is not specified trying to process event');
1274 }
1275
1276 return [
1277 'FIELDS' => [
1278 'ID' => $id,
1279 'TYPE' => $type
1280 ],
1281 ];
1282 }
1283
1284 protected static function getBindings(): array
1285 {
1286 $entity = (new static())->getEntity();
1287 $class = $entity->getNamespace() . $entity->getName();
1288 $model = \Bitrix\Catalog\Model\Product::class;
1289
1290 return [
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',
1294 ];
1295 }
1296 // endregion
1297
1298 // region Internal tools
1299
1306 protected static function getProductIblockId(int $productId): ?int
1307 {
1308 $iblockId = \CIBlockElement::GetIBlockByID($productId);
1309
1310 return
1311 $iblockId === false
1312 ? null
1313 : $iblockId
1314 ;
1315 }
1316
1317 // endRegion
1318}
checkPermissionIBlockElementModify($iblockId, $elementId)
Definition product.php:1080
checkPermissionIBlockElementGet($elementId)
Definition product.php:1151
checkPermissionCatalogProductDelete(int $elementId)
Definition product.php:1121
attachPropertyValues(array &$result, int $iblockId, array $propertyIds=[])
Definition product.php:751
processBeforeAdd(Engine\Action $action)
Definition product.php:124
checkPermissionIBlockElementAdd(int $iblockId)
Definition product.php:1023
processBeforeAction(Engine\Action $action)
Definition product.php:42
processBeforeUpdate(Engine\Action $action)
Definition product.php:94
processAfterAction(Engine\Action $action, $result)
Definition product.php:78
checkPermissionIBlockElementUpdate(int $elementId)
Definition product.php:1055
updateAction(int $id, array $fields)
Definition product.php:320
listAction(PageNavigation $pageNavigation, array $select=[], array $filter=[], array $order=[])
Definition product.php:191
fillPropertyFieldsDefaultPropertyValues($id, $iblockId, $propertyValues)
Definition product.php:612
checkPermissionIBlockElementDelete(int $elementId)
Definition product.php:1133
prepareProductFields(array $fields)
Definition product.php:527
checkPermissionCatalogProductUpdate(int $elementId)
Definition product.php:1043
static processItemEvent(array $arParams, array $arHandler)
Definition product.php:1242
checkPermissionIBlockElementSectionBindUpdate($iblockSectionId)
Definition product.php:1206
checkPermissionEntity($name, $arguments=[])
Definition product.php:846
checkPermissionDelete(int $elementId)
Definition product.php:1107
checkPermissionUpdate(int $elementId)
Definition product.php:1029
checkPermissionIBlockElementSectionBindModify($iblockId, $iblockSectionId)
Definition product.php:1185
static getProductIblockId(int $productId)
Definition product.php:1306
static perfGetList(array $select, array $filter, array $order, $pageNavigation=null)
Definition product.php:150