Server IP : 80.87.202.40 / Your IP : 216.73.216.169 Web Server : Apache System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64 User : bitrix ( 600) PHP Version : 8.2.27 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/sale/lib/ |
Upload File : |
<?php namespace Bitrix\Sale; use Bitrix\Main\DB\SqlExpression; use Bitrix\Main\Entity\ReferenceField; use Bitrix\Sale\Internals\CollectableEntity; use Bitrix\Sale\Internals\Entity; use Bitrix\Sale\Internals\OrderPropsRelationTable; use Bitrix\Main; use Bitrix\Sale\Internals\OrderPropsValueTable; /** * Class EntityPropertyValue * @package Bitrix\Sale; */ abstract class EntityPropertyValue extends CollectableEntity { /** @var EntityProperty|null $property */ protected $property = null; /** * @return string Registry::ENTITY_SHIPMENT or Registry::ENTITY_ORDER */ abstract protected static function getEntityType(): string; /** * @return string Property class name. */ abstract protected static function getPropertyClassName(): string; /** * @param array|null $property * @param array|null $value * @param array|null $relation * @return EntityPropertyValue * @throws Main\ArgumentException * @throws Main\NotImplementedException */ abstract protected static function createPropertyValueObject( array $property = null, array $value = [], array $relation = null ): EntityPropertyValue; /** * Returns OnSaved event name * @return string */ abstract protected static function getOnSavedEventName(): string; protected static function extractPaySystemIdList(Entity $entity) { return []; } protected static function extractDeliveryIdList(Entity $entity) { return []; } protected static function extractTpLandingIdList(Entity $entity) : array { return []; } protected static function extractTradingPlatformIdList(Entity $entity): array { return []; } /** * @param Entity $entity * @return array * @throws Main\ArgumentException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ protected static function loadFromDb(Entity $entity): array { $propertyValues = []; $propertyValuesMap = []; if ($entity->getId() > 0) { $dbRes = static::getList( [ 'select' => ['ID', 'NAME', 'VALUE', 'CODE', 'ORDER_PROPS_ID'], 'filter' => [ '=ENTITY_ID' => $entity->getId(), '=ENTITY_TYPE' => static::getEntityType() ] ] ); while ($row = $dbRes->fetch()) { $propertyValues[$row['ID']] = $row; $propertyValuesMap[$row['ORDER_PROPS_ID']] = $row['ID']; } } /** @var EntityProperty $propertyClassName */ $propertyClassName = static::getPropertyClassName(); $getListParams = [ 'select' => [ 'ID', 'PERSON_TYPE_ID', 'NAME', 'TYPE', 'REQUIRED', 'DEFAULT_VALUE', 'SORT', 'USER_PROPS', 'IS_LOCATION', 'PROPS_GROUP_ID', 'DESCRIPTION', 'IS_EMAIL', 'IS_PROFILE_NAME', 'IS_PAYER', 'IS_LOCATION4TAX', 'IS_FILTERED', 'CODE', 'IS_ZIP', 'IS_PHONE', 'IS_ADDRESS', 'IS_ADDRESS_FROM', 'IS_ADDRESS_TO', 'ACTIVE', 'UTIL', 'INPUT_FIELD_LOCATION', 'MULTIPLE', 'SETTINGS', 'ENTITY_TYPE' ], 'filter' => static::constructPropertyFilter($entity), 'runtime' => static::getRelationRuntimeFields(), 'order' => ['SORT' => 'ASC'], ]; $dbRes = $propertyClassName::getList($getListParams); $properties = []; $propRelation = []; while ($row = $dbRes->fetch()) { $properties[$row['ID']] = $row; $propRelation[$row['ID']] = []; } if (!empty($properties)) { $dbRes = OrderPropsRelationTable::getList( [ 'select' => [ 'PROPERTY_ID', 'ENTITY_ID', 'ENTITY_TYPE' ], 'filter' => [ 'PROPERTY_ID' => array_keys($properties) ] ] ); while ($row = $dbRes->fetch()) { $propRelation[$row['PROPERTY_ID']][] = $row; } } return [$properties, $propertyValues, $propRelation, $propertyValuesMap]; } /** * @return bool */ public function needDeleteOnRefresh() : bool { $property = $this->getPropertyObject(); return $property ? !empty($property->getRelations()) : false; } protected static function constructPropertyFilter(Entity $entity) : array { $filter = [ '=ENTITY_TYPE' => static::getEntityType() ]; if ($entity->getPersonTypeId() > 0) { $filter['=PERSON_TYPE_ID'] = $entity->getPersonTypeId(); } $subFilter = [ 'LOGIC' => 'OR', static::constructPropertyRelatedEntitiesFilter($entity) ]; if ($entity->getId() > 0) { $dbRes = static::getList([ 'select' => ['ORDER_PROPS_ID'], 'filter' => [ '=ENTITY_ID' => $entity->getId(), '=ENTITY_TYPE' => static::getEntityType() ] ]); while ($row = $dbRes->fetch()) { $subFilter['@ID'][] = $row['ORDER_PROPS_ID']; } } $filter[] = $subFilter; return $filter; } protected static function hasPresetForLanding(Entity $entity) : bool { $tpLandingList = static::extractTpLandingIdList($entity); if ($tpLandingList) { $dbRes = Internals\OrderPropsRelationTable::getList([ 'filter' => [ '@ENTITY_ID' => $tpLandingList, '=ENTITY_TYPE' => OrderPropsRelationTable::ENTITY_TYPE_LANDING, ], 'cache' => ['ttl' => 86400], 'limit' => 1 ]); return (bool)$dbRes->fetch(); } return false; } protected static function hasPresetFotTradingPlatform(Entity $entity): bool { $tpList = static::extractTradingPlatformIdList($entity); if ($tpList) { $dbRes = Internals\OrderPropsRelationTable::getList([ 'filter' => [ '@ENTITY_ID' => $tpList, '=ENTITY_TYPE' => OrderPropsRelationTable::ENTITY_TYPE_TRADING_PLATFORM ], 'cache' => ['ttl' => 86400], 'limit' => 1 ]); return (bool)$dbRes->fetch(); } return false; } /** * @param Entity $entity * @return array */ protected static function constructPropertyRelatedEntitiesFilter(Entity $entity): array { $result = []; $psFilter = ['=RELATION_PS.ENTITY_ID' => null]; if ($paySystemList = static::extractPaySystemIdList($entity)) { $psFilter['LOGIC'] = 'OR'; $psFilter['@RELATION_PS.ENTITY_ID'] = $paySystemList; } $result[] = $psFilter; $dlvFilter = ['=RELATION_DLV.ENTITY_ID' => null]; if ($deliveryList = static::extractDeliveryIdList($entity)) { $dlvFilter['LOGIC'] = 'OR'; $dlvFilter['@RELATION_DLV.ENTITY_ID'] = $deliveryList; } $result[] = $dlvFilter; if (self::hasPresetForLanding($entity)) { $result[] = [ 'LOGIC' => 'OR', '!RELATION_PS.ENTITY_ID' => null, '!RELATION_DLV.ENTITY_ID' => null, ]; $result = [ 'LOGIC' => 'OR', '@RELATION_TP_LANDING.ENTITY_ID' => static::extractTpLandingIdList($entity), $result, ]; } else { $result = [ '=RELATION_TP_LANDING.ENTITY_ID' => null, $result, ]; } if (self::hasPresetFotTradingPlatform($entity)) { $result[] = [ 'LOGIC' => 'OR', '!RELATION_PS.ENTITY_ID' => null, '!RELATION_DLV.ENTITY_ID' => null, '!RELATION_TP_LANDING.ENTITY_ID' => null, ]; $result = [ 'LOGIC' => 'OR', '@RELATION_TP.ENTITY_ID' => static::extractTradingPlatformIdList($entity), $result, ]; } else { $result = [ '=RELATION_TP.ENTITY_ID' => null, $result, ]; } return $result; } protected static function getRelationRuntimeFields(): array { return [ new ReferenceField( 'RELATION_PS', '\Bitrix\Sale\Internals\OrderPropsRelation', [ '=this.ID' => 'ref.PROPERTY_ID', 'ref.ENTITY_TYPE' => new SqlExpression('?', OrderPropsRelationTable::ENTITY_TYPE_PAY_SYSTEM) ], 'left_join' ), new ReferenceField( 'RELATION_DLV', '\Bitrix\Sale\Internals\OrderPropsRelation', [ '=this.ID' => 'ref.PROPERTY_ID', 'ref.ENTITY_TYPE' => new SqlExpression('?', OrderPropsRelationTable::ENTITY_TYPE_DELIVERY) ], 'left_join' ), new Main\Entity\ReferenceField( 'RELATION_TP_LANDING', '\Bitrix\Sale\Internals\OrderPropsRelation', [ '=this.ID' => 'ref.PROPERTY_ID', 'ref.ENTITY_TYPE' => new Main\DB\SqlExpression('?', OrderPropsRelationTable::ENTITY_TYPE_LANDING) ], 'left_join' ), new Main\Entity\ReferenceField( 'RELATION_TP', '\Bitrix\Sale\Internals\OrderPropsRelation', [ '=this.ID' => 'ref.PROPERTY_ID', 'ref.ENTITY_TYPE' => new Main\DB\SqlExpression('?', OrderPropsRelationTable::ENTITY_TYPE_TRADING_PLATFORM) ], 'left_join' ), ]; } /** * @param array $properties * @param array $propertyValues * @param array $propRelation * @param array $propertyValuesMap * @return array * @throws Main\ArgumentException * @throws Main\NotImplementedException */ protected static function createPropertyValuesObjects( array $properties, array $propertyValues, array $propRelation, array $propertyValuesMap): array { $result = []; foreach ($properties as $property) { $id = $property['ID']; if (isset($propertyValuesMap[$id])) { $fields = $propertyValues[$propertyValuesMap[$id]]; unset($propertyValues[$propertyValuesMap[$id]]); unset($propertyValuesMap[$id]); } else { if ($property['ACTIVE'] === 'N') { continue; } $fields = []; } $result[$id] = static::createPropertyValueObject($property, $fields, $propRelation[$id]); } foreach ($propertyValues as $propertyValue) { $result[$propertyValue['ORDER_PROPS_ID']] = static::createPropertyValueObject(null, $propertyValue); } return $result; } /** * @return array */ protected static function getFieldsMap() { return OrderPropsValueTable::getMap(); } /** * EntityPropertyValue constructor. * @param array|null $property * @param array|null $value * @param array|null $relation * @throws Main\SystemException|Main\LoaderException */ protected function __construct(array $property = null, array $value = [], array $relation = null) { if (!$property && !$value) { throw new Main\SystemException('invalid arguments', 0, __FILE__, __LINE__); } if ($property) { if (isset($property['SETTINGS']) && is_array($property['SETTINGS'])) { $property += $property['SETTINGS']; unset ($property['SETTINGS']); } } else { $property = [ 'TYPE' => 'STRING', 'PROPS_GROUP_ID' => 0, 'NAME' => $value['NAME'], 'CODE' => $value['CODE'], // defaults 'PERSON_TYPE_ID' => null, 'DESCRIPTION' => null, 'REQUIRED' => null, 'DEFAULT_VALUE' => null, 'SORT' => null, 'USER_PROPS' => null, 'IS_LOCATION' => 'N', 'IS_EMAIL' => 'N', 'IS_PROFILE_NAME' => 'N', 'IS_PAYER' => 'N', 'IS_LOCATION4TAX' => 'N', 'IS_FILTERED' => 'N', 'IS_ZIP' => 'N', 'IS_PHONE' => 'N', 'IS_ADDRESS' => 'N', 'IS_ADDRESS_FROM' => 'N', 'IS_ADDRESS_TO' => 'N', 'ACTIVE' => null, 'UTIL' => null, 'INPUT_FIELD_LOCATION' => null, 'MULTIPLE' => null, ]; } $property['ENTITY_TYPE'] = static::getEntityType(); $propertyClassName = static::getPropertyClassName(); $this->property = new $propertyClassName($property, $relation); if (isset($value['VALUE'])) { $value['VALUE'] = $this->property->normalizeValue($value['VALUE']); } parent::__construct($value); if (!$value) { $value = [ 'ORDER_PROPS_ID' => $this->property->getId(), 'NAME' => $this->property->getName(), 'CODE' => $this->property->getField('CODE'), 'XML_ID' => static::generateXmlId(), 'ENTITY_TYPE' => $this->property->getField('ENTITY_TYPE') ]; if (!empty($this->property->getField('DEFAULT_VALUE'))) { $value['VALUE'] = $this->property->getField('DEFAULT_VALUE'); } $this->setFieldsNoDemand($value); } } /** * @return string */ public static function generateXmlId(): string { return uniqid('bx_'); } /** * @param EntityPropertyValueCollection $collection * @param array $property * @return mixed * @throws Main\ArgumentException * @throws Main\NotImplementedException */ public static function create(EntityPropertyValueCollection $collection, array $property = []) { $propertyValue = static::createPropertyValueObject($property); $propertyValue->setCollection($collection); return $propertyValue; } /** * @return array */ public static function getAvailableFields() { return ['VALUE']; } /** * @return array */ protected static function getMeaningfulFields() { return []; } /** * @param $name * @param $value * @return mixed * @throws Main\ArgumentException * @throws Main\LoaderException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public function normalizeValue($name, $value) { if ($name === 'VALUE') { $value = $this->property->normalizeValue($value); } return parent::normalizeValue($name, $value); } /** * @internal * * @return Result * @throws Main\ArgumentOutOfRangeException * @throws Main\NotImplementedException */ public function save(): Result { $this->checkCallingContext(); $result = new Result(); if (!$this->isChanged()) { return $result; } if ($this->getId() > 0) { $res = $this->update(); } else { $res = $this->add(); } if (!$res->isSuccess()) { $result->addErrors($res->getErrors()); } $this->callEventOnPropertyValueEntitySaved(); return $result; } private function checkCallingContext(): void { $order = $this->getOrder(); if (!$order->isSaveRunning()) { trigger_error("Incorrect call to the save process. Use method save() on \Bitrix\Sale\Order entity", E_USER_WARNING); } } /** * @return Order|null */ public function getOrder(): ?Order { /** @var PropertyValueCollectionBase $collection */ $collection = $this->getCollection(); if (!$collection) { return null; } /** @var Order $order */ $order = $collection->getOrder(); if (!$order) { return null; } return $order; } /** * @return Result * @throws Main\NotImplementedException|Main\ArgumentOutOfRangeException */ protected function update() { $result = new Result(); $value = $this->property->getPreparedValueForSave($this); $res = $this->updateInternal($this->getId(), ['VALUE' => $value]); if ($res->isSuccess()) { $result->setId($res->getId()); } else { $result->addErrors($res->getErrors()); } return $result; } /** * @return Result * @throws Main\ArgumentOutOfRangeException * @throws Main\NotImplementedException */ protected function add() { $result = new Result(); $value = $this->property->getPreparedValueForSave($this); /** @var PropertyValueCollection $collection */ $res = $this->addInternal( [ 'ORDER_ID' => $this->getOrder()->getId(), 'ORDER_PROPS_ID' => $this->property->getId(), 'NAME' => $this->property->getName(), 'VALUE' => $value, 'CODE' => $this->property->getField('CODE'), 'XML_ID' => $this->getField('XML_ID'), 'ENTITY_ID' => $this->getCollection()->getEntityParentId(), 'ENTITY_TYPE' => $this->getField('ENTITY_TYPE') ] ); if ($res->isSuccess()) { $this->setFieldNoDemand('ID', $res->getId()); $result->setId($res->getId()); } else { $result->addErrors($res->getErrors()); } return $result; } /** * @return void */ protected function callEventOnPropertyValueEntitySaved(): void { $event = new Main\Event( 'sale', static::getOnSavedEventName(), [ 'ENTITY' => $this, 'VALUES' => $this->fields->getOriginalValues(), ] ); $event->send(); } /** * @param array $post * @return Result * @throws Main\ArgumentOutOfRangeException * @throws Main\NotImplementedException */ public function setValueFromPost(array $post): Result { $result = new Result(); $key = ($this->getField('ORDER_PROPS_ID')) ?: "n".$this->getInternalIndex(); if (is_array($post['PROPERTIES']) && array_key_exists($key, $post['PROPERTIES'])) { $this->setValue($post['PROPERTIES'][$key]); } return $result; } /** * @param $key * @param $value * @return Result * @throws Main\SystemException */ public function checkValue($key, $value) { $result = new Result(); $res = $this->property->checkValue($value); if (!$res->isSuccess()) { $errors = $res->getErrors(); foreach ($errors as $error) { $result->addError(new ResultError($error->getMessage(), "PROPERTIES[$key]")); $result->addError(new ResultWarning($error->getMessage(), "PROPERTIES[$key]")); } } return $result; } /** * @param $key * @param $value * * @return Result * @throws Main\SystemException */ public function checkRequiredValue($key, $value) { $result = new Result(); $res = $this->property->checkRequiredValue($value); if (!$res->isSuccess()) { $errors = $res->getErrors(); foreach ($errors as $error) { $result->addError(new ResultError($error->getMessage(), "PROPERTIES[$key]")); $result->addError(new ResultWarning($error->getMessage(), "PROPERTIES[$key]")); } } return $result; } /** * @return array */ public function getProperty(): array { return $this->property->getFields(); } /** * @return EntityProperty|null */ public function getPropertyObject(): ?EntityProperty { return $this->property; } /** * @return null|string */ public function getValueId(): ?string { return $this->getField('ID'); } /** * @return mixed */ public function getPropertyId() { return $this->property->getId(); } /** * @return mixed */ public function getPersonTypeId() { return $this->property->getPersonTypeId(); } /** * @return mixed */ public function getGroupId() { return $this->property->getGroupId(); } /** * @return mixed */ public function getName() { return $this->property->getName(); } /** * @return mixed */ public function getRelations() { return $this->property->getRelations(); } /** * @return mixed */ public function getDescription() { return $this->property->getDescription(); } /** * @return mixed */ public function getType() { return $this->property->getType(); } /** * @return bool */ public function isRequired() { return $this->property->isRequired(); } /** * @return bool */ public function isUtil() { return $this->property->isUtil(); } /** * @return string */ public static function getRegistryType() { return Registry::REGISTRY_TYPE_ORDER; } /** * @return string */ public static function getRegistryEntity(): string { return Registry::ENTITY_PROPERTY_VALUE; } /** * @param array $data * @return Main\Entity\AddResult * @throws \Exception */ protected function addInternal(array $data) { return OrderPropsValueTable::add($data); } /** * @param $primary * @param array $data * @return Main\Entity\UpdateResult * @throws \Exception */ protected function updateInternal($primary, array $data) { return OrderPropsValueTable::update($primary, $data); } /** * @param array $parameters * @return Main\DB\Result|Main\ORM\Query\Result * @throws Main\ArgumentException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public static function getList(array $parameters = []) { return OrderPropsValueTable::getList($parameters); } /** * @param $value * @throws Main\ArgumentOutOfRangeException * @throws Main\NotImplementedException */ public function setValue($value) { return $this->setField('VALUE', $value); } /** * @return string * @throws Main\SystemException */ public function getViewHtml() { return $this->property->getViewHtml($this->getValue()); } /** * @return string * @throws Main\SystemException */ public function getEditHtml() { return $this->property->getEditHtml($this->getFieldValues()); } /** * @return null|string|array */ public function getValue() { return $this->getField("VALUE"); } /** * @return Result * @throws Main\SystemException */ public function verify() { $res = $this->checkValue($this->getPropertyId(), $this->getValue()); if (!$res->isSuccess()) { $order = $this->getOrder(); $registry = Registry::getInstance(static::getRegistryType()); /** @var EntityMarker $entityMarker */ $entityMarker = $registry->getEntityMarkerClassName(); $entityMarker::addMarker($order, $this, $res); } return $res; } /** * @param Entity $entity * @return array */ public static function loadForEntity(Entity $entity): array { [$properties, $propertyValues, $propRelation, $propertyValuesMap] = static::loadFromDb($entity); return static::createPropertyValuesObjects($properties, $propertyValues, $propRelation, $propertyValuesMap); } public static function getTableEntity() { return \Bitrix\Sale\Internals\OrderPropsValueTable::getEntity(); } }