Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
BasketItem.php
1<?php
2
4
20
22{
23 private const DISCOUNT_TYPE_MONETARY = 1;
24 private const DISCOUNT_TYPE_PERCENTAGE = 2;
25 private const BRAND_PROPERTY_CODE = 'BRAND_FOR_FACEBOOK';
26
27 private $fields;
28 private $detailUrlType;
29 private $id;
30 private $priceGroupId;
31
33 private $sku;
34
36 private $priceItem;
37
38 public function __construct()
39 {
40 $this->id = uniqid('', true);
41 $this->fields = [
42 'innerId' => $this->id,
43 'productId' => 0,
44 'skuId' => 0,
45 'type' => null,
46 'code' => '',
47 'name' => '',
48 'sort' => 0,
49 'module' => '',
50 'catalogPrice' => null,
51 'basePrice' => 0,
52 'price' => 0,
53 'priceExclusive' => 0,
54 'isCustomPrice' => 'Y',
55 'discountType' => self::DISCOUNT_TYPE_PERCENTAGE,
56 'quantity' => 1,
57 'measureCode' => 0,
58 'measureName' => '',
59 'measureRatio' => 1,
60 'discountRate' => 0,
61 'discount' => 0,
62 'taxId' => 0,
63 'taxIncluded' => 'N',
64 'additionalFields' => [],
65 'properties' => [],
66 'brands' => '',
67 'weight' => 0,
68 'dimensions' => [],
69 ];
70
72
73 $basePriceGroup = \CCatalogGroup::GetBaseGroup();
74 if ($basePriceGroup)
75 {
76 $this->setPriceGroupId((int)$basePriceGroup['ID']);
77 }
78 }
79
80 private function getField($name)
81 {
82 return $this->fields[$name] ?? '';
83 }
84
85 private function getEncodedSkuTree(): string
86 {
87 if (!$this->sku || $this->sku->isSimple())
88 {
89 return '';
90 }
91
93 $product = $this->sku->getParent();
94 $skuTree = ServiceContainer::make('sku.tree', ['iblockId' => $product->getIblockId()]);
95
96 if (!$skuTree)
97 {
98 return '';
99 }
100
101 $skuTreeItems = $skuTree->loadJsonOffers([
102 $product->getId() => $this->sku->getId(),
103 ]);
104
105 if (!$skuTreeItems[$product->getId()][$this->sku->getId()])
106 {
107 return '';
108 }
109
110 return Json::encode($skuTreeItems[$product->getId()][$this->sku->getId()]);
111 }
112
113 private function getImageInputField(): ?array
114 {
115 if (!$this->sku)
116 {
117 return null;
118 }
119
120 $variationImageField = new ImageInput($this->sku);
121
122 return $variationImageField->getFormattedField();
123 }
124
125 private function getSum(): float
126 {
127 return (float)$this->getField('priceExclusive') * (float)$this->getField('quantity');
128 }
129
130 private function getDetailUrl(): string
131 {
132 if (!$this->sku || $this->sku->isNew())
133 {
134 return '';
135 }
136
137 $parent = $this->sku->getParent();
138 $urlBuilder = BuilderManager::getInstance()->getBuilder($this->detailUrlType);
139 if (!$urlBuilder || !$parent)
140 {
141 return '';
142 }
143
144 $urlBuilder->setIblockId($parent->getIblockId());
145
146 return $urlBuilder->getElementDetailUrl($parent->getId());
147 }
148
149 public function getFields(): array
150 {
151 return $this->fields;
152 }
153
154 public function getId(): string
155 {
156 return $this->id;
157 }
158
159 public function getSkuId(): ?int
160 {
161 if ($this->sku)
162 {
163 return $this->sku->getId();
164 }
165
166 return null;
167 }
168
169 public function getPriceItem(): ?BasePrice
170 {
171 return $this->priceItem;
172 }
173
174 public function setSku(BaseSku $sku): self
175 {
176 $this->sku = $sku;
177 if ($sku->getParent())
178 {
179 $this->fields['productId'] = $sku->getParent()->getId();
180 }
181 $this->fields['skuId'] = $sku->getId();
182 $this->fields['module'] = 'catalog';
183
184 $this->fillFieldsFromSku();
185
186 return $this;
187 }
188
189 public function removeSku(): self
190 {
191 $this->sku = null;
192 $this->priceItem = null;
193 $this->fields['productId'] = '';
194 $this->fields['skuId'] = '';
195 $this->fields['module'] = '';
196 $this->fields['properties'] = [];
197
198 return $this;
199 }
200
201 private function fillFieldsFromSku(): void
202 {
203 $this->setName($this->sku->getName());
204 $this->setType($this->sku->getType());
205 $this->fillProperties();
206 $this->fillBrands();
207 $this->fillMeasureFields();
208 $this->fillTaxFields();
209 $this->fillPriceFields();
210 $this->fillDeliveryFields();
211 }
212
213 private function fillProperties(): void
214 {
215 $properties = [];
216 foreach ($this->sku->getPropertyCollection() as $property)
217 {
218 $formattedValues = $this->getFormattedProperty($property);
219 if ($formattedValues === null)
220 {
221 continue;
222 }
223 $properties[] = $formattedValues;
224 }
225
226 $this->fields['properties'] = $properties;
227 }
228
229 private function fillBrands(): void
230 {
232 $product = $this->sku->getParent();
233 if (!$product)
234 {
235 return;
236 }
237
238 $property = $product->getPropertyCollection()->findByCode(self::BRAND_PROPERTY_CODE);
239 if (!$property)
240 {
241 return;
242 }
243
244 $userType = \CIBlockProperty::GetUserType($property->getUserType());
245 $userTypeMethod = $userType['GetUIEntityEditorProperty'];
246 $propertySettings = $property->getSettings();
247 $propertyValues = $property->getPropertyValueCollection()->getValues();
248 $description = $userTypeMethod($propertySettings, $propertyValues);
249 $propertyBrandItems = $description['data']['items'];
250
251 $selectedBrandItems = [];
252
253 foreach ($propertyBrandItems as $propertyBrandItem)
254 {
255 if (in_array($propertyBrandItem['VALUE'], $propertyValues, true))
256 {
257 $selectedBrandItems[] = $propertyBrandItem;
258 }
259 }
260
261 $this->fields['brands'] = $selectedBrandItems;
262 }
263
264 private function getFormattedProperty(Property $property): ?array
265 {
266 $propertyKeys = array_flip(['ID', 'NAME', 'CODE', 'SORT', 'XML_ID']);
267 $formattedValues = $property->getPropertyValueCollection()->toArray();
268 if (empty($formattedValues))
269 {
270 return null;
271 }
272
273 $enumValueMap = [];
274 if ($property->getPropertyType() === PropertyTable::TYPE_LIST)
275 {
276 $enumIds = array_column($formattedValues, 'VALUE');
277 $enumSettings = PropertyEnumerationTable::getList([
278 'select' => ['ID', 'VALUE'],
279 'filter' => [
280 '=ID' => $enumIds,
281 ],
282 ])
283 ->fetchAll()
284 ;
285
286 $enumValueMap = array_column($enumSettings, 'VALUE', 'ID');
287 }
288
289 $propertySettings = $property->getSettings();
290 foreach ($formattedValues as $propertyValueId => $valueInfo)
291 {
292 $value = $valueInfo['VALUE'];
293
294 if ($property->getPropertyType() === PropertyTable::TYPE_LIST)
295 {
296 $value = $enumValueMap[$value] ?? $value;
297 }
298
299 $displayProperty = array_merge(
300 $propertySettings,
301 [
302 'DESCRIPTION' => $valueInfo['DESCRIPTION'] ?? null,
303 '~DESCRIPTION' => $valueInfo['DESCRIPTION'] ?? null,
304 'VALUE' => $value,
305 '~VALUE' => $value,
306 ]
307 );
308
309 $displayProperty = \CIBlockFormatProperties::GetDisplayValue([], $displayProperty);
310
311 $formattedValues[$propertyValueId]['DISPLAY_VALUE'] = $displayProperty['DISPLAY_VALUE'];
312 }
313
314 $propertySettings = array_intersect_key($propertySettings, $propertyKeys);
315 $propertySettings['PROPERTY_VALUES'] = $formattedValues;
316
317 return $propertySettings;
318 }
319
320 private function fillMeasureFields(): void
321 {
322 $measureId = (int)$this->sku->getField('MEASURE');
323 $filter =
324 $measureId > 0
325 ? ['=ID' => $this->sku->getField('MEASURE')]
326 : ['=IS_DEFAULT' => 'Y']
327 ;
328
329 $measureRow = \CCatalogMeasure::getList(
330 ['CODE' => 'ASC'],
331 $filter,
332 false,
333 ['nTopCount' => 1],
334 ['CODE', 'SYMBOL', 'SYMBOL_INTL']
335 );
336
337 if ($measure = $measureRow->Fetch())
338 {
339 $name = $measure['SYMBOL'] ?? $measure['SYMBOL_INTL'];
340 $this
341 ->setMeasureCode((int)$measure['CODE'])
342 ->setMeasureName($name)
343 ;
344 }
345
346 $ratioItem = $this->sku->getMeasureRatioCollection()->findDefault();
347 if ($ratioItem)
348 {
349 $this->setMeasureRatio((float)$ratioItem->getRatio());
350 }
351 }
352
353 private function fillTaxFields(): void
354 {
355 $taxId = $this->sku->getField('VAT_ID');
356 if (empty($taxId))
357 {
358 $taxId = $this->sku->getIblockInfo()->getVatId();
359 }
360
361 $this
362 ->setTaxId((int)$taxId)
363 ->setTaxIncluded($this->sku->getField('VAT_INCLUDED'))
364 ;
365 }
366
367 private function fillPriceFields(): void
368 {
369 if (!$this->priceGroupId)
370 {
371 return;
372 }
373
374 $this->priceItem = $this->sku->getPriceCollection()->findByGroupId($this->priceGroupId);
375 if ($this->priceItem)
376 {
377 $price = (float)$this->priceItem->getPrice();
378 $this
379 ->setPrice($price)
380 ->setBasePrice($price)
381 ->setPriceExclusive($price)
382 ;
383 }
384 }
385
386 private function fillDeliveryFields(): void
387 {
388 $this->fields['weight'] = $this->sku->getField('WEIGHT');
389
390 $this->fields['dimensions'] = [
391 'LENGTH' => $this->sku->getField('LENGTH'),
392 'WIDTH' => $this->sku->getField('WIDTH'),
393 'HEIGHT' => $this->sku->getField('HEIGHT'),
394 ];
395 }
396
397 private function hasEditRights(): bool
398 {
399 global $USER;
400
401 if (!$this->sku || !$USER instanceof \CUser)
402 {
403 return false;
404 }
405
406 return
407 \CIBlockElementRights::UserHasRightTo($this->sku->getIblockId(), $this->sku->getId(), 'element_edit')
408 && \CIBlockElementRights::UserHasRightTo($this->sku->getIblockId(), $this->sku->getId(), 'element_edit_price')
409 && !AccessController::getCurrent()->check(ActionDictionary::ACTION_PRICE_EDIT)
410 ;
411 }
412
413 public function getCatalogPrice(): ?float
414 {
415 if (!$this->priceItem)
416 {
417 return null;
418 }
419
420 return (float)$this->priceItem->getPrice();
421 }
422
423 public function setQuantity(float $value): self
424 {
425 $this->fields['quantity'] = $value;
426
427 return $this;
428 }
429
430 public function setId(string $value): self
431 {
432 $this->id = $value;
433 $this->fields['innerId'] = $value;
434
435 return $this;
436 }
437
438 public function setName(string $value = null): self
439 {
440 $this->fields['name'] = $value;
441
442 return $this;
443 }
444
445 public function setCode(string $value): self
446 {
447 $this->fields['code'] = $value;
448
449 return $this;
450 }
451
452 public function setType(?int $value): self
453 {
454 $this->fields['type'] = $value;
455
456 return $this;
457 }
458
459 public function setSort(int $value): self
460 {
461 $this->fields['sort'] = $value;
462
463 return $this;
464 }
465
466 public function setDiscountType(int $value): self
467 {
468 $this->fields['discountType'] =
469 $value === self::DISCOUNT_TYPE_MONETARY
470 ? self::DISCOUNT_TYPE_MONETARY
471 : self::DISCOUNT_TYPE_PERCENTAGE;
472
473 return $this;
474 }
475
476 public function setCustomPriceType(string $value = null): self
477 {
478 $this->fields['isCustomPrice'] = ($value === 'N') ? 'N' : 'Y';
479
480 return $this;
481 }
482
483 public function setBasePrice(float $value): self
484 {
485 $this->fields['basePrice'] = $value > 0 ? $value : 0;
486
487 return $this;
488 }
489
490 public function setPrice(float $value): self
491 {
492 $this->fields['price'] = $value > 0 ? $value : 0;
493
494 return $this;
495 }
496
497 public function setPriceExclusive(float $value): self
498 {
499 $this->fields['priceExclusive'] = $value > 0 ? $value : 0;
500
501 return $this;
502 }
503
504 public function setMeasureCode(int $code): self
505 {
506 if ($code > 0)
507 {
508 $this->fields['measureCode'] = $code;
509 }
510
511 return $this;
512 }
513
514 public function setMeasureName($name = null): self
515 {
516 $this->fields['measureName'] = $name;
517
518 return $this;
519 }
520
521 public function setMeasureRatio(float $ratio): self
522 {
523 $this->fields['measureRatio'] = $ratio > 0 ? $ratio : 1;
524
525 return $this;
526 }
527
528 public function setDiscountRate(float $value): self
529 {
530 $this->fields['discountRate'] = $value;
531
532 return $this;
533 }
534
535 public function setDiscountValue(float $value): self
536 {
537 $this->fields['discount'] = $value;
538
539 return $this;
540 }
541
542 public function addAdditionalField(string $name, $value): self
543 {
544 $this->fields['additionalFields'][$name] = $value;
545
546 return $this;
547 }
548
549 public function setTaxIncluded(string $value = null): self
550 {
551 $this->fields['taxIncluded'] = ($value === 'N') ? 'N' : 'Y';
552
553 return $this;
554 }
555
556 public function setTaxId(int $value): self
557 {
558 $this->fields['taxId'] = $value;
559
560 return $this;
561 }
562
563 public function clearAdditionalFields(): self
564 {
565 $this->fields['additionalFields'] = [];
566
567 return $this;
568 }
569
570 public function setPriceGroupId(int $groupId): self
571 {
572 if ($groupId > 0)
573 {
574 $this->priceGroupId = $groupId;
575 }
576
577 return $this;
578 }
579
580 public function setDetailUrlManagerType(string $type): self
581 {
582 $this->detailUrlType = $type;
583
584 return $this;
585 }
586
587 public function getResult(): array
588 {
589 return [
590 'selectorId' => $this->id,
591 'offerId' => $this->sku ? $this->sku->getId() : null,
592 'fields' => $this->fields,
593 'skuTree' => $this->getEncodedSkuTree(),
594 'showDiscount' => !empty($this->getField('discount')) ? 'Y' : 'N',
595 'image' => $this->getImageInputField(),
596 'sum' => $this->getSum(),
597 'catalogPrice' => $this->getCatalogPrice(),
598 'detailUrl' => $this->getDetailUrl(),
599 'discountSum' => $this->getField('discountSum'),
600 'hasEditRights' => $this->hasEditRights(),
601 ];
602 }
603}