Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
entitypropertyvalue.php
1<?php
2
3namespace Bitrix\Sale;
4
6use Bitrix\Main\Entity\ReferenceField;
10use Bitrix\Main;
12
18{
20 protected $property = null;
21
25 abstract protected static function getEntityType(): string;
26
30 abstract protected static function getPropertyClassName(): string;
31
40 abstract protected static function createPropertyValueObject(
41 array $property = null,
42 array $value = [],
43 array $relation = null
45
50 abstract protected static function getOnSavedEventName(): string;
51
52 protected static function extractPaySystemIdList(Entity $entity)
53 {
54 return [];
55 }
56
57 protected static function extractDeliveryIdList(Entity $entity)
58 {
59 return [];
60 }
61
62 protected static function extractTpLandingIdList(Entity $entity) : array
63 {
64 return [];
65 }
66
67 protected static function extractTradingPlatformIdList(Entity $entity): array
68 {
69 return [];
70 }
71
79 protected static function loadFromDb(Entity $entity): array
80 {
81 $propertyValues = [];
82 $propertyValuesMap = [];
83
84 if ($entity->getId() > 0)
85 {
86 $dbRes = static::getList(
87 [
88 'select' => ['ID', 'NAME', 'VALUE', 'CODE', 'ORDER_PROPS_ID'],
89 'filter' => [
90 '=ENTITY_ID' => $entity->getId(),
91 '=ENTITY_TYPE' => static::getEntityType()
92 ]
93 ]
94 );
95 while ($row = $dbRes->fetch())
96 {
97 $propertyValues[$row['ID']] = $row;
98 $propertyValuesMap[$row['ORDER_PROPS_ID']] = $row['ID'];
99 }
100 }
101
103 $propertyClassName = static::getPropertyClassName();
104
105 $getListParams = [
106 'select' => [
107 'ID',
108 'PERSON_TYPE_ID',
109 'NAME',
110 'TYPE',
111 'REQUIRED',
112 'DEFAULT_VALUE',
113 'SORT',
114 'USER_PROPS',
115 'IS_LOCATION',
116 'PROPS_GROUP_ID',
117 'DESCRIPTION',
118 'IS_EMAIL',
119 'IS_PROFILE_NAME',
120 'IS_PAYER',
121 'IS_LOCATION4TAX',
122 'IS_FILTERED',
123 'CODE',
124 'IS_ZIP',
125 'IS_PHONE',
126 'IS_ADDRESS',
127 'IS_ADDRESS_FROM',
128 'IS_ADDRESS_TO',
129 'ACTIVE',
130 'UTIL',
131 'INPUT_FIELD_LOCATION',
132 'MULTIPLE',
133 'SETTINGS',
134 'ENTITY_TYPE'
135 ],
136 'filter' => static::constructPropertyFilter($entity),
137 'runtime' => static::getRelationRuntimeFields(),
138 'order' => ['SORT' => 'ASC'],
139 ];
140
141 $dbRes = $propertyClassName::getList($getListParams);
142 $properties = [];
143 $propRelation = [];
144
145 while ($row = $dbRes->fetch())
146 {
147 $properties[$row['ID']] = $row;
148 $propRelation[$row['ID']] = [];
149 }
150
151 $dbRes = OrderPropsRelationTable::getList(
152 [
153 'select' => [
154 'PROPERTY_ID',
155 'ENTITY_ID',
156 'ENTITY_TYPE'
157 ],
158 'filter' => [
159 'PROPERTY_ID' => array_keys($properties)
160 ]
161 ]
162 );
163
164 while ($row = $dbRes->fetch())
165 {
166 $propRelation[$row['PROPERTY_ID']][] = $row;
167 }
168
169 return [$properties, $propertyValues, $propRelation, $propertyValuesMap];
170 }
171
175 public function needDeleteOnRefresh() : bool
176 {
177 $property = $this->getPropertyObject();
178
179 return $property ? !empty($property->getRelations()) : false;
180 }
181
182 protected static function constructPropertyFilter(Entity $entity) : array
183 {
184 $filter = [
185 '=ENTITY_TYPE' => static::getEntityType()
186 ];
187
188 if ($entity->getPersonTypeId() > 0)
189 {
190 $filter['=PERSON_TYPE_ID'] = $entity->getPersonTypeId();
191 }
192
193 $subFilter = [
194 'LOGIC' => 'OR',
195 static::constructPropertyRelatedEntitiesFilter($entity)
196 ];
197
198 if ($entity->getId() > 0)
199 {
200 $dbRes = static::getList([
201 'select' => ['ORDER_PROPS_ID'],
202 'filter' => [
203 '=ENTITY_ID' => $entity->getId(),
204 '=ENTITY_TYPE' => static::getEntityType()
205 ]
206 ]);
207
208 while ($row = $dbRes->fetch())
209 {
210 $subFilter['@ID'][] = $row['ORDER_PROPS_ID'];
211 }
212 }
213
214 $filter[] = $subFilter;
215
216 return $filter;
217 }
218
219 protected static function hasPresetForLanding(Entity $entity) : bool
220 {
221 $tpLandingList = static::extractTpLandingIdList($entity);
222
223 if ($tpLandingList)
224 {
225 $dbRes = Internals\OrderPropsRelationTable::getList([
226 'filter' => [
227 '@ENTITY_ID' => $tpLandingList,
228 '=ENTITY_TYPE' => OrderPropsRelationTable::ENTITY_TYPE_LANDING,
229 ],
230 'cache' => ['ttl' => 86400],
231 'limit' => 1
232 ]);
233
234 return (bool)$dbRes->fetch();
235 }
236
237 return false;
238 }
239
240 protected static function hasPresetFotTradingPlatform(Entity $entity): bool
241 {
242 $tpList = static::extractTradingPlatformIdList($entity);
243
244 if ($tpList)
245 {
246 $dbRes = Internals\OrderPropsRelationTable::getList([
247 'filter' => [
248 '@ENTITY_ID' => $tpList,
249 '=ENTITY_TYPE' => OrderPropsRelationTable::ENTITY_TYPE_TRADING_PLATFORM
250 ],
251 'cache' => ['ttl' => 86400],
252 'limit' => 1
253 ]);
254
255 return (bool)$dbRes->fetch();
256 }
257
258 return false;
259 }
260
265 protected static function constructPropertyRelatedEntitiesFilter(Entity $entity): array
266 {
267 $result = [];
268
269 $psFilter = ['=RELATION_PS.ENTITY_ID' => null];
270
271 if ($paySystemList = static::extractPaySystemIdList($entity))
272 {
273 $psFilter['LOGIC'] = 'OR';
274 $psFilter['@RELATION_PS.ENTITY_ID'] = $paySystemList;
275 }
276
277 $result[] = $psFilter;
278 $dlvFilter = ['=RELATION_DLV.ENTITY_ID' => null];
279
280 if ($deliveryList = static::extractDeliveryIdList($entity))
281 {
282 $dlvFilter['LOGIC'] = 'OR';
283 $dlvFilter['@RELATION_DLV.ENTITY_ID'] = $deliveryList;
284 }
285
286 $result[] = $dlvFilter;
287
288 if (self::hasPresetForLanding($entity))
289 {
290 $result[] = [
291 'LOGIC' => 'OR',
292 '!RELATION_PS.ENTITY_ID' => null,
293 '!RELATION_DLV.ENTITY_ID' => null,
294 ];
295
296 $result = [
297 'LOGIC' => 'OR',
298 '@RELATION_TP_LANDING.ENTITY_ID' => static::extractTpLandingIdList($entity),
299 $result,
300 ];
301 }
302 else
303 {
304 $result = [
305 '=RELATION_TP_LANDING.ENTITY_ID' => null,
306 $result,
307 ];
308 }
309
310 if (self::hasPresetFotTradingPlatform($entity))
311 {
312 $result[] = [
313 'LOGIC' => 'OR',
314 '!RELATION_PS.ENTITY_ID' => null,
315 '!RELATION_DLV.ENTITY_ID' => null,
316 '!RELATION_TP_LANDING.ENTITY_ID' => null,
317 ];
318
319 $result = [
320 'LOGIC' => 'OR',
321 '@RELATION_TP.ENTITY_ID' => static::extractTradingPlatformIdList($entity),
322 $result,
323 ];
324 }
325 else
326 {
327 $result = [
328 '=RELATION_TP.ENTITY_ID' => null,
329 $result,
330 ];
331 }
332
333 return $result;
334 }
335
336 protected static function getRelationRuntimeFields(): array
337 {
338 return [
339 new ReferenceField(
340 'RELATION_PS',
341 '\Bitrix\Sale\Internals\OrderPropsRelation',
342 [
343 '=this.ID' => 'ref.PROPERTY_ID',
344 'ref.ENTITY_TYPE' => new SqlExpression('?', OrderPropsRelationTable::ENTITY_TYPE_PAY_SYSTEM)
345 ],
346 'left_join'
347 ),
348 new ReferenceField(
349 'RELATION_DLV',
350 '\Bitrix\Sale\Internals\OrderPropsRelation',
351 [
352 '=this.ID' => 'ref.PROPERTY_ID',
353 'ref.ENTITY_TYPE' => new SqlExpression('?', OrderPropsRelationTable::ENTITY_TYPE_DELIVERY)
354 ],
355 'left_join'
356 ),
357 new Main\Entity\ReferenceField(
358 'RELATION_TP_LANDING',
359 '\Bitrix\Sale\Internals\OrderPropsRelation',
360 [
361 '=this.ID' => 'ref.PROPERTY_ID',
362 'ref.ENTITY_TYPE' => new Main\DB\SqlExpression('?', OrderPropsRelationTable::ENTITY_TYPE_LANDING)
363 ],
364 'left_join'
365 ),
366 new Main\Entity\ReferenceField(
367 'RELATION_TP',
368 '\Bitrix\Sale\Internals\OrderPropsRelation',
369 [
370 '=this.ID' => 'ref.PROPERTY_ID',
371 'ref.ENTITY_TYPE' => new Main\DB\SqlExpression('?', OrderPropsRelationTable::ENTITY_TYPE_TRADING_PLATFORM)
372 ],
373 'left_join'
374 ),
375 ];
376 }
377
387 protected static function createPropertyValuesObjects(
388 array $properties,
389 array $propertyValues,
390 array $propRelation,
391 array $propertyValuesMap): array
392 {
393 $result = [];
394
395 foreach ($properties as $property)
396 {
397 $id = $property['ID'];
398
399 if (isset($propertyValuesMap[$id]))
400 {
401 $fields = $propertyValues[$propertyValuesMap[$id]];
402 unset($propertyValues[$propertyValuesMap[$id]]);
403 unset($propertyValuesMap[$id]);
404 }
405 else
406 {
407 if ($property['ACTIVE'] === 'N')
408 {
409 continue;
410 }
411
412 $fields = [];
413 }
414
415 $result[$id] = static::createPropertyValueObject($property, $fields, $propRelation[$id]);
416 }
417
418 foreach ($propertyValues as $propertyValue)
419 {
420 $result[$propertyValue['ORDER_PROPS_ID']] = static::createPropertyValueObject(null, $propertyValue);
421 }
422
423 return $result;
424 }
425
429 protected static function getFieldsMap()
430 {
431 return OrderPropsValueTable::getMap();
432 }
433
441 protected function __construct(array $property = null, array $value = [], array $relation = null)
442 {
443 if (!$property && !$value)
444 {
445 throw new Main\SystemException('invalid arguments', 0, __FILE__, __LINE__);
446 }
447
448 if ($property)
449 {
450 if (is_array($property['SETTINGS']))
451 {
452 $property += $property['SETTINGS'];
453 unset ($property['SETTINGS']);
454 }
455 }
456 else
457 {
458 $property = [
459 'TYPE' => 'STRING',
460 'PROPS_GROUP_ID' => 0,
461 'NAME' => $value['NAME'],
462 'CODE' => $value['CODE'],
463 // defaults
464 'PERSON_TYPE_ID' => null,
465 'DESCRIPTION' => null,
466 'REQUIRED' => null,
467 'DEFAULT_VALUE' => null,
468 'SORT' => null,
469 'USER_PROPS' => null,
470 'IS_LOCATION' => 'N',
471 'IS_EMAIL' => 'N',
472 'IS_PROFILE_NAME' => 'N',
473 'IS_PAYER' => 'N',
474 'IS_LOCATION4TAX' => 'N',
475 'IS_FILTERED' => 'N',
476 'IS_ZIP' => 'N',
477 'IS_PHONE' => 'N',
478 'IS_ADDRESS' => 'N',
479 'IS_ADDRESS_FROM' => 'N',
480 'IS_ADDRESS_TO' => 'N',
481 'ACTIVE' => null,
482 'UTIL' => null,
483 'INPUT_FIELD_LOCATION' => null,
484 'MULTIPLE' => null,
485 ];
486 }
487
488 $property['ENTITY_TYPE'] = static::getEntityType();
489
490 $propertyClassName = static::getPropertyClassName();
491
492 $this->property = new $propertyClassName($property, $relation);
493
494 if (isset($value['VALUE']))
495 {
496 $value['VALUE'] = $this->property->normalizeValue($value['VALUE']);
497 }
498
499 parent::__construct($value);
500
501 if (!$value)
502 {
503 $value = [
504 'ORDER_PROPS_ID' => $this->property->getId(),
505 'NAME' => $this->property->getName(),
506 'CODE' => $this->property->getField('CODE'),
507 'XML_ID' => static::generateXmlId(),
508 'ENTITY_TYPE' => $this->property->getField('ENTITY_TYPE')
509 ];
510
511 if (!empty($this->property->getField('DEFAULT_VALUE')))
512 {
513 $value['VALUE'] = $this->property->getField('DEFAULT_VALUE');
514 }
515
516 $this->setFieldsNoDemand($value);
517 }
518 }
519
523 public static function generateXmlId(): string
524 {
525 return uniqid('bx_');
526 }
527
535 public static function create(EntityPropertyValueCollection $collection, array $property = [])
536 {
537 $propertyValue = static::createPropertyValueObject($property);
538 $propertyValue->setCollection($collection);
539 return $propertyValue;
540 }
541
545 public static function getAvailableFields()
546 {
547 return ['VALUE'];
548 }
549
553 protected static function getMeaningfulFields()
554 {
555 return [];
556 }
557
567 public function normalizeValue($name, $value)
568 {
569 if ($name === 'VALUE')
570 {
571 $value = $this->property->normalizeValue($value);
572 }
573
574 return parent::normalizeValue($name, $value);
575 }
576
584 public function save(): Result
585 {
586 $this->checkCallingContext();
587
588 $result = new Result();
589
590 if (!$this->isChanged())
591 {
592 return $result;
593 }
594
595 if ($this->getId() > 0)
596 {
597 $res = $this->update();
598 }
599 else
600 {
601 $res = $this->add();
602 }
603
604 if (!$res->isSuccess())
605 {
606 $result->addErrors($res->getErrors());
607 }
608
610
611 return $result;
612 }
613
614 private function checkCallingContext(): void
615 {
616 $order = $this->getOrder();
617
618 if (!$order->isSaveRunning())
619 {
620 trigger_error("Incorrect call to the save process. Use method save() on \Bitrix\Sale\Order entity", E_USER_WARNING);
621 }
622 }
623
627 public function getOrder(): ?Order
628 {
630 $collection = $this->getCollection();
631 if (!$collection)
632 {
633 return null;
634 }
635
637 $order = $collection->getOrder();
638 if (!$order)
639 {
640 return null;
641 }
642
643 return $order;
644 }
645
650 protected function update()
651 {
652 $result = new Result();
653
654 $value = $this->property->getPreparedValueForSave($this);
655 $res = $this->updateInternal($this->getId(), ['VALUE' => $value]);
656
657 if ($res->isSuccess())
658 {
659 $result->setId($res->getId());
660 }
661 else
662 {
663 $result->addErrors($res->getErrors());
664 }
665
666 return $result;
667 }
668
674 protected function add()
675 {
676 $result = new Result();
677
678 $value = $this->property->getPreparedValueForSave($this);
681 $res = $this->addInternal(
682 [
683 'ORDER_ID' => $this->getOrder()->getId(),
684 'ORDER_PROPS_ID' => $this->property->getId(),
685 'NAME' => $this->property->getName(),
686 'VALUE' => $value,
687 'CODE' => $this->property->getField('CODE'),
688 'XML_ID' => $this->getField('XML_ID'),
689 'ENTITY_ID' => $this->getCollection()->getEntityParentId(),
690 'ENTITY_TYPE' => $this->getField('ENTITY_TYPE')
691 ]
692 );
693
694 if ($res->isSuccess())
695 {
696 $this->setFieldNoDemand('ID', $res->getId());
697 $result->setId($res->getId());
698 }
699 else
700 {
701 $result->addErrors($res->getErrors());
702 }
703
704 return $result;
705 }
706
710 protected function callEventOnPropertyValueEntitySaved(): void
711 {
712 $event = new Main\Event(
713 'sale',
714 static::getOnSavedEventName(),
715 [
716 'ENTITY' => $this,
717 'VALUES' => $this->fields->getOriginalValues(),
718 ]
719 );
720
721 $event->send();
722 }
723
730 public function setValueFromPost(array $post): Result
731 {
732 $result = new Result();
733
734 $key = ($this->getField('ORDER_PROPS_ID')) ?: "n".$this->getInternalIndex();
735
736 if (is_array($post['PROPERTIES']) && array_key_exists($key, $post['PROPERTIES']))
737 {
738 $this->setValue($post['PROPERTIES'][$key]);
739 }
740
741 return $result;
742 }
743
750 public function checkValue($key, $value)
751 {
752 $result = new Result();
753
754 $res = $this->property->checkValue($value);
755 if (!$res->isSuccess())
756 {
757 $errors = $res->getErrors();
758 foreach ($errors as $error)
759 {
760 $result->addError(new ResultError($error->getMessage(), "PROPERTIES[$key]"));
761 $result->addError(new ResultWarning($error->getMessage(), "PROPERTIES[$key]"));
762 }
763 }
764
765 return $result;
766 }
767
775 public function checkRequiredValue($key, $value)
776 {
777 $result = new Result();
778
779 $res = $this->property->checkRequiredValue($value);
780 if (!$res->isSuccess())
781 {
782 $errors = $res->getErrors();
783 foreach ($errors as $error)
784 {
785 $result->addError(new ResultError($error->getMessage(), "PROPERTIES[$key]"));
786 $result->addError(new ResultWarning($error->getMessage(), "PROPERTIES[$key]"));
787 }
788 }
789
790 return $result;
791 }
792
796 public function getProperty(): array
797 {
798 return $this->property->getFields();
799 }
800
805 {
806 return $this->property;
807 }
808
812 public function getValueId(): ?string
813 {
814 return $this->getField('ID');
815 }
816
820 public function getPropertyId()
821 {
822 return $this->property->getId();
823 }
824
828 public function getPersonTypeId()
829 {
830 return $this->property->getPersonTypeId();
831 }
832
836 public function getGroupId()
837 {
838 return $this->property->getGroupId();
839 }
840
844 public function getName()
845 {
846 return $this->property->getName();
847 }
848
852 public function getRelations()
853 {
854 return $this->property->getRelations();
855 }
856
860 public function getDescription()
861 {
862 return $this->property->getDescription();
863 }
864
868 public function getType()
869 {
870 return $this->property->getType();
871 }
872
876 public function isRequired()
877 {
878 return $this->property->isRequired();
879 }
880
884 public function isUtil()
885 {
886 return $this->property->isUtil();
887 }
888
892 public static function getRegistryType()
893 {
895 }
896
900 public static function getRegistryEntity(): string
901 {
903 }
904
910 protected function addInternal(array $data)
911 {
912 return OrderPropsValueTable::add($data);
913 }
914
921 protected function updateInternal($primary, array $data)
922 {
923 return OrderPropsValueTable::update($primary, $data);
924 }
925
933 public static function getList(array $parameters = [])
934 {
935 return OrderPropsValueTable::getList($parameters);
936 }
937
943 public function setValue($value)
944 {
945 return $this->setField('VALUE', $value);
946 }
947
952 public function getViewHtml()
953 {
954 return $this->property->getViewHtml($this->getValue());
955 }
956
961 public function getEditHtml()
962 {
963 return $this->property->getEditHtml($this->getFieldValues());
964 }
965
969 public function getValue()
970 {
971 return $this->getField("VALUE");
972 }
973
978 public function verify()
979 {
980 $res = $this->checkValue($this->getPropertyId(), $this->getValue());
981 if (!$res->isSuccess())
982 {
983 $order = $this->getOrder();
984
985 $registry = Registry::getInstance(static::getRegistryType());
986
988 $entityMarker = $registry->getEntityMarkerClassName();
989 $entityMarker::addMarker($order, $this, $res);
990 }
991
992 return $res;
993 }
994
999 public static function loadForEntity(Entity $entity): array
1000 {
1001 [$properties, $propertyValues, $propRelation, $propertyValuesMap] = static::loadFromDb($entity);
1002 return static::createPropertyValuesObjects($properties, $propertyValues, $propRelation, $propertyValuesMap);
1003 }
1004
1005 public static function getTableEntity()
1006 {
1007 return \Bitrix\Sale\Internals\OrderPropsValueTable::getEntity();
1008 }
1009}
static add(array $data)
Definition entity.php:150
static constructPropertyFilter(Entity $entity)
static extractPaySystemIdList(Entity $entity)
static create(EntityPropertyValueCollection $collection, array $property=[])
static extractTpLandingIdList(Entity $entity)
static extractDeliveryIdList(Entity $entity)
static hasPresetFotTradingPlatform(Entity $entity)
static constructPropertyRelatedEntitiesFilter(Entity $entity)
static createPropertyValueObject(array $property=null, array $value=[], array $relation=null)
__construct(array $property=null, array $value=[], array $relation=null)
static hasPresetForLanding(Entity $entity)
static createPropertyValuesObjects(array $properties, array $propertyValues, array $propRelation, array $propertyValuesMap)
static getList(array $parameters=[])
static extractTradingPlatformIdList(Entity $entity)
const ENTITY_PROPERTY_VALUE
Definition registry.php:27
static getInstance($type)
Definition registry.php:183