Bitrix-D7  20.5.0
propertyvaluebase.php
См. документацию.
1 <?php
2 
3 namespace Bitrix\Sale;
4 
5 use Bitrix\Main;
6 
7 /**
8  * Class PropertyValueBase
9  * @package Bitrix\Sale
10  */
12 {
13  /** @var PropertyBase|null $property */
14  protected $property = null;
15 
16  /**
17  * PropertyValueBase constructor.
18  * @param array|null $property
19  * @param array|null $value
20  * @param array|null $relation
21  * @throws Main\SystemException
22  */
23  protected function __construct(array $property = null, array $value = [], array $relation = null)
24  {
25  if (!$property && !$value)
26  {
27  throw new Main\SystemException('invalid arguments', 0, __FILE__, __LINE__);
28  }
29 
30  if ($property)
31  {
32  if (is_array($property['SETTINGS']))
33  {
34  $property += $property['SETTINGS'];
35  unset ($property['SETTINGS']);
36  }
37  }
38  else
39  {
40  $property = array(
41  'TYPE' => 'STRING',
42  'PROPS_GROUP_ID' => 0,
43  'NAME' => $value['NAME'],
44  'CODE' => $value['CODE'],
45  );
46  }
47 
48  $registry = Registry::getInstance(static::getRegistryType());
49 
50  /** @var PropertyBase $propertyClassName */
51  $propertyClassName = $registry->getPropertyClassName();
52 
53  $this->property = new $propertyClassName($property, $relation);
54 
55  if (isset($value['VALUE']))
56  {
57  $value['VALUE'] = $this->property->normalizeValue($value['VALUE']);
58  }
59 
60  parent::__construct($value);
61 
62  if (!$value)
63  {
64  $value = array(
65  'ORDER_PROPS_ID' => $this->property->getId(),
66  'NAME' => $this->property->getName(),
67  'CODE' => $this->property->getField('CODE'),
68  'XML_ID' => static::generateXmlId()
69  );
70 
71  if (!empty($this->property->getField('DEFAULT_VALUE')))
72  {
73  $value['VALUE'] = $this->property->getField('DEFAULT_VALUE');
74  }
75 
76  $this->setFieldsNoDemand($value);
77  }
78  }
79 
80  /**
81  * @return string
82  */
83  public static function generateXmlId()
84  {
85  return uniqid('bx_');
86  }
87 
88  /**
89  * @param OrderBase $order
90  * @return array
91  * @throws Main\ArgumentException
92  * @throws Main\NotImplementedException
93  * @throws Main\ObjectPropertyException
94  * @throws Main\SystemException
95  */
96  public static function loadForOrder(OrderBase $order)
97  {
98  $result = [];
99 
100  $propertyValues = [];
101  $propertyValuesMap = [];
102 
103  if ($order->getId() > 0)
104  {
105  $dbRes = static::getList(array(
106  'select' => array('ID', 'NAME', 'VALUE', 'CODE', 'ORDER_PROPS_ID'),
107  'filter' => array('ORDER_ID' => $order->getId())
108  ));
109  while ($row = $dbRes->fetch())
110  {
111  $propertyValues[$row['ID']] = $row;
112  $propertyValuesMap[$row['ORDER_PROPS_ID']] = $row['ID'];
113  }
114  }
115 
116  $filter = [];
117  if ($order->getPersonTypeId() > 0)
118  {
119  $filter['=PERSON_TYPE_ID'] = $order->getPersonTypeId();
120  }
121 
122  $filter[] = [
123  'LOGIC' => 'OR',
124  [
125  '=ID' => array_keys($propertyValuesMap),
126  ],
128  ];
129 
130  $registry = Registry::getInstance(static::getRegistryType());
131 
132  /** @var PropertyBase $propertyClassName */
133  $propertyClassName = $registry->getPropertyClassName();
134 
135  $dbRes = $propertyClassName::getList([
136  'select' => array('ID', 'PERSON_TYPE_ID', 'NAME', 'TYPE', 'REQUIRED', 'DEFAULT_VALUE', 'SORT',
137  'USER_PROPS', 'IS_LOCATION', 'PROPS_GROUP_ID', 'DESCRIPTION', 'IS_EMAIL', 'IS_PROFILE_NAME',
138  'IS_PAYER', 'IS_LOCATION4TAX', 'IS_FILTERED', 'CODE', 'IS_ZIP', 'IS_PHONE', 'IS_ADDRESS',
139  'ACTIVE', 'UTIL', 'INPUT_FIELD_LOCATION', 'MULTIPLE', 'SETTINGS'
140  ),
141  'filter' => $filter,
142  'runtime' => [
143  new Main\Entity\ReferenceField(
144  'RELATION_PS',
145  '\Bitrix\Sale\Internals\OrderPropsRelation',
146  [
147  '=this.ID' => 'ref.PROPERTY_ID',
148  'ref.ENTITY_TYPE' => new Main\DB\SqlExpression('?', 'P')
149  ],
150  'left_join'
151  ),
152  new Main\Entity\ReferenceField(
153  'RELATION_DLV',
154  '\Bitrix\Sale\Internals\OrderPropsRelation',
155  [
156  '=this.ID' => 'ref.PROPERTY_ID',
157  'ref.ENTITY_TYPE' => new Main\DB\SqlExpression('?', 'D')
158  ],
159  'left_join'
160  ),
161  ],
162  'order' => array('SORT' => 'ASC')
163  ]);
164 
165  $properties = array();
166  $propRelation = array();
167  while ($row = $dbRes->fetch())
168  {
169  $properties[$row['ID']] = $row;
170  $propRelation[$row['ID']] = [];
171  }
172 
173  $dbRes = Internals\OrderPropsRelationTable::getList(array(
174  'select' => [
175  'PROPERTY_ID', 'ENTITY_ID', 'ENTITY_TYPE'
176  ],
177  'filter' => [
178  'PROPERTY_ID' => array_keys($properties)
179  ]
180  ));
181 
182  while ($row = $dbRes->fetch())
183  {
184  $propRelation[$row['PROPERTY_ID']][] = $row;
185  }
186 
187  foreach ($properties as $property)
188  {
189  $id = $property['ID'];
190 
191  if (isset($propertyValuesMap[$id]))
192  {
193  $fields = $propertyValues[$propertyValuesMap[$id]];
194  unset($propertyValues[$propertyValuesMap[$id]]);
195  unset($propertyValuesMap[$id]);
196  }
197  else
198  {
199  if ($property['ACTIVE'] == 'N')
200  {
201  continue;
202  }
203 
204  $fields = [];
205  }
206 
207  $result[$id] = static::createPropertyValueObject($property, $fields, $propRelation[$id]);
208  }
209 
210  foreach ($propertyValues as $propertyValue)
211  {
212  $result[$propertyValue['ORDER_PROPS_ID']] = static::createPropertyValueObject(null, $propertyValue);
213  }
214 
215  return $result;
216  }
217 
218  /**
219  * @param OrderBase $order
220  * @return array
221  */
222  protected static function constructRelatedEntitiesFilter(OrderBase $order)
223  {
224  $result = [];
225 
226  $subFilter = [
227  'LOGIC' => 'OR',
228  '=RELATION_PS.ENTITY_ID' => null,
229  ];
230 
231  $paySystemList = static::extractPaySystemIdList($order);
232  if ($paySystemList)
233  {
234  $subFilter['@RELATION_PS.ENTITY_ID'] = $paySystemList;
235  }
236 
237  $result[] = $subFilter;
238 
239  $subFilter = [
240  'LOGIC' => 'OR',
241  '=RELATION_DLV.ENTITY_ID' => null,
242  ];
243 
244  $deliveryList = static::extractDeliveryIdList($order);
245  if ($deliveryList)
246  {
247  $subFilter['@RELATION_DLV.ENTITY_ID'] = $deliveryList;
248  }
249 
250  $result[] = $subFilter;
251 
252  return $result;
253  }
254 
255  /**
256  * @param OrderBase $order
257  * @return array
258  */
259  protected static function extractPaySystemIdList(OrderBase $order)
260  {
261  return [$order->getField('PAY_SYSTEM_ID')];
262  }
263 
264  /**
265  * @param OrderBase $order
266  * @return array
267  */
268  protected static function extractDeliveryIdList(OrderBase $order)
269  {
270  return [(int)$order->getField('DELIVERY_ID')];
271  }
272 
273  /**
274  * @param PropertyValueCollectionBase $collection
275  * @param array $property
276  * @return mixed
277  * @throws Main\ArgumentException
278  * @throws Main\NotImplementedException
279  */
280  public static function create(PropertyValueCollectionBase $collection, array $property = array())
281  {
282  $propertyValue = static::createPropertyValueObject($property);
283  $propertyValue->setCollection($collection);
284 
285  return $propertyValue;
286  }
287 
288  /**
289  * @param array|null $property
290  * @param array|null $value
291  * @param array|null $relation
292  * @return mixed
293  * @throws Main\ArgumentException
294  * @throws Main\NotImplementedException
295  */
296  protected static function createPropertyValueObject(array $property = null, array $value = [], array $relation = null)
297  {
298  $registry = Registry::getInstance(static::getRegistryType());
299  $propertyValueClassName = $registry->getPropertyValueClassName();
300 
301  return new $propertyValueClassName($property, $value, $relation);
302  }
303 
304  /**
305  * @return array
306  */
307  public static function getAvailableFields()
308  {
309  return array('VALUE');
310  }
311 
312  /**
313  * @return array
314  */
315  protected static function getMeaningfulFields()
316  {
317  return array();
318  }
319 
320  /**
321  * @param $name
322  * @param $value
323  * @return Result
324  * @throws Main\ArgumentOutOfRangeException
325  * @throws Main\NotImplementedException
326  * @throws \Exception
327  */
328  public function setField($name, $value)
329  {
330  $result = new Result();
331 
332  $value = $this->property->normalizeValue($value);
333 
334  $r = parent::setField($name, $value);
335  if (!$r->isSuccess())
336  {
337  $result->addErrors($r->getErrors());
338  }
339 
340  return $result;
341  }
342 
343  /**
344  * @internal
345  *
346  * @return Result
347  * @throws Main\ArgumentOutOfRangeException
348  * @throws Main\NotImplementedException
349  * @throws Main\ObjectNotFoundException
350  */
351  public function save()
352  {
353  $this->checkCallingContext();
354 
355  $result = new Result();
356 
357  if (!$this->isChanged())
358  {
359  return $result;
360  }
361 
362  if ($this->getId() > 0)
363  {
364  $r = $this->update();
365  }
366  else
367  {
368  $r = $this->add();
369  }
370 
371  if (!$r->isSuccess())
372  {
373  $result->addErrors($r->getErrors());
374  }
375 
376  $this->callEventOnPropertyValueEntitySaved();
377 
378  return $result;
379  }
380 
381  /**
382  * @throws Main\ObjectNotFoundException
383  */
384  private function checkCallingContext()
385  {
386  $order = $this->getOrder();
387 
388  if (!$order->isSaveRunning())
389  {
390  trigger_error("Incorrect call to the save process. Use method save() on \Bitrix\Sale\Order entity", E_USER_WARNING);
391  }
392  }
393 
394  /**
395  * @return Order|null
396  */
397  public function getOrder()
398  {
399  /** @var PropertyValueCollectionBase $collection */
400  $collection = $this->getCollection();
401  if (!$collection)
402  {
403  return null;
404  }
405 
406  /** @var Order $order */
407  $order = $collection->getOrder();
408  if (!$order)
409  {
410  return null;
411  }
412 
413  return $order;
414  }
415 
416  /**
417  * @return Result
418  * @throws Main\NotImplementedException
419  */
420  protected function update()
421  {
422  $result = new Result();
423 
424  $value = $this->property->getPreparedValueForSave($this);
425 
426  $r = static::updateInternal($this->getId(), array('VALUE' => $value));
427  if ($r->isSuccess())
428  {
429  $result->setId($r->getId());
430  }
431  else
432  {
433  $result->addErrors($r->getErrors());
434  }
435 
436  return $result;
437  }
438 
439  /**
440  * @return Result
441  * @throws Main\ArgumentOutOfRangeException
442  * @throws Main\NotImplementedException
443  */
444  protected function add()
445  {
446  $result = new Result();
447 
448  $value = $this->property->getPreparedValueForSave($this);
449 
450  $r = static::addInternal(
451  array(
452  'ORDER_ID' => $this->getOrder()->getId(),
453  'ORDER_PROPS_ID' => $this->property->getId(),
454  'NAME' => $this->property->getName(),
455  'VALUE' => $value,
456  'CODE' => $this->property->getField('CODE'),
457  'XML_ID' => $this->getField('XML_ID'),
458  )
459  );
460 
461  if ($r->isSuccess())
462  {
463  $this->setFieldNoDemand('ID', $r->getId());
464  $result->setId($r->getId());
465  }
466  else
467  {
468  $result->addErrors($r->getErrors());
469  }
470 
471  return $result;
472  }
473 
474  /**
475  * @return void
476  */
477  private function callEventOnPropertyValueEntitySaved()
478  {
479  /** @var Main\Event $event */
480  $event = new Main\Event('sale', 'OnSalePropertyValueEntitySaved', array(
481  'ENTITY' => $this,
482  'VALUES' => $this->fields->getOriginalValues(),
483  ));
484 
485  $event->send();
486  }
487 
488  /**
489  * @param array $post
490  * @return Result
491  * @throws Main\ArgumentOutOfRangeException
492  * @throws Main\NotImplementedException
493  */
494  public function setValueFromPost(array $post)
495  {
496  $result = new Result();
497 
498  $key = ($this->getField('ORDER_PROPS_ID')) ?: "n".$this->getInternalIndex();
499 
500  if (is_array($post['PROPERTIES']) && array_key_exists($key, $post['PROPERTIES']))
501  {
502  $this->setValue($post['PROPERTIES'][$key]);
503  }
504 
505  return $result;
506  }
507 
508  /**
509  * @param $key
510  * @param $value
511  * @return Result
512  * @throws Main\SystemException
513  */
514  public function checkValue($key, $value)
515  {
516  $result = new Result();
517 
518  $r = $this->property->checkValue($value);
519  if (!$r->isSuccess())
520  {
521  $errors = $r->getErrors();
522  foreach ($errors as $error)
523  {
524  $result->addError(new ResultError($error->getMessage(), "PROPERTIES[$key]"));
525  $result->addError(new ResultWarning($error->getMessage(), "PROPERTIES[$key]"));
526  }
527  }
528 
529  return $result;
530  }
531 
532  /**
533  * @param $key
534  * @param $value
535  *
536  * @return Result
537  * @throws Main\SystemException
538  */
539  public function checkRequiredValue($key, $value)
540  {
541  $result = new Result();
542 
543  $r = $this->property->checkRequiredValue($value);
544  if (!$r->isSuccess())
545  {
546  $errors = $r->getErrors();
547  foreach ($errors as $error)
548  {
549  $result->addError(new ResultError($error->getMessage(), "PROPERTIES[$key]"));
550  $result->addError(new ResultWarning($error->getMessage(), "PROPERTIES[$key]"));
551  }
552  }
553 
554  return $result;
555  }
556 
557  /**
558  * @return array
559  */
560  public function getProperty()
561  {
562  return $this->property->getFields();
563  }
564 
565  /**
566  * @return PropertyBase|null
567  */
568  public function getPropertyObject()
569  {
570  return $this->property;
571  }
572 
573  /**
574  * @return null|string
575  */
576  public function getValueId()
577  {
578  return $this->getField('ID');
579  }
580 
581  /**
582  * @return mixed
583  */
584  public function getPropertyId()
585  {
586  return $this->property->getId();
587  }
588 
589  /**
590  * @return mixed
591  */
592  public function getPersonTypeId()
593  {
594  return $this->property->getPersonTypeId();
595  }
596 
597  /**
598  * @return mixed
599  */
600  public function getGroupId()
601  {
602  return $this->property->getGroupId();
603  }
604 
605  /**
606  * @return mixed
607  */
608  public function getName()
609  {
610  return $this->property->getName();
611  }
612 
613  /**
614  * @return mixed
615  */
616  public function getRelations()
617  {
618  return $this->property->getRelations();
619  }
620 
621  /**
622  * @return mixed
623  */
624  public function getDescription()
625  {
626  return $this->property->getDescription();
627  }
628 
629  /**
630  * @return mixed
631  */
632  public function getType()
633  {
634  return $this->property->getType();
635  }
636 
637  /**
638  * @return bool
639  */
640  public function isRequired()
641  {
642  return $this->property->isRequired();
643  }
644 
645  /**
646  * @return bool
647  */
648  public function isUtil()
649  {
650  return $this->property->isUtil();
651  }
652 
653  /**
654  * @return string
655  */
656  public static function getRegistryEntity()
657  {
659  }
660 
661  /**
662  * @param array $data
663  * @throws Main\NotImplementedException
664  * @return Main\Entity\AddResult
665  */
666  abstract protected function addInternal(array $data);
667 
668  /**
669  * @param $primary
670  * @param array $data
671  * @throws Main\NotImplementedException
672  * @return Main\Entity\UpdateResult
673  */
674  abstract protected function updateInternal($primary, array $data);
675 
676  /**
677  * @param array $parameters
678  * @throws Main\NotImplementedException
679  * @return Main\DB\Result
680  */
681  public static function getList(array $parameters = array())
682  {
683  throw new Main\NotImplementedException();
684  }
685 
686  /**
687  * @param $value
688  * @throws Main\ArgumentOutOfRangeException
689  * @throws Main\NotImplementedException
690  */
691  public function setValue($value)
692  {
693  $this->setField('VALUE', $value);
694  }
695 
696  /**
697  * @return string
698  * @throws Main\SystemException
699  */
700  public function getViewHtml()
701  {
702  return $this->property->getViewHtml($this->getValue());
703  }
704 
705  /**
706  * @return string
707  * @throws Main\SystemException
708  */
709  public function getEditHtml()
710  {
711  return $this->property->getEditHtml($this->getFieldValues());
712  }
713 
714  /**
715  * @return null|string|array
716  */
717  public function getValue()
718  {
719  return $this->getField("VALUE");
720  }
721 
722  /**
723  * @return Result
724  * @throws Main\SystemException
725  */
726  public function verify()
727  {
728  $r = $this->checkValue($this->getPropertyId(), $this->getValue());
729  if (!$r->isSuccess())
730  {
731  $order = $this->getOrder();
732 
733  $registry = Registry::getInstance(static::getRegistryType());
734 
735  /** @var EntityMarker $entityMarker */
736  $entityMarker = $registry->getEntityMarkerClassName();
737  $entityMarker::addMarker($order, $this, $r);
738  }
739 
740  return $r;
741  }
742 
743  /**
744  * @deprecated
745  * @see \Bitrix\Sale\Property::getOptions
746  *
747  * @param $propertyId
748  * @return array
749  * @throws Main\ArgumentException
750  * @throws Main\ObjectPropertyException
751  * @throws Main\SystemException
752  */
753  public static function loadOptions($propertyId)
754  {
755  $registry = Registry::getInstance(static::getRegistryType());
756 
757  /** @var PropertyBase $propertyClassName */
758  $propertyClassName = $registry->getPropertyClassName();
759  $property = $propertyClassName::getObjectById($propertyId);
760 
761  if ($property)
762  {
763  return $property->getOptions();
764  }
765 
766  return [];
767  }
768 
769  /**
770  * @deprecated
771  * @see \Bitrix\Sale\Property::getMeaningfulValues
772  *
773  * @param $personTypeId
774  * @param $request
775  * @return array
776  * @throws Main\ArgumentException
777  * @throws Main\ArgumentNullException
778  * @throws Main\ObjectPropertyException
779  * @throws Main\SystemException
780  */
781  public static function getMeaningfulValues($personTypeId, $request)
782  {
783  $registry = Registry::getInstance(static::getRegistryType());
784 
785  /** @var PropertyBase $propertyClassName */
786  $propertyClassName = $registry->getPropertyClassName();
787  return $propertyClassName::getMeaningfulValues($personTypeId, $request);
788  }
789 
790  /**
791  * @return null|string
792  * @internal
793  *
794  */
795  public static function getEntityEventName()
796  {
797  return 'SalePropertyValue';
798  }
799 }
Exception is thrown when operation is not implemented but should be.
Base class for fatal exceptions.
getPersonTypeId()
Return person type id of order.
Definition: orderbase.php:721
getField($name)
Return field value.
Definition: orderbase.php:568
static getMeaningfulValues($personTypeId, $request)
updateInternal($primary, array $data)
static create(PropertyValueCollectionBase $collection, array $property=array())
static extractPaySystemIdList(OrderBase $order)
static getList(array $parameters=array())
static loadForOrder(OrderBase $order)
static constructRelatedEntitiesFilter(OrderBase $order)
static extractDeliveryIdList(OrderBase $order)
static createPropertyValueObject(array $property=null, array $value=[], array $relation=null)
__construct(array $property=null, array $value=[], array $relation=null)
PropertyValueBase constructor.
__construct(Base $connector)
Constructor.
Definition: resultview.php:40