%PDF- %PDF-
Direktori : /home/bitrix/www/bitrix/modules/sale/lib/delivery/services/ |
Current File : /home/bitrix/www/bitrix/modules/sale/lib/delivery/services/manager.php |
<?php namespace Bitrix\Sale\Delivery\Services; use Bitrix\Main\Config\Option; use Bitrix\Main\Error; use Bitrix\Main\Event; use Bitrix\Sale\Internals\Pool; use Bitrix\Sale\Result; use Bitrix\Main\IO\File; use Bitrix\Sale\Shipment; use Bitrix\Main\IO\Directory; use Bitrix\Main\SystemException; use Bitrix\Main\Localization\Loc; use Bitrix\Main\Entity\EventResult; use Bitrix\Main\ArgumentNullException; use Bitrix\Sale\Delivery\Restrictions; use Bitrix\Sale\Delivery\ExtraServices; use Bitrix\Sale\Internals\ShipmentTable; use Bitrix\Sale\Delivery\CalculationResult; use Bitrix\Sale\Internals\ServiceRestrictionTable; Loc::loadMessages(__FILE__); /** * Class Manager * Helps to manage delivery services. * @package Bitrix\Sale\Delivery\Services */ class Manager { const SKIP_PROFILE_PARENT_CHECK = 0; const SKIP_CHILDREN_PARENT_CHECK = 1; protected static $handlers = null; protected static $cachedFields = array(); /* Directories where we can found handlers */ protected static $handlersDirectories = array(); /** @var null|Pool */ protected static $objectsPool = null; /** * Returns service field, caches results during hit. * @param int $deliveryId * @return array Service fields * @throws SystemException * @throws \Bitrix\Main\ArgumentException */ public static function getById($deliveryId) { $id = intval($deliveryId); if($id <= 0) throw new SystemException("deliveryId"); if(!isset(self::$cachedFields[$deliveryId]) || !is_array(self::$cachedFields[$deliveryId])) { self::$cachedFields[$deliveryId] = array(); $resSrvParams = Table::getList(array( 'filter' => array("=ID" => $deliveryId) )); if($srvParams = $resSrvParams->fetch()) self::$cachedFields[$srvParams["ID"]] = $srvParams; } return self::$cachedFields[$deliveryId]; } /** * @param Shipment $shipment. * @param int $restrictionMode MODE_CLIENT or MODE_MANAGER from Restrictions\Manager. * @return Base[] delivery services objects */ public static function getRestrictedObjectsList(Shipment $shipment, $restrictionMode = Restrictions\Manager::MODE_CLIENT) { $result = array(); $services = self::getRestrictedList($shipment, $restrictionMode); foreach($services as $srvParams) { if($srvParams["CLASS_NAME"]::canHasProfiles()) continue; if(is_callable($srvParams["CLASS_NAME"]."::canHasChildren") && $srvParams["CLASS_NAME"]::canHasChildren()) continue; $service = self::getPooledObject($srvParams); if(!$service) continue; if(!$service->isCompatible($shipment)) continue; if($shipment->getCurrency() != $service->getCurrency()) { $service->getExtraServices()->setOperationCurrency( $shipment->getCurrency() ); } $result[$srvParams["ID"]] = $service; } return $result; } /** * @param $deliveryId * @return bool is service exists or not * @throws SystemException */ public static function isServiceExist($deliveryId) { if(intval($deliveryId) <= 0) return false; $srv = self::getById($deliveryId); return !empty($srv); } /** * Prepares and caches data during the hit * @param bool $calculatingOnly If we need absolutely all, or calculating items only. * @param array $restrictedIds If we have list of services ids, successful checked restrictions. * @return array Array of active delivery services fields. * @throws \Bitrix\Main\ArgumentException */ public static function getActiveList($calculatingOnly = false, $restrictedIds = null) { //If we alredy got all active services static $isDataPrepared = false; static $activeIds = array(); static $canHasProfiles = array(); static $canHasChildren = array(); static $DontHaveRestrictionsIds = array(); if(is_array($restrictedIds)) { $unPreparedRestrictedIds = array_diff_key( array_flip( $restrictedIds ), self::$cachedFields ); $unPreparedRestrictedIds = array_keys($unPreparedRestrictedIds); } else { $unPreparedRestrictedIds = array(); } if(!$isDataPrepared || !empty($unPreparedRestrictedIds)) { $result = array(); self::initHandlers(); $filter = array( '=ACTIVE' => 'Y' ); $params = array( 'order' => array('SORT' =>'ASC', 'NAME' => 'ASC'), 'filter' => $filter ); $params['runtime'] = array( new \Bitrix\Main\Entity\ExpressionField( 'RESTRICTIONS_EXIST', 'CASE WHEN EXISTS('. 'SELECT 1 FROM b_sale_service_rstr SSR WHERE SSR.SERVICE_ID = %s AND SSR.SERVICE_TYPE = '.Restrictions\Manager::SERVICE_TYPE_SHIPMENT.') THEN 1 ELSE 0 END', 'ID' ) ); $params['select'] = array('*', 'RESTRICTIONS_EXIST'); if(!empty($unPreparedRestrictedIds)) { if($isDataPrepared) { $params['filter']['ID'] = $unPreparedRestrictedIds; } else { $params['filter'][] = array( "LOGIC" => "OR", "ID" => $unPreparedRestrictedIds, 'RESTRICTIONS_EXIST' => 0 ); } } $dbRes = Table::getList($params); $profilesParentsIds = array(); while($service = $dbRes->fetch()) { if(!is_subclass_of($service["CLASS_NAME"], 'Bitrix\Sale\Delivery\Services\Base')) continue; if(!$service['RESTRICTIONS_EXIST']) $DontHaveRestrictionsIds[] = $service['ID']; if($service["CLASS_NAME"]::canHasChildren()) $canHasChildren[$service["ID"]] = true; if ($service['CLASS_NAME']::canHasProfiles()) $canHasProfiles[$service["ID"]] = true; if($service["PARENT_ID"] != 0) $profilesParentsIds[$service["PARENT_ID"]] = $service['ID']; $result[$service["ID"]] = $service; if($service['ACTIVE'] == 'Y') $activeIds[$service["ID"]] = $service["ID"]; } foreach(array_diff_key($canHasProfiles, $profilesParentsIds) as $id => $tmp) unset($result[$id]); self::$cachedFields = self::$cachedFields + $result; Restrictions\Manager::prepareData(array_keys($result)); ExtraServices\Manager::prepareData(array_keys($result)); //selected all active if(!$isDataPrepared && empty($unPreparedRestrictedIds)) $isDataPrepared = true; } if(is_array($restrictedIds) && !empty($restrictedIds)) $storedIds = array_diff($restrictedIds, $unPreparedRestrictedIds); else $storedIds = array(); if(!empty($storedIds) && is_array($storedIds)) { foreach($storedIds as $storedId) { if(empty(self::$cachedFields[$storedId])) continue; $service = self::$cachedFields[$storedId]; if(!class_exists($service["CLASS_NAME"])) continue; if($service["CLASS_NAME"]::canHasChildren()) $canHasChildren[$storedId] = true; if ($service['CLASS_NAME']::canHasProfiles()) $canHasProfiles[$storedId] = true; if($service['ACTIVE'] == 'Y') $activeIds[$storedId] = $storedId; } } $active = array_intersect_key(self::$cachedFields, array_flip($activeIds)); if(is_array($restrictedIds)) { $result = array_intersect_key($active, array_flip($DontHaveRestrictionsIds)); if(!empty($restrictedIds)) $result = $result + array_intersect_key($active, array_flip($restrictedIds)); } else { $result = $active; } /* * Clean children if parent is not present in result. * We mean that it doesn't pass restrictions checks. * Or it is not active. */ foreach($result as $id => $fields) { if(intval($fields['PARENT_ID']) <= 0) continue; if(empty($result[$fields['PARENT_ID']])) unset($result[$id]); } if($calculatingOnly) $result = array_diff_key($result, $canHasChildren, $canHasProfiles); if(!empty($result)) sortByColumn($result, array("SORT" => SORT_ASC, "NAME" => SORT_ASC), '', null, true); return $result; } /** * @param Shipment $shipment * @param int $restrictionMode MODE_CLIENT or MODE_MANAGER from Restrictions\Manager. * @param array $skipChecks self::SKIP_CHILDREN_PARENT_CHECK || self::SKIP_PROFILE_PARENT_CHECK * @return array Array of active delivery services fields filtered by restrictions. */ public static function getRestrictedList(Shipment $shipment = null, $restrictionMode, array $skipChecks = array()) { $result = array(); if(empty($skipChecks)) { $skipChecks = array( self::SKIP_CHILDREN_PARENT_CHECK, self::SKIP_PROFILE_PARENT_CHECK ); } //Have restrictions and this restrictions successfully checked $restrictedSrvIds = Restrictions\Manager::getRestrictedIds($shipment, $restrictionMode); //Don't have any restrictions + successfully checked $services = self::getActiveList(false, array_keys($restrictedSrvIds)); foreach($services as $srvParams) { $srvParams["RESTRICTED"] = false; if(!in_array(self::SKIP_PROFILE_PARENT_CHECK, $skipChecks)) if($srvParams["CLASS_NAME"]::canHasProfiles()) continue; if(!in_array(self::SKIP_CHILDREN_PARENT_CHECK, $skipChecks)) if(is_callable($srvParams["CLASS_NAME"]."::canHasChildren") && $srvParams["CLASS_NAME"]::canHasChildren()) continue; if(isset($restrictedSrvIds[$srvParams["ID"]]) && $restrictedSrvIds[$srvParams["ID"]] == Restrictions\Manager::SEVERITY_SOFT) $srvParams["RESTRICTED"] = true; $result[$srvParams["ID"]] = $srvParams; } return $result; } /** * @param array $srvParams Delivery service fields from DataBase to construct service object. * @return Base|null Delivery service object * All errors it writes to system log. * It's better to use \Bitrix\Sale\Delivery\Services\Manager::getPooledObject for performance purposes */ public static function createObject(array $srvParams) { self::initHandlers(); $errorMsg = ""; $service = null; if(!isset($srvParams["PARENT_ID"])) $srvParams["PARENT_ID"] = 0; if(class_exists($srvParams['CLASS_NAME'])) { try { $service = new $srvParams['CLASS_NAME']($srvParams); } catch(SystemException $e) { $errorMsg = $e->getMessage(); } if($service && !($service instanceof Base)) $errorMsg = "Can't create delivery object. Class ".$srvParams['CLASS_NAME'].' is not the instance of Bitrix\Sale\DeliveryService'; } else { $errorMsg = "Can't create delivery object. Class \"".$srvParams['CLASS_NAME']."\" does not exist."; } if(strlen($errorMsg) > 0) { $eventLog = new \CEventLog; $eventLog->Add(array( "SEVERITY" => $eventLog::SEVERITY_ERROR, "AUDIT_TYPE_ID" => "SALE_DELIVERY_CREATE_OBJECT_ERROR", "MODULE_ID" => "sale", "ITEM_ID" => 'createObject()', "DESCRIPTION" => $errorMsg." Fields: ".serialize($srvParams), )); return null; } return $service; } public static function getPooledObject(array $fields) { if(self::$objectsPool === null) self::$objectsPool = new ObjectPool(); return self::$objectsPool->getObject($fields); } /** * @param int $deliveryId Delivery service id * @return Base Delivery service object * @throws ArgumentNullException * @throws SystemException */ public static function getObjectById($deliveryId) { if(intval($deliveryId) <= 0 ) throw new ArgumentNullException("deliveryId"); $srvParams = self::getById($deliveryId); if(empty($srvParams)) return null; return self::getPooledObject($srvParams); } /** * @param string $serviceCode Delivery service code * @return Base Delivery service object. * @throws ArgumentNullException * @throws SystemException * @throws \Bitrix\Main\ArgumentException */ public static function getObjectByCode($serviceCode) { if(strlen($serviceCode) <= 0 ) throw new ArgumentNullException("serviceCode"); $srvParams = array(); foreach(self::$cachedFields as $id => $srv) { if($srv['CODE'] == $serviceCode) { $srvParams = $srv; } } if(empty($srvParams)) { $resSrvParams = Table::getList(array( 'filter' => array('=CODE' => $serviceCode) )); if(!($srvParams = $resSrvParams->fetch())) throw new SystemException("Can't get delivery service data with code: \"".$serviceCode."\""); self::$cachedFields[$srvParams['ID']] = $srvParams; } return self::getPooledObject($srvParams); } /** * Gets info about existing delivery services handlers * Stores this information during the hit * @return bool * @throws SystemException * @throws \Bitrix\Main\LoaderException */ protected static function initHandlers() { if(self::$handlers !== null) return true; self::$handlersDirectories = array( 'LOCAL' => '/local/php_interface/include/sale_delivery/', 'CUSTOM' => Option::get('sale', 'delivery_handles_custom_path', BX_PERSONAL_ROOT.'/php_interface/include/sale_delivery/'), 'SYSTEM' => '/bitrix/modules/sale/handlers/delivery/' ); $result = array( '\Bitrix\Sale\Delivery\Services\Group' => 'lib/delivery/services/group.php', '\Bitrix\Sale\Delivery\Services\Automatic' => 'lib/delivery/services/automatic.php', '\Bitrix\Sale\Delivery\Services\Configurable' => 'lib/delivery/services/configurable.php', '\Bitrix\Sale\Delivery\Services\AutomaticProfile' => 'lib/delivery/services/automatic_profile.php', '\Bitrix\Sale\Delivery\Services\EmptyDeliveryService' => 'lib/delivery/services/emptydeliveryservice.php' ); \Bitrix\Main\Loader::registerAutoLoadClasses('sale', $result); /* * To add you own handler you must wrote smth. like this in for example init.php: * * function addCustomDeliveryServices() * { * return new \Bitrix\Main\EventResult( * \Bitrix\Main\EventResult::SUCCESS, * array( * '\Sale\Handlers\Delivery\SimpleHandler' => '/bitrix/modules/sale/handlers/delivery/simple/handler.php' * ), * 'sale' * ); * } * * $eventManager->addEventHandler('sale', 'onSaleDeliveryHandlersClassNamesBuildList', 'addCustomDeliveryServices'); */ $event = new Event('sale', 'onSaleDeliveryHandlersClassNamesBuildList'); $event->send(); $resultList = $event->getResults(); if (is_array($resultList) && !empty($resultList)) { $customClasses = array(); foreach ($resultList as $eventResult) { /** @var \Bitrix\Main\EventResult $eventResult*/ if ($eventResult->getType() != EventResult::SUCCESS) continue; $params = $eventResult->getParameters(); if(!empty($params) && is_array($params)) $customClasses = array_merge($customClasses, $params); } if(!empty($customClasses)) { \Bitrix\Main\Loader::registerAutoLoadClasses(null, $customClasses); $result = array_merge($result, $customClasses); } } $handlers = self::getHandlersClasses(); if(!empty($handlers)) { \Bitrix\Main\Loader::registerAutoLoadClasses(null, $handlers); $result = array_merge($result, self::getHandlersClasses()); } self::$handlers = array_keys($result); /** * @var \Bitrix\Sale\Delivery\Services\Base $handler */ foreach(self::$handlers as $idx => $handler) { if(!$handler::isHandlerCompatible()) { unset(self::$handlers[$idx]); continue; } $profiles = $handler::getChildrenClassNames(); if(!empty($profiles)) { self::$handlers = array_merge(self::$handlers, $profiles); } } return true; } /** * @return array Handler Classes * @throws \Bitrix\Main\IO\FileNotFoundException */ protected static function getHandlersClasses() { $result = array(); foreach(self::$handlersDirectories as $handlersDirectory) { $dirPath = $_SERVER['DOCUMENT_ROOT'].$handlersDirectory; if(!Directory::isDirectoryExists($dirPath)) continue; $dir = new Directory($_SERVER['DOCUMENT_ROOT'].$handlersDirectory); foreach ($dir->getChildren() as $handler) { if (!$handler->isDirectory()) continue; /** @var Directory $handler */ $handlerDir = $handler->getPath(); $handlerPath = $handlerDir.'/handler.php'; if(!File::isFileExists($handlerPath)) continue; $handlerClassName = ucfirst($handler->getName().'Handler'); $fullClassName = '\Sale\Handlers\Delivery\\'.$handlerClassName; $result[$fullClassName] = $handlersDirectory.$handler->getName().'/handler.php'; require_once($handlerPath); } } return $result; } /** * @return array Known delivery services handlers * @throws SystemException */ public static function getHandlersList() { if(self::$handlers === null) self::initHandlers(); return self::$handlers; } /** * Calculates the price of the shipment * @param Shipment $shipment * @param int $deliveryId optional * @param array $extraServices optional * @return \Bitrix\Sale\Delivery\CalculationResult * @throws ArgumentNullException */ public static function calculateDeliveryPrice(Shipment $shipment, $deliveryId = 0, $extraServices = array()) { if($deliveryId <=0) $deliveryId = $shipment->getDeliveryId(); $delivery = self::getObjectById($deliveryId); if($delivery) { $result = $delivery->calculate($shipment, $extraServices); } else { $result = new CalculationResult(); $result->addError(new Error("Can't create delivery service object with id: \"".$deliveryId."\"")); } return $result; } /** * Returns id of delivery service group. * Creates if such group does not exist. * @param string $name Group name * @return int Group id * @throws SystemException * @throws \Bitrix\Main\ArgumentException * @throws \Exception */ public static function getGroupId($name) { $res = Table::getList( array( 'select' => array("ID"), 'filter' => array( "=NAME" => $name, "=CLASS_NAME" => '\Bitrix\Sale\Delivery\Services\Group' ) )); if($group = $res->fetch()) { $result = $group["ID"]; } else { $res = self::add(array( "NAME" => $name, "CLASS_NAME" => '\Bitrix\Sale\Delivery\Services\Group', "ACTIVE" => "Y" )); if($res->isSuccess()) $result = $res->getId(); else throw new SystemException(implode("<br>\n",$res->getErrorMessages())); } return $result; } /** * @param int $parentId Delivery service parent id * @return array Delivery service fields * @throws \Bitrix\Main\ArgumentException */ public static function getByParentId($parentId) { $result = array(); $srvList = self::getActiveList(); foreach($srvList as $id => $srv) { if($srv['PARENT_ID'] == $parentId) { $result[$srv['ID']] = $srv; } } return $result; } /** * Returns entity link name for connection with Locations * @return string */ public static function getLocationConnectorEntityName() { return 'Bitrix\Sale\Delivery\DeliveryLocation'; } /** * Adds delivery service * @param array $fields * @return \Bitrix\Main\Entity\AddResult * @throws SystemException * @throws \Exception */ public static function add(array $fields) { self::initHandlers(); $res = \Bitrix\Sale\Delivery\Services\Table::add($fields); if($res->isSuccess()) { if(!empty($fields["CLASS_NAME"])) $fields["CLASS_NAME"]::onAfterAdd($res->getId(), $fields); if(!empty($fields['CODE'])) self::setIdCodeCached($res->getId(), $fields['CODE']); } return $res; } /** * Updates delivery service * @param int $id * @param array $fields * @return \Bitrix\Main\Entity\UpdateResult * @throws SystemException * @throws \Exception */ public static function update($id, array $fields) { self::initHandlers(); $res = \Bitrix\Sale\Delivery\Services\Table::update($id, $fields); if($res->isSuccess()) { if(!empty($fields["CLASS_NAME"]) && class_exists($fields["CLASS_NAME"])) $fields["CLASS_NAME"]::onAfterUpdate($res->getId(), $fields); if(isset($fields['CODE'])) self::cleanIdCodeCached($id); } return $res; } /** * Deletes delivery service * @param int $id * @return \Bitrix\Main\Result * @throws ArgumentNullException * @throws SystemException * @throws \Bitrix\Main\ArgumentException * @throws \Exception */ public static function delete($id) { if(intval($id) <= 0) throw new ArgumentNullException('id'); $res = self::checkServiceUsage($id); if(!$res->isSuccess()) return $res; self::initHandlers(); $res = Table::getList(array( 'filter' => array( 'ID' => $id ), 'select' => array('ID', 'CLASS_NAME', 'LOGOTIP') )); $className = ''; $logotip = 0; if($service = $res->fetch()) { $className = $service['CLASS_NAME']; $logotip = intval($service['LOGOTIP']); } $res = \Bitrix\Sale\Delivery\Services\Table::delete($id); if($res->isSuccess()) { if(!empty($className) && class_exists($className)) $className::onAfterDelete($id); self::deleteRelatedEntities($id); if($logotip > 0) \CFile::Delete($logotip); } return $res; } /** * @return array * registerEventHandler( * 'sale', 'OnGetBusinessValueConsumers', 'sale', * '\Bitrix\Sale\Delivery\Services\Manager', * 'onGetBusinessValueConsumers'); */ public static function onGetBusinessValueConsumers() { static $result = null; if($result !== null) return $result; $result = array(); $handlers = self::getHandlersList(); $consumers = array(); /** @var Base $handlerClassName */ foreach($handlers as $handlerClassName) { $tmpCons = $handlerClassName::onGetBusinessValueConsumers(); /** @var string $handlerClassName*/ if(!empty($tmpCons)) $consumers[$handlerClassName] = $tmpCons; } $res = Table::getList(array( 'filter' => array( '=CLASS_NAME' => array_keys($consumers), '=ACTIVE' => 'Y' ), 'select' => array('ID', 'CLASS_NAME', 'NAME') )); while($dlv = $res->fetch()) { $result['DELIVERY_'.$dlv['ID']] = $consumers[$dlv['CLASS_NAME']]; $result['DELIVERY_'.$dlv['ID']]['NAME'] = $dlv['NAME']; } return $result; } public static function onGetBusinessValueGroups() { $result = array( 'DELIVERY' => array('NAME' => Loc::getMessage('SALE_DLVR_MNGR_DLV_SRVS'), 'SORT' => 100), ); $handlers = self::getHandlersList(); /** @var Base $handlerClassName */ foreach($handlers as $handlerClassName) $result = array_merge($result, $handlerClassName::onGetBusinessValueGroups()); return $result; } /** * Sets fields values to all children * @param int $id * @param array $fields * @return int count modified children * @throws \Bitrix\Main\ArgumentException */ public static function setChildrenFieldsValues($id, array $fields) { if(empty($fields)) return 0; $counter = 0; $res = Table::getList(array( 'filter' => array('PARENT_ID' => $id), 'select' => array('ID') )); while($child = $res->fetch()) { $ures = self::update($child['ID'], $fields); if($ures->isSuccess()) $counter++; $counter += self::setChildrenFieldsValues($child['ID'], $fields); } return $counter; } /** * @param string $code * @return int Service id * @throws \Bitrix\Main\ArgumentException */ public static function getIdByCode($code) { $result = self::getIdCodeCached($code, "code"); if($result !== false) return $result; foreach(self::$cachedFields as $id => $srv) { if($srv['CODE'] == $code) { $result = $id; } } if(intval($result) <= 0) { $res = Table::getList(array( 'filter' => array( '=CODE' => $code ) )); if($handler = $res->fetch()) { $result = $handler["ID"]; self::$cachedFields[$handler["ID"]] = $handler; } } $result = intval($result); self::setIdCodeCached($result, $code); return $result; } /** * @param int $id * @return string Delivery service code * @throws \Bitrix\Main\ArgumentException */ public static function getCodeById($id) { $result = self::getIdCodeCached($id, "id"); if($result !== false) return $result; $srv = self::getById($id); $result = $srv['CODE']; self::setIdCodeCached($id, $result); return $result; } /** * * @param $value * @param $type * @return int|string Id or Code of delivery service */ protected static function getIdCodeCached($value, $type) { $result = false; $ttl = 315360000; $cacheId = "SALE_DELIVERY_ID_CODE_MAP_".($type == "id" ? "I" : "C")."_".$value; $cacheManager = \Bitrix\Main\Application::getInstance()->getManagedCache(); if($cacheManager->read($ttl, $cacheId)) $result = $cacheManager->get($cacheId); return $result; } /** * Saves relation between Id an code of delivery service * @param int $id * @param string $code */ protected static function setIdCodeCached($id, $code) { $cacheManager = \Bitrix\Main\Application::getInstance()->getManagedCache(); $cacheManager->set("SALE_DELIVERY_ID_CODE_MAP_I_".$id, $code); $cacheManager->set("SALE_DELIVERY_ID_CODE_MAP_C_".$code, $id); } /** * Cleans cache of delivery service id-code relation * @param int $id */ protected static function cleanIdCodeCached($id) { $cacheManager = \Bitrix\Main\Application::getInstance()->getManagedCache(); $code = self::getIdCodeCached($id, "id"); $cacheManager->clean("SALE_DELIVERY_ID_CODE_MAP_I_".$id); if(strlen($code) > 0) $cacheManager->clean("SALE_DELIVERY_ID_CODE_MAP_C_".$code); } /** * Returns is delivery service is already used in shipments * @param $deliveryId * @return bool * @throws \Bitrix\Main\ArgumentException */ protected static function isDeliveryInShipments($deliveryId) { $res = ShipmentTable::getList(array( 'filter' => array( "=DELIVERY_ID" => $deliveryId, "=SYSTEM" => "N" ), 'select' => array("ID") )); if($res->fetch()) $result = true; else $result = false; return $result; } /** * Returns if delivery service and it's children are used in shipments * @param $deliveryId * @return Result * @throws \Bitrix\Main\ArgumentException */ public static function checkServiceUsage($deliveryId) { $result = new Result(); if(self::isDeliveryInShipments($deliveryId)) { $result->addError(new Error(Loc::getMessage('SALE_DLVR_MNGR_ERR_DEL_IN_SHPMNTS_EXIST'))); } else { $dbRes = Table::getList(array( 'filter' => array( "PARENT_ID" => $deliveryId ), 'select' => array("ID") )); while($child = $dbRes->fetch()) { if(self::isDeliveryInShipments($child["ID"])) { $result->addError(new Error(Loc::getMessage('SALE_DLVR_MNGR_ERR_DEL_IN_SHPMNTS_EXIST_CHLD'))); break; } } } return $result; } /** * Deletes related entities * @param int $deliveryId * @return bool * @throws ArgumentNullException * @throws \Bitrix\Main\ArgumentException * todo: restrictions, extra_services - can require some actions after deletion */ protected static function deleteRelatedEntities($deliveryId) { $con = \Bitrix\Main\Application::getConnection(); $deliveryId = (int)$deliveryId; $con->queryExecute("DELETE FROM b_sale_service_rstr WHERE SERVICE_ID=".$deliveryId); $con->queryExecute("DELETE FROM b_sale_delivery2location WHERE DELIVERY_ID=".$deliveryId); $con->queryExecute("DELETE FROM b_sale_delivery2paysystem WHERE DELIVERY_ID=".$deliveryId); $con->queryExecute("DELETE FROM b_sale_delivery_es WHERE DELIVERY_ID=".$deliveryId); $dbRes = Table::getList(array( 'filter' => array( "PARENT_ID" => $deliveryId ), 'select' => array("ID") )); while($child = $dbRes->fetch()) self::delete($child["ID"]); self::cleanIdCodeCached($deliveryId); return true; } /** * @return int Empty delivery service id * @throws SystemException */ public static function getEmptyDeliveryServiceId() { self::initHandlers(); return \Bitrix\Sale\Delivery\Services\EmptyDeliveryService::getEmptyDeliveryServiceId(); } /** * @internal * @param int|int[] $deliveryId * @param mixed $checkParams * @param string $restrictionClassName * @return bool|int[] * @throws ArgumentNullException * @throws SystemException * @throws \Bitrix\Main\ArgumentException * @throws \Bitrix\Main\NotImplementedException */ public static function checkServiceRestriction($deliveryId, $checkParams, $restrictionClassName) { if(empty($deliveryId)) throw new ArgumentNullException("deliveryId"); if(!is_array($deliveryId)) $deliveryId = array($deliveryId); $dbRstrRes = ServiceRestrictionTable::getList(array( 'filter' => array( '=SERVICE_ID' => $deliveryId, '=SERVICE_TYPE' => Restrictions\Manager::SERVICE_TYPE_SHIPMENT, '=CLASS_NAME' => $restrictionClassName ) )); $tmp = array(); /** @var Restrictions\Base $restriction */ $restriction = static::getRestrictionObject($restrictionClassName); while($rstFields = $dbRstrRes->fetch()) { $rstParams = is_array($rstFields["PARAMS"]) ? $rstFields["PARAMS"] : array(); $tmp[$rstFields['SERVICE_ID']] = $restriction->check($checkParams, $rstParams, $rstFields['SERVICE_ID']); } if(count($deliveryId) == 1) return current($tmp); $result = array(); foreach($deliveryId as $id) if(!isset($tmp[$id]) || (isset($tmp[$id]) && $tmp[$id] == true)) $result[] = $id; return $result; } /** * Check if given class is valid delivery service class * inheritance of Bitrix\Sale\Delivery\Services\Base. * @param string $class Checking class. * @return bool */ public static function isDeliveryServiceClassValid($class) { if(strlen($class) <= 0) return false; self::initHandlers(); if(!class_exists($class)) return false; if(!is_subclass_of($class, 'Bitrix\Sale\Delivery\Services\Base')) return false; return true; } /* * Deprecated methods. Will be removed in future versions. */ /** * @deprecated use \Bitrix\Sale\Delivery\Services\Manager::calculateDeliveryPrice() */ public static function calculate(Shipment $shipment) { $delivery = self::getObjectById($shipment->getDeliveryId()); return $delivery->calculate($shipment); } /** * @deprecated will be remove in next versions */ public static function getRestrictionObject($className) { if(!class_exists($className)) throw new SystemException("Can't find class: ".$className); static $cache = array(); if(isset($cache[$className])) return $cache[$className]; $restriction = new $className; if(!($restriction instanceof Restrictions\Base)) throw new SystemException('Object must be the instance of Bitrix\Sale\Delivery\Restrictions\Base'); $cache[$className] = $restriction; return $restriction; } /** * @deprecated use Restrictions\Manager::checkService() */ public static function checkServiceRestrictions($deliveryId, Shipment $shipment, $restrictionsClassesToSkip = array()) { return Restrictions\Manager::checkService($deliveryId, $shipment) == Restrictions\Manager::SEVERITY_NONE; } /** * @deprecated use \Bitrix\Sale\Delivery\Services\Manager::getRestrictedObjectsList() */ public static function getServicesForShipment(Shipment $shipment) { return self::getRestrictedObjectsList($shipment); } /** * @deprecated use \Bitrix\Sale\Delivery\Services\Manager::isServiceExist() */ public static function isExistService($deliveryId) { return self::isServiceExist($deliveryId); } /** * @deprecated use \Bitrix\Sale\Delivery\Services\Manager::getActiveList() */ public static function getActive() { return self::getActiveList(); } /** * @deprecated use \Bitrix\Sale\Delivery\Services\Manager::getRestrictedList() */ public static function getServicesBriefsForShipment(Shipment $shipment = null, array $skipChecks = array(), $getAll = false) { return self::getRestrictedList($shipment, Restrictions\Manager::MODE_CLIENT, $skipChecks); } /** * @deprecated use \Bitrix\Sale\Delivery\Services\Manager::createObject() */ public static function createServiceObject(array $srvParams) { return self::createObject($srvParams); } /** * @deprecated use \Bitrix\Sale\Delivery\Services\Manager::getObjectById() */ public static function getService($deliveryId) { return self::getObjectById($deliveryId); } /** * @deprecated use \Bitrix\Sale\Delivery\Services\Manager::getServiceByCode() */ public static function getServiceByCode($serviceCode) { return self::getObjectByCode($serviceCode); } /** * @deprecated use \Bitrix\Sale\Delivery\Services\Manager::getHandlersList() */ public static function getHandlersClassNames() { return self::getHandlersList(); } /** * @deprecated use Restrictions\Manager::getClassesList() */ public static function getRestrictionClassNames() { return Restrictions\Manager::getClassesList(); } /** * @deprecated use Restrictions\Manager::getRestrictionsList() */ public static function getRestrictionsByDeliveryId($deliveryId) { return Restrictions\Manager::getRestrictionsList($deliveryId); } }