Cart.php 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Payment\Model;
  7. /**
  8. * Provide methods for collecting cart items information of specific sales model entity
  9. *
  10. * @api
  11. * @since 100.0.2
  12. */
  13. class Cart
  14. {
  15. /**#@+
  16. * Amounts
  17. */
  18. const AMOUNT_TAX = 'tax';
  19. const AMOUNT_SHIPPING = 'shipping';
  20. const AMOUNT_DISCOUNT = 'discount';
  21. const AMOUNT_SUBTOTAL = 'subtotal';
  22. /**#@-*/
  23. /**#@-*/
  24. protected $_salesModel;
  25. /**
  26. * Core event manager proxy
  27. *
  28. * @var \Magento\Framework\Event\ManagerInterface
  29. */
  30. protected $_eventManager;
  31. /**
  32. * Amounts
  33. *
  34. * @var array
  35. */
  36. protected $_amounts;
  37. /**
  38. * Custom items list
  39. *
  40. * @var array
  41. */
  42. protected $_customItems = [];
  43. /**
  44. * Items imported from sales model
  45. *
  46. * @var array
  47. */
  48. protected $_salesModelItems = [];
  49. /**
  50. * Flags that indicates whether discount, shopping and taxes should be transferred as cart item
  51. *
  52. * @var array
  53. */
  54. protected $_transferFlags = [];
  55. /**
  56. * Flags which indicates whether items data is outdated and has to be recollected
  57. *
  58. * @var bool
  59. */
  60. protected $_itemsCollectingRequired = true;
  61. /**
  62. * @param \Magento\Payment\Model\Cart\SalesModel\Factory $salesModelFactory
  63. * @param \Magento\Framework\Event\ManagerInterface $eventManager
  64. * @param \Magento\Quote\Api\Data\CartInterface $salesModel
  65. */
  66. public function __construct(
  67. \Magento\Payment\Model\Cart\SalesModel\Factory $salesModelFactory,
  68. \Magento\Framework\Event\ManagerInterface $eventManager,
  69. $salesModel
  70. ) {
  71. $this->_eventManager = $eventManager;
  72. $this->_salesModel = $salesModelFactory->create($salesModel);
  73. $this->_resetAmounts();
  74. }
  75. /**
  76. * Return payment cart sales model
  77. *
  78. * @return \Magento\Payment\Model\Cart\SalesModel\SalesModelInterface
  79. * @api
  80. */
  81. public function getSalesModel()
  82. {
  83. return $this->_salesModel;
  84. }
  85. /**
  86. * Add amount to existing tax amount
  87. *
  88. * @param float $taxAmount
  89. * @return void
  90. * @api
  91. */
  92. public function addTax($taxAmount)
  93. {
  94. $this->_addAmount(self::AMOUNT_TAX, $taxAmount);
  95. }
  96. /**
  97. * Set tax. Old value will be overwritten
  98. *
  99. * @param float $taxAmount
  100. * @return void
  101. * @api
  102. */
  103. public function setTax($taxAmount)
  104. {
  105. $this->_setAmount(self::AMOUNT_TAX, $taxAmount);
  106. }
  107. /**
  108. * Get tax amount
  109. *
  110. * @return float
  111. * @api
  112. */
  113. public function getTax()
  114. {
  115. return $this->_getAmount(self::AMOUNT_TAX);
  116. }
  117. /**
  118. * Add amount to existing discount amount
  119. *
  120. * @param float $discountAmount
  121. * @return void
  122. * @api
  123. */
  124. public function addDiscount($discountAmount)
  125. {
  126. $this->_addAmount(self::AMOUNT_DISCOUNT, $discountAmount);
  127. }
  128. /**
  129. * Set discount. Old value will be overwritten
  130. *
  131. * @param float $discountAmount
  132. * @return void
  133. * @api
  134. */
  135. public function setDiscount($discountAmount)
  136. {
  137. $this->_setAmount(self::AMOUNT_DISCOUNT, $discountAmount);
  138. }
  139. /**
  140. * Get discount amount
  141. *
  142. * @return float
  143. * @api
  144. */
  145. public function getDiscount()
  146. {
  147. return $this->_getAmount(self::AMOUNT_DISCOUNT);
  148. }
  149. /**
  150. * Add amount to existing shipping amount
  151. *
  152. * @param float $shippingAmount
  153. * @return void
  154. * @api
  155. */
  156. public function addShipping($shippingAmount)
  157. {
  158. $this->_addAmount(self::AMOUNT_SHIPPING, $shippingAmount);
  159. }
  160. /**
  161. * Set shipping. Old value will be overwritten
  162. *
  163. * @param float $shippingAmount
  164. * @return void
  165. * @api
  166. */
  167. public function setShipping($shippingAmount)
  168. {
  169. $this->_setAmount(self::AMOUNT_SHIPPING, $shippingAmount);
  170. }
  171. /**
  172. * Get shipping amount
  173. *
  174. * @return float
  175. * @api
  176. */
  177. public function getShipping()
  178. {
  179. return $this->_getAmount(self::AMOUNT_SHIPPING);
  180. }
  181. /**
  182. * Add amount to existing subtotal amount
  183. *
  184. * @param float $subtotalAmount
  185. * @return void
  186. * @api
  187. */
  188. public function addSubtotal($subtotalAmount)
  189. {
  190. $this->_addAmount(self::AMOUNT_SUBTOTAL, $subtotalAmount);
  191. }
  192. /**
  193. * Get subtotal amount
  194. *
  195. * @return float
  196. * @api
  197. */
  198. public function getSubtotal()
  199. {
  200. return $this->_getAmount(self::AMOUNT_SUBTOTAL);
  201. }
  202. /**
  203. * Add custom item (such as discount as line item, shipping as line item, etc)
  204. *
  205. * @param string $name
  206. * @param int $qty
  207. * @param float $amount
  208. * @param string|null $identifier
  209. * @return void
  210. * @api
  211. */
  212. public function addCustomItem($name, $qty, $amount, $identifier = null)
  213. {
  214. $this->_customItems[] = $this->_createItemFromData($name, $qty, $amount, $identifier);
  215. }
  216. /**
  217. * Get all cart items
  218. *
  219. * @return array
  220. * @api
  221. */
  222. public function getAllItems()
  223. {
  224. $this->_collectItemsAndAmounts();
  225. return array_merge($this->_salesModelItems, $this->_customItems);
  226. }
  227. /**
  228. * Get shipping, tax, subtotal and discount amounts all together
  229. *
  230. * @return array
  231. * @api
  232. */
  233. public function getAmounts()
  234. {
  235. $this->_collectItemsAndAmounts();
  236. return $this->_amounts;
  237. }
  238. /**
  239. * Specify that shipping should be transferred as cart item
  240. *
  241. * @return void
  242. * @api
  243. */
  244. public function setTransferShippingAsItem()
  245. {
  246. $this->_setTransferFlag(self::AMOUNT_SHIPPING, true);
  247. }
  248. /**
  249. * Specify that discount should be transferred as cart item
  250. *
  251. * @return void
  252. * @api
  253. */
  254. public function setTransferDiscountAsItem()
  255. {
  256. $this->_setTransferFlag(self::AMOUNT_DISCOUNT, true);
  257. }
  258. /**
  259. * Collect all items, discounts, taxes, shipping to cart
  260. *
  261. * @return void
  262. */
  263. protected function _collectItemsAndAmounts()
  264. {
  265. if (!$this->_itemsCollectingRequired) {
  266. return;
  267. }
  268. $this->_itemsCollectingRequired = false;
  269. $this->_salesModelItems = [];
  270. $this->_customItems = [];
  271. $this->_resetAmounts();
  272. $this->_eventManager->dispatch('payment_cart_collect_items_and_amounts', ['cart' => $this]);
  273. $this->_importItemsFromSalesModel();
  274. $this->_calculateCustomItemsSubtotal();
  275. }
  276. /**
  277. * Import items from sales model
  278. *
  279. * @return void
  280. */
  281. protected function _importItemsFromSalesModel()
  282. {
  283. $this->_salesModelItems = [];
  284. foreach ($this->_salesModel->getAllItems() as $item) {
  285. if ($item->getParentItem()) {
  286. continue;
  287. }
  288. $this->_salesModelItems[] = $this->_createItemFromData(
  289. $item->getName(),
  290. $item->getQty(),
  291. $item->getPrice(),
  292. $item->getOriginalItem()->getId()
  293. );
  294. }
  295. $this->addSubtotal($this->_salesModel->getBaseSubtotal());
  296. $this->addTax($this->_salesModel->getBaseTaxAmount());
  297. $this->addShipping($this->_salesModel->getBaseShippingAmount());
  298. $this->addDiscount(abs($this->_salesModel->getBaseDiscountAmount()));
  299. }
  300. /**
  301. * Calculate subtotal from custom items
  302. *
  303. * @return void
  304. */
  305. protected function _calculateCustomItemsSubtotal()
  306. {
  307. if (!empty($this->_transferFlags[self::AMOUNT_DISCOUNT]) && $this->getDiscount()) {
  308. $this->addCustomItem(__('Discount'), 1, -1.00 * $this->getDiscount());
  309. $this->setDiscount(0);
  310. }
  311. if (!empty($this->_transferFlags[self::AMOUNT_SHIPPING]) && $this->getShipping()) {
  312. $this->addCustomItem(__('Shipping'), 1, $this->getShipping());
  313. $this->setShipping(0);
  314. }
  315. foreach ($this->_customItems as $item) {
  316. $this->_amounts[self::AMOUNT_SUBTOTAL] += $item->getAmount();
  317. }
  318. }
  319. /**
  320. * @param string $flagType
  321. * @param bool $value
  322. * @return void
  323. */
  324. protected function _setTransferFlag($flagType, $value)
  325. {
  326. $this->_transferFlags[$flagType] = (bool)$value;
  327. $this->_itemsCollectingRequired = true;
  328. }
  329. /**
  330. * @param string $amountType
  331. * @param float $amount
  332. * @return void
  333. */
  334. protected function _setAmount($amountType, $amount)
  335. {
  336. $this->_amounts[$amountType] = (double)$amount;
  337. }
  338. /**
  339. * @param string $amountType
  340. * @param float $amount
  341. * @return void
  342. */
  343. protected function _addAmount($amountType, $amount)
  344. {
  345. $this->_amounts[$amountType] += (double)$amount;
  346. }
  347. /**
  348. * Get amount of specified type
  349. *
  350. * @param string $amountType
  351. * @return float
  352. */
  353. protected function _getAmount($amountType)
  354. {
  355. return $this->_amounts[$amountType];
  356. }
  357. /**
  358. * Create item object from item data
  359. *
  360. * @param string $name
  361. * @param int $qty
  362. * @param float $amount
  363. * @param null|string $identifier
  364. * @return \Magento\Framework\DataObject
  365. */
  366. protected function _createItemFromData($name, $qty, $amount, $identifier = null)
  367. {
  368. $item = new \Magento\Framework\DataObject(['name' => $name, 'qty' => $qty, 'amount' => (double)$amount]);
  369. if ($identifier) {
  370. $item->setData('id', $identifier);
  371. }
  372. return $item;
  373. }
  374. /**
  375. * Set all amount types to zero
  376. *
  377. * @return void
  378. */
  379. protected function _resetAmounts()
  380. {
  381. $this->_amounts = [
  382. self::AMOUNT_DISCOUNT => 0,
  383. self::AMOUNT_SHIPPING => 0,
  384. self::AMOUNT_SUBTOTAL => 0,
  385. self::AMOUNT_TAX => 0,
  386. ];
  387. }
  388. }