PageRenderTime 40ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/sale/lib/internals/delivery_paysystem.php

https://gitlab.com/alexprowars/bitrix
PHP | 863 lines | 716 code | 106 blank | 41 comment | 90 complexity | 0fef601b086b3ac5cc7fabd4b118ebd9 MD5 | raw file
  1. <?php
  2. namespace Bitrix\Sale\Internals;
  3. use Bitrix\Main\ArgumentNullException;
  4. use Bitrix\Main\ArgumentOutOfRangeException;
  5. use Bitrix\Main\Localization\Loc;
  6. use Bitrix\Sale\Delivery\Restrictions;
  7. use Bitrix\Sale\Delivery\Services;
  8. use Bitrix\Sale\Services\PaySystem\Restrictions\Manager;
  9. use Bitrix\Sale\PaySystem;
  10. Loc::loadMessages(__FILE__);
  11. /**
  12. * Class DeliveryPaySystemTable
  13. *
  14. * Fields:
  15. * <ul>
  16. * <li> DELIVERY_ID string(35) mandatory
  17. * <li> PAYSYSTEM_ID int mandatory
  18. * </ul>
  19. *
  20. * @package Bitrix\Sale
  21. *
  22. * DO NOT WRITE ANYTHING BELOW THIS
  23. *
  24. * <<< ORMENTITYANNOTATION
  25. * @method static EO_DeliveryPaySystem_Query query()
  26. * @method static EO_DeliveryPaySystem_Result getByPrimary($primary, array $parameters = array())
  27. * @method static EO_DeliveryPaySystem_Result getById($id)
  28. * @method static EO_DeliveryPaySystem_Result getList(array $parameters = array())
  29. * @method static EO_DeliveryPaySystem_Entity getEntity()
  30. * @method static \Bitrix\Sale\Internals\EO_DeliveryPaySystem createObject($setDefaultValues = true)
  31. * @method static \Bitrix\Sale\Internals\EO_DeliveryPaySystem_Collection createCollection()
  32. * @method static \Bitrix\Sale\Internals\EO_DeliveryPaySystem wakeUpObject($row)
  33. * @method static \Bitrix\Sale\Internals\EO_DeliveryPaySystem_Collection wakeUpCollection($rows)
  34. */
  35. class DeliveryPaySystemTable extends \Bitrix\Main\Entity\DataManager
  36. {
  37. const LINK_DIRECTION_DELIVERY_PAYSYSTEM = "D";
  38. const LINK_DIRECTION_PAYSYSTEM_DELIVERY = "P";
  39. const ENTITY_TYPE_DELIVERY = "DELIVERY_ID";
  40. const ENTITY_TYPE_PAYSYSTEM = "PAYSYSTEM_ID";
  41. protected static $unLinked = null;
  42. protected static $entityItemsFullList = array();
  43. protected static $entityItemsFieldsList = array();
  44. public static function getFilePath()
  45. {
  46. return __FILE__;
  47. }
  48. public static function getTableName()
  49. {
  50. return 'b_sale_delivery2paysystem';
  51. }
  52. public static function getMap()
  53. {
  54. return array(
  55. 'DELIVERY_ID' => array(
  56. 'primary' => true,
  57. 'data_type' => 'integer',
  58. 'required' => true,
  59. 'title' => Loc::getMessage('DELIVERY_PAYSYSTEM_ENTITY_DELIVERY_ID_FIELD'),
  60. ),
  61. 'DELIVERY' => array(
  62. 'data_type' => '\Bitrix\Sale\Delivery\Services\Table',
  63. 'reference' => array(
  64. '=this.DELIVERY_ID' => 'ref.ID'
  65. )
  66. ),
  67. 'LINK_DIRECTION' => array(
  68. 'primary' => true,
  69. 'data_type' => 'string',
  70. 'validation' => array(__CLASS__, 'validateLinkDirection'),
  71. 'required' => true,
  72. 'title' => Loc::getMessage('DELIVERY_PAYSYSTEM_ENTITY_LINK_DIRECTION'),
  73. ),
  74. 'PAYSYSTEM_ID' => array(
  75. 'primary' => true,
  76. 'data_type' => 'integer',
  77. 'required' => true,
  78. 'title' => Loc::getMessage('DELIVERY_PAYSYSTEM_ENTITY_PAYSYSTEM_ID_FIELD'),
  79. ),
  80. 'PAYSYSTEM' => array(
  81. 'data_type' => '\Bitrix\Sale\Internals\PaySystemActionTable',
  82. 'reference' => array(
  83. '=this.PAYSYSTEM_ID' => 'ref.ID'
  84. )
  85. )
  86. );
  87. }
  88. public static function validateLinkDirection()
  89. {
  90. return array(
  91. new \Bitrix\Main\Entity\Validator\Length(1, 1),
  92. );
  93. }
  94. /**
  95. * @param int $entityId
  96. * @param string $entityType self::ENTITY_TYPE_DELIVERY || self::ENTITY_TYPE_PAYSYSTEM
  97. * @param int[] $linkedIds Empty means all
  98. * @return \Bitrix\Main\Entity\Result
  99. * @throws ArgumentNullException
  100. * @throws ArgumentOutOfRangeException
  101. * @throws \Bitrix\Main\ArgumentException
  102. */
  103. public static function setLinks($entityId, $entityType, array $linkedIds = array(), $actualizeRestrictions = true)
  104. {
  105. if(intval($entityId) <= 0)
  106. throw new ArgumentNullException("entityId");
  107. if($entityType != self::ENTITY_TYPE_DELIVERY && $entityType != self::ENTITY_TYPE_PAYSYSTEM)
  108. throw new ArgumentOutOfRangeException("entityType");
  109. $result = new \Bitrix\Main\Entity\Result();
  110. $con = \Bitrix\Main\Application::getConnection();
  111. $sqlHelper = $con->getSqlHelper();
  112. $entityId = $sqlHelper->forSql($entityId);
  113. $reverseParentLinks = array();
  114. if($entityType == self::ENTITY_TYPE_DELIVERY)
  115. {
  116. $linkDirection = self::LINK_DIRECTION_DELIVERY_PAYSYSTEM ;
  117. $reverseLinkDirection = self::LINK_DIRECTION_PAYSYSTEM_DELIVERY;
  118. $reverseEntityType = self::ENTITY_TYPE_PAYSYSTEM;
  119. $parentId = self::getDeliveryParentId($entityId);
  120. }
  121. else
  122. {
  123. $linkDirection = self::LINK_DIRECTION_PAYSYSTEM_DELIVERY;
  124. $reverseLinkDirection = self::LINK_DIRECTION_DELIVERY_PAYSYSTEM;
  125. $reverseEntityType = self::ENTITY_TYPE_DELIVERY;
  126. $parentId = 0;
  127. if(!empty($linkedIds)) // for delivery profiles
  128. {
  129. $reverseFieldsList = self::getEntityItemsFieldsList($reverseEntityType);
  130. foreach($linkedIds as $id)
  131. if(isset($reverseFieldsList[$id]['PARENT_ID']) && self::isValidParent($reverseFieldsList[$id]['PARENT_ID'], $reverseEntityType))
  132. if(!in_array($reverseFieldsList[$id]['PARENT_ID'], $linkedIds))
  133. $reverseParentLinks[] = $reverseFieldsList[$id]['PARENT_ID'];
  134. if(!empty($reverseParentLinks))
  135. {
  136. $linkedIds = array_unique(array_merge($linkedIds, $reverseParentLinks));
  137. }
  138. }
  139. }
  140. //delete current entity links
  141. $con->queryExecute(
  142. "DELETE FROM ".self::getTableName().
  143. " WHERE ".$entityType."=".$entityId ." AND LINK_DIRECTION='".$linkDirection."'"
  144. );
  145. //insert new links
  146. if(!empty($linkedIds))
  147. self::insertLinks($entityId, $linkDirection, $entityType, $linkedIds);
  148. $glParams = array(
  149. 'filter' => array(
  150. '=LINK_DIRECTION' => $reverseLinkDirection,
  151. )
  152. );
  153. if(!empty($linkedIds))
  154. $glParams['filter'][$reverseEntityType] = $linkedIds;
  155. $res = self::getList($glParams);
  156. $linkedToEntity = array();
  157. $linkedToOther = array();
  158. while($rec = $res->fetch())
  159. {
  160. if($rec[$entityType] == $entityId)
  161. {
  162. if(!in_array($rec[$reverseEntityType], $linkedToEntity))
  163. $linkedToEntity[] = $rec[$reverseEntityType];
  164. }
  165. else
  166. {
  167. if(!in_array($rec[$reverseEntityType], $linkedToOther))
  168. $linkedToOther[] = $rec[$reverseEntityType];
  169. }
  170. }
  171. $reverseIdsToAdd = array_diff($linkedToOther, $linkedToEntity);
  172. //set reverse links to current entity
  173. if(!empty($reverseIdsToAdd))
  174. self::insertLinks($entityId, $reverseLinkDirection, $entityType, $reverseIdsToAdd);
  175. //delete reverse links we didn't choose
  176. $glParams = array(
  177. 'filter' => array(
  178. '=LINK_DIRECTION' => $reverseLinkDirection,
  179. '='.$entityType => $entityId,
  180. )
  181. );
  182. if(!empty($linkedIds))
  183. $glParams['filter']['!='.$reverseEntityType] = $linkedIds;
  184. $res = self::getList($glParams);
  185. while($rec = $res->fetch())
  186. {
  187. self::delete(array(
  188. 'DELIVERY_ID' => $rec['DELIVERY_ID'],
  189. 'PAYSYSTEM_ID' => $rec['PAYSYSTEM_ID'],
  190. 'LINK_DIRECTION' => $rec['LINK_DIRECTION']
  191. ));
  192. }
  193. self::$unLinked = null;
  194. //Modify delivery parent links for working profile links.
  195. if(!empty($linkedIds))
  196. {
  197. $unlinked = self::getUnlinkedEnityItems($entityType);
  198. if($entityType == self::ENTITY_TYPE_DELIVERY && self::isValidParent($parentId, $entityType) && !in_array($parentId, $unlinked))
  199. {
  200. $parentLinks = self::getLinks($parentId, $entityType, array(), false);
  201. self::setLinks(
  202. $parentId,
  203. $entityType,
  204. array_unique(array_merge($parentLinks, $linkedIds)),
  205. false
  206. );
  207. }
  208. elseif($entityType == self::ENTITY_TYPE_PAYSYSTEM)
  209. {
  210. $reverseFieldsList = self::getEntityItemsFieldsList($reverseEntityType);
  211. $unlinkedReverse = self::getUnlinkedEnityItems($reverseEntityType);
  212. $entityList = self::getEntityItemsFullList($entityType);
  213. $entityList = array_diff($entityList, array($entityId));
  214. foreach($reverseFieldsList as $id => $fields)
  215. {
  216. if(intval($fields['PARENT_ID']) > 0 && in_array($fields['PARENT_ID'], $reverseParentLinks) && in_array($id, $unlinkedReverse))
  217. {
  218. self::setLinks(
  219. $id,
  220. $reverseEntityType,
  221. $entityList,
  222. false
  223. );
  224. }
  225. }
  226. }
  227. }
  228. if($actualizeRestrictions)
  229. {
  230. self::actualizeDeliveriesRestrictionByPS();
  231. self::actualizePaySystemRestrictionByDelivery();
  232. }
  233. return $result;
  234. }
  235. protected static function isValidParent($parentId, $entityType)
  236. {
  237. $parentId = intval($parentId);
  238. if($parentId <= 0)
  239. return false;
  240. if($entityType == self::ENTITY_TYPE_DELIVERY)
  241. {
  242. $activeDeliveryData = self::getActiveDeliveryData();
  243. if(!in_array($parentId, array_keys($activeDeliveryData)))
  244. return false;
  245. if($activeDeliveryData[$parentId]['PARENT_CLASS_NAME'] == '\Bitrix\Sale\Delivery\Services\Group')
  246. return false;
  247. }
  248. return true;
  249. }
  250. protected static function actualizeDeliveriesRestrictionByPS()
  251. {
  252. $con = \Bitrix\Main\Application::getConnection();
  253. $sqlHelper = $con->getSqlHelper();
  254. $restrictions = array();
  255. $dbR = \Bitrix\Sale\Internals\ServiceRestrictionTable::getList(array(
  256. 'filter' => array(
  257. '=CLASS_NAME' => '\Bitrix\Sale\Delivery\Restrictions\ByPaySystem'
  258. ),
  259. 'select' => array('SERVICE_ID')
  260. ));
  261. while($restr = $dbR->fetch())
  262. $restrictions[] = $restr['SERVICE_ID'];
  263. $deliveryList = self::getEntityItemsFullList(self::ENTITY_TYPE_DELIVERY);
  264. $dLinkedToP = array();
  265. $deliveriesToPs = array();
  266. $linkedPS = array();
  267. $dbP2S = DeliveryPaySystemTable::getList();
  268. while($d2p = $dbP2S->fetch())
  269. {
  270. if($d2p["LINK_DIRECTION"] == self::LINK_DIRECTION_DELIVERY_PAYSYSTEM && !in_array($d2p["DELIVERY_ID"], $dLinkedToP))
  271. $dLinkedToP[] = $d2p["DELIVERY_ID"];
  272. if($d2p["LINK_DIRECTION"] == self::LINK_DIRECTION_PAYSYSTEM_DELIVERY )
  273. {
  274. if(!isset($deliveriesToPs[$d2p["DELIVERY_ID"]]))
  275. $deliveriesToPs[$d2p["DELIVERY_ID"]] = array();
  276. $linkedPS[] = $d2p["PAYSYSTEM_ID"];
  277. $deliveriesToPs[$d2p["DELIVERY_ID"]][] = $d2p["PAYSYSTEM_ID"];
  278. }
  279. }
  280. $notLinkedToPS = array_diff($deliveryList, $dLinkedToP);
  281. $existLinkedPs = !empty($linkedPS);
  282. $notNeedRestriction = array();
  283. $needRestriction = array();
  284. foreach($deliveryList as $id)
  285. {
  286. $need = true;
  287. //DS not linked to PS and (All PS having links linked to current DS
  288. if(in_array($id, $notLinkedToPS))
  289. {
  290. if(isset($deliveriesToPs[$id]))
  291. $diff = array_diff($linkedPS, $deliveriesToPs[$id]);
  292. else
  293. $diff = $linkedPS;
  294. if(!$existLinkedPs || empty($diff))
  295. {
  296. $notNeedRestriction[] = $id;
  297. $need = false;
  298. }
  299. }
  300. // DS linked to PS or exist linked PS but not linked to current DS
  301. if($need)
  302. $needRestriction[] = $id;
  303. }
  304. $notNeedRestriction = array_intersect($notNeedRestriction, $restrictions);
  305. if(!empty($notNeedRestriction))
  306. {
  307. $sql = "";
  308. foreach($notNeedRestriction as $deliveryId)
  309. $sql .= " ".($sql == "" ? "WHERE CLASS_NAME='".$sqlHelper->forSql('\Bitrix\Sale\Delivery\Restrictions\ByPaySystem')."' AND (" : "OR " )."SERVICE_ID=".$sqlHelper->forSql($deliveryId)." AND SERVICE_TYPE=".Restrictions\Manager::SERVICE_TYPE_SHIPMENT;
  310. $sql = "DELETE FROM ".\Bitrix\Sale\Internals\ServiceRestrictionTable::getTableName().$sql.")";
  311. $con->queryExecute($sql);
  312. }
  313. $needRestriction = array_diff($needRestriction, $restrictions);
  314. //let's... add missing
  315. if(!empty($needRestriction))
  316. {
  317. $sql = "";
  318. foreach($needRestriction as $deliveryId)
  319. $sql .= ($sql == "" ? " " : ", ")."(".$sqlHelper->forSql($deliveryId).", '".$sqlHelper->forSql('\Bitrix\Sale\Delivery\Restrictions\ByPaySystem')."', ".Restrictions\Manager::SERVICE_TYPE_SHIPMENT.")";
  320. $sql = "INSERT INTO ".\Bitrix\Sale\Internals\ServiceRestrictionTable::getTableName()."(SERVICE_ID, CLASS_NAME, SERVICE_TYPE) VALUES".$sql;
  321. $con->queryExecute($sql);
  322. }
  323. }
  324. protected static function actualizePaySystemRestrictionByDelivery()
  325. {
  326. $con = \Bitrix\Main\Application::getConnection();
  327. $sqlHelper = $con->getSqlHelper();
  328. $restrictions = array();
  329. $dbR = \Bitrix\Sale\Internals\ServiceRestrictionTable::getList(array(
  330. 'filter' => array(
  331. '=CLASS_NAME' => '\\'.\Bitrix\Sale\Services\PaySystem\Restrictions\Delivery::class
  332. ),
  333. 'select' => array('SERVICE_ID')
  334. ));
  335. while($restr = $dbR->fetch())
  336. $restrictions[] = $restr['SERVICE_ID'];
  337. $deliveryList = self::getEntityItemsFullList(self::ENTITY_TYPE_PAYSYSTEM);
  338. $dLinkedToP = array();
  339. $deliveriesToPs = array();
  340. $linkedPS = array();
  341. $dbP2S = DeliveryPaySystemTable::getList();
  342. while($d2p = $dbP2S->fetch())
  343. {
  344. if($d2p["LINK_DIRECTION"] == self::LINK_DIRECTION_PAYSYSTEM_DELIVERY && !in_array($d2p["PAYSYSTEM_ID"], $dLinkedToP))
  345. $dLinkedToP[] = $d2p["PAYSYSTEM_ID"];
  346. if($d2p["LINK_DIRECTION"] == self::LINK_DIRECTION_DELIVERY_PAYSYSTEM)
  347. {
  348. if(!isset($deliveriesToPs[$d2p["PAYSYSTEM_ID"]]))
  349. $deliveriesToPs[$d2p["PAYSYSTEM_ID"]] = array();
  350. $linkedPS[] = $d2p["DELIVERY_ID"];
  351. $deliveriesToPs[$d2p["PAYSYSTEM_ID"]][] = $d2p["DELIVERY_ID"];
  352. }
  353. }
  354. $notLinkedToPS = array_diff($deliveryList, $dLinkedToP);
  355. $existLinkedPs = !empty($linkedPS);
  356. $notNeedRestriction = array();
  357. $needRestriction = array();
  358. foreach($deliveryList as $id)
  359. {
  360. $need = true;
  361. //DS not linked to PS and (All PS having links linked to current DS
  362. if(in_array($id, $notLinkedToPS))
  363. {
  364. if(isset($deliveriesToPs[$id]))
  365. $diff = array_diff($linkedPS, $deliveriesToPs[$id]);
  366. else
  367. $diff = $linkedPS;
  368. if(!$existLinkedPs || empty($diff))
  369. {
  370. $notNeedRestriction[] = $id;
  371. $need = false;
  372. }
  373. }
  374. // DS linked to PS or exist linked PS but not linked to current DS
  375. if($need)
  376. $needRestriction[] = $id;
  377. }
  378. $notNeedRestriction = array_intersect($notNeedRestriction, $restrictions);
  379. if(!empty($notNeedRestriction))
  380. {
  381. $sql = "";
  382. foreach($notNeedRestriction as $deliveryId)
  383. $sql .= " ".($sql == "" ? "WHERE CLASS_NAME='".$sqlHelper->forSql('\Bitrix\Sale\Services\PaySystem\Restrictions\Delivery')."' AND (" : "OR " )."SERVICE_ID=".$sqlHelper->forSql($deliveryId)." AND SERVICE_TYPE=".Manager::SERVICE_TYPE_PAYMENT;
  384. $sql = "DELETE FROM ".\Bitrix\Sale\Internals\ServiceRestrictionTable::getTableName().$sql.")";
  385. $con->queryExecute($sql);
  386. }
  387. $needRestriction = array_diff($needRestriction, $restrictions);
  388. //let's... add missing
  389. if(!empty($needRestriction))
  390. {
  391. $sql = "";
  392. foreach($needRestriction as $deliveryId)
  393. $sql .= ($sql == "" ? " " : ", ")."(".$sqlHelper->forSql($deliveryId).", '".$sqlHelper->forSql('\\'.\Bitrix\Sale\Services\PaySystem\Restrictions\Delivery::class)."', ".Manager::SERVICE_TYPE_PAYMENT.")";
  394. $sql = "INSERT INTO ".\Bitrix\Sale\Internals\ServiceRestrictionTable::getTableName()."(SERVICE_ID, CLASS_NAME, SERVICE_TYPE) VALUES".$sql;
  395. $con->queryExecute($sql);
  396. }
  397. }
  398. protected static function insertLinks($entityId, $linkDirection, $entityType, $linkedIds)
  399. {
  400. $con = \Bitrix\Main\Application::getConnection();
  401. $sqlHelper = $con->getSqlHelper();
  402. $entityId = (int)$entityId;
  403. $linkDirection = $sqlHelper->forSql($linkDirection);
  404. $sql = "INSERT INTO ".
  405. self::getTableName().
  406. "(DELIVERY_ID, PAYSYSTEM_ID, LINK_DIRECTION) ".
  407. "VALUES";
  408. $first = true;
  409. foreach($linkedIds as $id)
  410. {
  411. if(!$first)
  412. $sql .= ",";
  413. else
  414. $first = false;
  415. $id = (int)$id;
  416. if($entityType == self::ENTITY_TYPE_DELIVERY)
  417. $sql .= " (".$entityId.", ".$id;
  418. else
  419. $sql .= " (".$id.", ".$entityId;
  420. $sql .= ", '".$linkDirection."')";
  421. }
  422. $con->queryExecute($sql);
  423. }
  424. /**
  425. * @param int $entityId
  426. * @param string $entityType self::ENTITY_TYPE_DELIVERY || self::ENTITY_TYPE_PAYSYSTEM
  427. * @return int[]
  428. * @throws ArgumentNullException
  429. * @throws ArgumentOutOfRangeException
  430. * @throws \Bitrix\Main\ArgumentException
  431. */
  432. public static function getLinks($entityId, $entityType, array $preparedData = array(), $considerParent = true)
  433. {
  434. $result = array();
  435. if(intval($entityId) <= 0)
  436. return array();
  437. if($entityType != self::ENTITY_TYPE_DELIVERY && $entityType != self::ENTITY_TYPE_PAYSYSTEM)
  438. throw new ArgumentOutOfRangeException("entityType");
  439. if($entityType == self::ENTITY_TYPE_DELIVERY)
  440. {
  441. $linkDirection = self::LINK_DIRECTION_DELIVERY_PAYSYSTEM;
  442. $reverseLinkDirection = self::LINK_DIRECTION_PAYSYSTEM_DELIVERY;
  443. $reverseEntityType = self::ENTITY_TYPE_PAYSYSTEM;
  444. $parentId = self::getDeliveryParentId($entityId);
  445. }
  446. else
  447. {
  448. $linkDirection = self::LINK_DIRECTION_PAYSYSTEM_DELIVERY;
  449. $reverseLinkDirection = self::LINK_DIRECTION_DELIVERY_PAYSYSTEM;
  450. $reverseEntityType = self::ENTITY_TYPE_DELIVERY;
  451. $parentId = 0;
  452. }
  453. if(isset($preparedData[$entityId]["DIRECT"]))
  454. {
  455. $result = $preparedData[$entityId]["DIRECT"];
  456. }
  457. else
  458. {
  459. $glParams = array(
  460. 'filter' => array(
  461. "=".$entityType => $entityId,
  462. "=LINK_DIRECTION" => $linkDirection
  463. ),
  464. 'select' => array($reverseEntityType)
  465. );
  466. $res = self::getList($glParams);
  467. while($rec = $res->fetch())
  468. $result[] = $rec[$reverseEntityType];
  469. }
  470. //if entity has links they must be actual
  471. if(!empty($result))
  472. {
  473. if($considerParent)
  474. {
  475. if($entityType == self::ENTITY_TYPE_PAYSYSTEM)
  476. {
  477. $result = self::includeDeliveryByParent($result);
  478. $result = self::excludeDeliveryByParent($result);
  479. }
  480. elseif($entityType == self::ENTITY_TYPE_DELIVERY && $parentId > 0)
  481. {
  482. $result = self::considerDeliveryParent($result, $entityId, $parentId, $preparedData);
  483. }
  484. }
  485. return $result;
  486. }
  487. if(isset($preparedData[$entityId]["REVERSE"]))
  488. {
  489. $result = $preparedData[$entityId]["REVERSE"];
  490. }
  491. else
  492. {
  493. $glParams = array(
  494. 'filter' => array(
  495. "=".$entityType => $entityId,
  496. "=LINK_DIRECTION" => $reverseLinkDirection
  497. ),
  498. 'select' => array($reverseEntityType)
  499. );
  500. $res = self::getList($glParams);
  501. while($rec = $res->fetch())
  502. $result[] = $rec[$reverseEntityType];
  503. }
  504. $result = array_merge($result, self::getUnlinkedEnityItems($reverseEntityType, $reverseLinkDirection));
  505. if($considerParent)
  506. {
  507. if($entityType == self::ENTITY_TYPE_DELIVERY && $parentId > 0)
  508. {
  509. $result = self::considerDeliveryParent($result, $entityId, $parentId, $preparedData);
  510. }
  511. elseif($entityType == self::ENTITY_TYPE_PAYSYSTEM && !empty($result))
  512. {
  513. $result = self::excludeDeliveryByParent($result);
  514. }
  515. }
  516. return $result;
  517. }
  518. protected static function getActiveDeliveryData()
  519. {
  520. $result = array();
  521. self::getEntityItemsFullList(self::ENTITY_TYPE_DELIVERY);
  522. if(is_array(self::$entityItemsFieldsList[self::ENTITY_TYPE_DELIVERY]))
  523. {
  524. foreach(self::$entityItemsFieldsList[self::ENTITY_TYPE_DELIVERY] as $fields)
  525. {
  526. $result[$fields['ID']] = $fields;
  527. }
  528. }
  529. return $result;
  530. }
  531. protected static function excludeDeliveryByParent(array $dlvIds)
  532. {
  533. $result = array();
  534. $activeDeliveryData = self::getActiveDeliveryData();
  535. foreach($dlvIds as $id)
  536. {
  537. if(intval($activeDeliveryData[$id]['PARENT_ID']) <= 0)
  538. $result[] = $id;
  539. elseif($activeDeliveryData[$id]['PARENT_CLASS_NAME'] == '\Bitrix\Sale\Delivery\Services\Group')
  540. $result[] = $id;
  541. elseif(in_array($activeDeliveryData[$id]['PARENT_ID'], $dlvIds))
  542. $result[] = $id;
  543. }
  544. return $result;
  545. }
  546. protected static function includeDeliveryByParent(array $dlvIds)
  547. {
  548. $result = $dlvIds;
  549. $unlinkedDlvIds = self::getUnlinkedEnityItems(self::ENTITY_TYPE_DELIVERY);
  550. foreach(self::getActiveDeliveryData() as $id => $fields)
  551. {
  552. if(in_array($fields['PARENT_ID'], $dlvIds)) //is profile
  553. if(in_array($id, $unlinkedDlvIds) && !in_array($id, $result)) //profile doesn't have own restriction by PS
  554. $result[] = $id;
  555. }
  556. return $result;
  557. }
  558. protected static function considerDeliveryParent(array $profilePsIds, $profileId, $parentId, $preparedData)
  559. {
  560. if(intval($parentId) <= 0)
  561. return $profilePsIds;
  562. $result = $profilePsIds;
  563. $unlinkedIds = self::getUnlinkedEnityItems(self::ENTITY_TYPE_DELIVERY);
  564. $parentPSIds = self::getLinks($parentId, self::ENTITY_TYPE_DELIVERY, $preparedData);
  565. if(!in_array($parentId, $unlinkedIds) && in_array($profileId, $unlinkedIds))
  566. $result = $parentPSIds;
  567. elseif(!in_array($parentId, $unlinkedIds) && !in_array($profileId, $unlinkedIds))
  568. $result = array_intersect($profilePsIds, $parentPSIds);
  569. return $result;
  570. }
  571. protected static function getDeliveryParentId($deliveryId)
  572. {
  573. $activeData = self::getActiveDeliveryData();
  574. if(empty($activeData[$deliveryId]))
  575. return 0;
  576. $parentId = intval($activeData[$deliveryId]['PARENT_ID']);
  577. if($parentId <= 0 || empty($activeData[$parentId]))
  578. return 0;
  579. if($activeData[$parentId]['CLASS_NAME'] == '\Bitrix\Sale\Delivery\Services\Group')
  580. return 0;
  581. return $parentId;
  582. }
  583. protected static function getUnlinkedEnityItems($entityType, $linkDirection = null)
  584. {
  585. if($entityType != self::ENTITY_TYPE_DELIVERY && $entityType != self::ENTITY_TYPE_PAYSYSTEM)
  586. throw new ArgumentOutOfRangeException('entityType');
  587. if($linkDirection != null)
  588. if($linkDirection != self::LINK_DIRECTION_DELIVERY_PAYSYSTEM && $linkDirection != self::LINK_DIRECTION_PAYSYSTEM_DELIVERY)
  589. throw new ArgumentOutOfRangeException('linkDirection');
  590. if(!isset(self::$unLinked[$entityType]))
  591. {
  592. $entityList = array_flip(self::getEntityItemsFullList($entityType));
  593. self::$unLinked[$entityType] = array(
  594. self::LINK_DIRECTION_DELIVERY_PAYSYSTEM => $entityList,
  595. self::LINK_DIRECTION_PAYSYSTEM_DELIVERY => $entityList
  596. );
  597. $glParams = array(
  598. 'group' => array($entityType, 'LINK_DIRECTION'),
  599. 'select' => array($entityType, 'LINK_DIRECTION')
  600. );
  601. $res = DeliveryPaySystemTable::getList($glParams);
  602. while($row = $res->fetch())
  603. {
  604. if(isset(self::$unLinked[$entityType][$row['LINK_DIRECTION']][$row[$entityType]]))
  605. {
  606. unset(self::$unLinked[$entityType][$row['LINK_DIRECTION']][$row[$entityType]]);
  607. }
  608. }
  609. self::$unLinked[$entityType][self::LINK_DIRECTION_DELIVERY_PAYSYSTEM] = array_keys(self::$unLinked[$entityType][self::LINK_DIRECTION_DELIVERY_PAYSYSTEM]);
  610. self::$unLinked[$entityType][self::LINK_DIRECTION_PAYSYSTEM_DELIVERY] = array_keys(self::$unLinked[$entityType][self::LINK_DIRECTION_PAYSYSTEM_DELIVERY]);
  611. }
  612. if($linkDirection == null)
  613. {
  614. $result = array_intersect(self::$unLinked[$entityType][self::LINK_DIRECTION_DELIVERY_PAYSYSTEM], self::$unLinked[$entityType][self::LINK_DIRECTION_PAYSYSTEM_DELIVERY]);
  615. }
  616. else
  617. {
  618. $result = self::$unLinked[$entityType][$linkDirection];
  619. }
  620. return $result;
  621. }
  622. protected static function getEntityItemsFieldsList($entityType)
  623. {
  624. self::getEntityItemsFullList($entityType);
  625. return self::$entityItemsFieldsList[$entityType];
  626. }
  627. protected static function getEntityItemsFullList($entityType)
  628. {
  629. if(isset(self::$entityItemsFullList[$entityType]))
  630. return self::$entityItemsFullList[$entityType];
  631. self::$entityItemsFullList[$entityType] = array();
  632. if($entityType == self::ENTITY_TYPE_DELIVERY)
  633. {
  634. \Bitrix\Sale\Delivery\Services\Manager::getActiveList();
  635. $res = Services\Table::getList(array(
  636. 'filter' => array(
  637. 'ACTIVE' => 'Y'
  638. ),
  639. 'select' => array('*', 'PARENT_CLASS_NAME' => 'PARENT.CLASS_NAME')
  640. ));
  641. while($dsrv = $res->fetch())
  642. {
  643. $obj = Services\Manager::createObject($dsrv);
  644. if ($obj && $obj->canHasChildren()) //groups
  645. continue;
  646. self::$entityItemsFullList[$entityType][] = $dsrv["ID"];
  647. self::$entityItemsFieldsList[$entityType][$dsrv["ID"]] = $dsrv;
  648. }
  649. }
  650. else
  651. {
  652. $dbRes = PaySystem\Manager::getList(array(
  653. 'filter' => array("ACTIVE" => "Y"),
  654. 'select' => array("ID")
  655. ));
  656. while($ps = $dbRes->fetch())
  657. {
  658. self::$entityItemsFullList[$entityType][] = $ps["ID"];
  659. self::$entityItemsFieldsList[$entityType][$ps["ID"]] = $ps;
  660. }
  661. }
  662. return self::$entityItemsFullList[$entityType];
  663. }
  664. public static function prepareData(array $entityIds, $entityType)
  665. {
  666. static $preparedData = array();
  667. if(!isset($preparedData[$entityType]))
  668. $preparedData[$entityType] = array();
  669. if($entityType == self::ENTITY_TYPE_DELIVERY)
  670. {
  671. $linkDirection = self::LINK_DIRECTION_DELIVERY_PAYSYSTEM;
  672. $reverseLinkDirection = self::LINK_DIRECTION_PAYSYSTEM_DELIVERY;
  673. $reverseEntityType = self::ENTITY_TYPE_PAYSYSTEM;
  674. }
  675. else
  676. {
  677. $linkDirection = self::LINK_DIRECTION_PAYSYSTEM_DELIVERY;
  678. $reverseLinkDirection = self::LINK_DIRECTION_DELIVERY_PAYSYSTEM;
  679. $reverseEntityType = self::ENTITY_TYPE_DELIVERY;
  680. }
  681. if(empty($entityIds))
  682. $entityIds = self::getEntityItemsFullList($entityType);
  683. $arrdif = array_diff($entityIds, array_keys($preparedData[$entityType]));
  684. if(is_array($arrdif) && empty($arrdif))
  685. return array_intersect_key($preparedData[$entityType], $entityIds);
  686. $glParams = array(
  687. 'filter' => array(
  688. "=".$entityType => $arrdif
  689. )
  690. );
  691. $res = DeliveryPaySystemTable::getList($glParams);
  692. foreach($arrdif as $id)
  693. {
  694. $preparedData[$entityType][$id] = array(
  695. "DIRECT" => array(),
  696. "REVERSE" => array()
  697. );
  698. }
  699. while($rec = $res->fetch())
  700. {
  701. if($rec["LINK_DIRECTION"] == $linkDirection)
  702. $preparedData[$entityType][$rec[$entityType]]["DIRECT"][] = $rec[$reverseEntityType];
  703. elseif($rec["LINK_DIRECTION"] == $reverseLinkDirection)
  704. $preparedData[$entityType][$rec[$entityType]]["REVERSE"][] = $rec[$reverseEntityType];
  705. }
  706. return $preparedData[$entityType];
  707. }
  708. }