Cart.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Checkout\Model;
  7. use Magento\Catalog\Api\ProductRepositoryInterface;
  8. use Magento\Catalog\Model\Product;
  9. use Magento\Checkout\Model\Cart\CartInterface;
  10. use Magento\Framework\DataObject;
  11. use Magento\Framework\Exception\NoSuchEntityException;
  12. /**
  13. * Shopping cart model
  14. *
  15. * @api
  16. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  17. * @deprecated 100.1.0 Use \Magento\Quote\Model\Quote instead
  18. * @see \Magento\Quote\Api\Data\CartInterface
  19. * @since 100.0.2
  20. */
  21. class Cart extends DataObject implements CartInterface
  22. {
  23. /**
  24. * Shopping cart items summary quantity(s)
  25. *
  26. * @var int|null
  27. */
  28. protected $_summaryQty;
  29. /**
  30. * List of product ids in shopping cart
  31. *
  32. * @var int[]|null
  33. */
  34. protected $_productIds;
  35. /**
  36. * Core event manager proxy
  37. *
  38. * @var \Magento\Framework\Event\ManagerInterface
  39. */
  40. protected $_eventManager;
  41. /**
  42. * Core store config
  43. *
  44. * @var \Magento\Framework\App\Config\ScopeConfigInterface
  45. */
  46. protected $_scopeConfig;
  47. /**
  48. * @var \Magento\Store\Model\StoreManagerInterface
  49. */
  50. protected $_storeManager;
  51. /**
  52. * @var \Magento\Checkout\Model\ResourceModel\Cart
  53. */
  54. protected $_resourceCart;
  55. /**
  56. * @var Session
  57. */
  58. protected $_checkoutSession;
  59. /**
  60. * @var \Magento\Customer\Model\Session
  61. */
  62. protected $_customerSession;
  63. /**
  64. * @var \Magento\Framework\Message\ManagerInterface
  65. */
  66. protected $messageManager;
  67. /**
  68. * @var \Magento\CatalogInventory\Api\StockRegistryInterface
  69. */
  70. protected $stockRegistry;
  71. /**
  72. * @var \Magento\CatalogInventory\Api\StockStateInterface
  73. */
  74. protected $stockState;
  75. /**
  76. * @var \Magento\Quote\Api\CartRepositoryInterface
  77. */
  78. protected $quoteRepository;
  79. /**
  80. * @var ProductRepositoryInterface
  81. */
  82. protected $productRepository;
  83. /**
  84. * @var \Magento\Checkout\Model\Cart\RequestInfoFilterInterface
  85. */
  86. private $requestInfoFilter;
  87. /**
  88. * @param \Magento\Framework\Event\ManagerInterface $eventManager
  89. * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
  90. * @param \Magento\Store\Model\StoreManagerInterface $storeManager
  91. * @param \Magento\Checkout\Model\ResourceModel\Cart $resourceCart
  92. * @param Session $checkoutSession
  93. * @param \Magento\Customer\Model\Session $customerSession
  94. * @param \Magento\Framework\Message\ManagerInterface $messageManager
  95. * @param \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry
  96. * @param \Magento\CatalogInventory\Api\StockStateInterface $stockState
  97. * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository
  98. * @param ProductRepositoryInterface $productRepository
  99. * @param array $data
  100. * @codeCoverageIgnore
  101. * @SuppressWarnings(PHPMD.ExcessiveParameterList)
  102. */
  103. public function __construct(
  104. \Magento\Framework\Event\ManagerInterface $eventManager,
  105. \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
  106. \Magento\Store\Model\StoreManagerInterface $storeManager,
  107. \Magento\Checkout\Model\ResourceModel\Cart $resourceCart,
  108. Session $checkoutSession,
  109. \Magento\Customer\Model\Session $customerSession,
  110. \Magento\Framework\Message\ManagerInterface $messageManager,
  111. \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry,
  112. \Magento\CatalogInventory\Api\StockStateInterface $stockState,
  113. \Magento\Quote\Api\CartRepositoryInterface $quoteRepository,
  114. ProductRepositoryInterface $productRepository,
  115. array $data = []
  116. ) {
  117. $this->_eventManager = $eventManager;
  118. $this->_scopeConfig = $scopeConfig;
  119. $this->_storeManager = $storeManager;
  120. $this->_resourceCart = $resourceCart;
  121. $this->_checkoutSession = $checkoutSession;
  122. $this->_customerSession = $customerSession;
  123. $this->messageManager = $messageManager;
  124. $this->stockRegistry = $stockRegistry;
  125. $this->stockState = $stockState;
  126. $this->quoteRepository = $quoteRepository;
  127. parent::__construct($data);
  128. $this->productRepository = $productRepository;
  129. }
  130. /**
  131. * Get shopping cart resource model
  132. *
  133. * @return \Magento\Checkout\Model\ResourceModel\Cart
  134. * @codeCoverageIgnore
  135. */
  136. protected function _getResource()
  137. {
  138. return $this->_resourceCart;
  139. }
  140. /**
  141. * Retrieve checkout session model
  142. *
  143. * @return Session
  144. * @codeCoverageIgnore
  145. */
  146. public function getCheckoutSession()
  147. {
  148. return $this->_checkoutSession;
  149. }
  150. /**
  151. * Retrieve customer session model
  152. *
  153. * @return \Magento\Customer\Model\Session
  154. * @codeCoverageIgnore
  155. */
  156. public function getCustomerSession()
  157. {
  158. return $this->_customerSession;
  159. }
  160. /**
  161. * List of shopping cart items
  162. *
  163. * @return \Magento\Eav\Model\Entity\Collection\AbstractCollection|array
  164. */
  165. public function getItems()
  166. {
  167. if (!$this->getQuote()->getId()) {
  168. return [];
  169. }
  170. return $this->getQuote()->getItemsCollection();
  171. }
  172. /**
  173. * Retrieve array of cart product ids
  174. *
  175. * @return array
  176. */
  177. public function getQuoteProductIds()
  178. {
  179. $products = $this->getData('product_ids');
  180. if ($products === null) {
  181. $products = [];
  182. foreach ($this->getQuote()->getAllItems() as $item) {
  183. $products[$item->getProductId()] = $item->getProductId();
  184. }
  185. $this->setData('product_ids', $products);
  186. }
  187. return $products;
  188. }
  189. /**
  190. * Get quote object associated with cart. By default it is current customer session quote
  191. *
  192. * @return \Magento\Quote\Model\Quote
  193. */
  194. public function getQuote()
  195. {
  196. if (!$this->hasData('quote')) {
  197. $this->setData('quote', $this->_checkoutSession->getQuote());
  198. }
  199. return $this->_getData('quote');
  200. }
  201. /**
  202. * Set quote object associated with the cart
  203. *
  204. * @param \Magento\Quote\Model\Quote $quote
  205. * @return $this
  206. * @codeCoverageIgnore
  207. */
  208. public function setQuote(\Magento\Quote\Model\Quote $quote)
  209. {
  210. $this->setData('quote', $quote);
  211. return $this;
  212. }
  213. /**
  214. * Reinitialize cart quote state
  215. *
  216. * @return $this
  217. */
  218. protected function reinitializeState()
  219. {
  220. $quote = $this->getQuote()->setCheckoutMethod('');
  221. $this->_checkoutSession->setCartWasUpdated(true);
  222. // TODO: Move this logic to Multishipping module as plug-in.
  223. // reset for multiple address checkout
  224. if ($this->_checkoutSession->getCheckoutState() !== Session::CHECKOUT_STATE_BEGIN
  225. && $this->_checkoutSession->getCheckoutState() !== null) {
  226. $quote->removeAllAddresses()->removePayment();
  227. $this->_checkoutSession->resetCheckout();
  228. }
  229. return $this;
  230. }
  231. /**
  232. * Convert order item to quote item
  233. *
  234. * @param \Magento\Sales\Model\Order\Item $orderItem
  235. * @param true|null $qtyFlag if is null set product qty like in order
  236. * @return $this
  237. */
  238. public function addOrderItem($orderItem, $qtyFlag = null)
  239. {
  240. /* @var $orderItem \Magento\Sales\Model\Order\Item */
  241. if ($orderItem->getParentItem() === null) {
  242. $storeId = $this->_storeManager->getStore()->getId();
  243. try {
  244. /**
  245. * We need to reload product in this place, because products
  246. * with the same id may have different sets of order attributes.
  247. */
  248. $product = $this->productRepository->getById($orderItem->getProductId(), false, $storeId, true);
  249. } catch (NoSuchEntityException $e) {
  250. return $this;
  251. }
  252. $info = $orderItem->getProductOptionByCode('info_buyRequest');
  253. $info = new \Magento\Framework\DataObject($info);
  254. if ($qtyFlag === null) {
  255. $info->setQty($orderItem->getQtyOrdered());
  256. } else {
  257. $info->setQty(1);
  258. }
  259. $this->addProduct($product, $info);
  260. }
  261. return $this;
  262. }
  263. /**
  264. * Get product object based on requested product information
  265. *
  266. * @param Product|int|string $productInfo
  267. * @return Product
  268. * @throws \Magento\Framework\Exception\LocalizedException
  269. */
  270. protected function _getProduct($productInfo)
  271. {
  272. $product = null;
  273. if ($productInfo instanceof Product) {
  274. $product = $productInfo;
  275. if (!$product->getId()) {
  276. throw new \Magento\Framework\Exception\LocalizedException(
  277. __("The product wasn't found. Verify the product and try again.")
  278. );
  279. }
  280. } elseif (is_int($productInfo) || is_string($productInfo)) {
  281. $storeId = $this->_storeManager->getStore()->getId();
  282. try {
  283. $product = $this->productRepository->getById($productInfo, false, $storeId);
  284. } catch (NoSuchEntityException $e) {
  285. throw new \Magento\Framework\Exception\LocalizedException(
  286. __("The product wasn't found. Verify the product and try again."),
  287. $e
  288. );
  289. }
  290. } else {
  291. throw new \Magento\Framework\Exception\LocalizedException(
  292. __("The product wasn't found. Verify the product and try again.")
  293. );
  294. }
  295. $currentWebsiteId = $this->_storeManager->getStore()->getWebsiteId();
  296. if (!is_array($product->getWebsiteIds()) || !in_array($currentWebsiteId, $product->getWebsiteIds())) {
  297. throw new \Magento\Framework\Exception\LocalizedException(
  298. __("The product wasn't found. Verify the product and try again.")
  299. );
  300. }
  301. return $product;
  302. }
  303. /**
  304. * Get request for product add to cart procedure
  305. *
  306. * @param \Magento\Framework\DataObject|int|array $requestInfo
  307. * @return \Magento\Framework\DataObject
  308. * @throws \Magento\Framework\Exception\LocalizedException
  309. */
  310. protected function _getProductRequest($requestInfo)
  311. {
  312. if ($requestInfo instanceof \Magento\Framework\DataObject) {
  313. $request = $requestInfo;
  314. } elseif (is_numeric($requestInfo)) {
  315. $request = new \Magento\Framework\DataObject(['qty' => $requestInfo]);
  316. } elseif (is_array($requestInfo)) {
  317. $request = new \Magento\Framework\DataObject($requestInfo);
  318. } else {
  319. throw new \Magento\Framework\Exception\LocalizedException(
  320. __('We found an invalid request for adding product to quote.')
  321. );
  322. }
  323. $this->getRequestInfoFilter()->filter($request);
  324. return $request;
  325. }
  326. /**
  327. * Add product to shopping cart (quote)
  328. *
  329. * @param int|Product $productInfo
  330. * @param \Magento\Framework\DataObject|int|array $requestInfo
  331. * @return $this
  332. * @throws \Magento\Framework\Exception\LocalizedException
  333. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  334. */
  335. public function addProduct($productInfo, $requestInfo = null)
  336. {
  337. $product = $this->_getProduct($productInfo);
  338. $request = $this->_getProductRequest($requestInfo);
  339. $productId = $product->getId();
  340. if ($productId) {
  341. $stockItem = $this->stockRegistry->getStockItem($productId, $product->getStore()->getWebsiteId());
  342. $minimumQty = $stockItem->getMinSaleQty();
  343. //If product quantity is not specified in request and there is set minimal qty for it
  344. if ($minimumQty
  345. && $minimumQty > 0
  346. && !$request->getQty()
  347. ) {
  348. $request->setQty($minimumQty);
  349. }
  350. try {
  351. $this->_eventManager->dispatch(
  352. 'checkout_cart_product_add_before',
  353. ['info' => $requestInfo, 'product' => $product]
  354. );
  355. $result = $this->getQuote()->addProduct($product, $request);
  356. } catch (\Magento\Framework\Exception\LocalizedException $e) {
  357. $this->_checkoutSession->setUseNotice(false);
  358. $result = $e->getMessage();
  359. }
  360. /**
  361. * String we can get if prepare process has error
  362. */
  363. if (is_string($result)) {
  364. if ($product->hasOptionsValidationFail()) {
  365. $redirectUrl = $product->getUrlModel()->getUrl(
  366. $product,
  367. ['_query' => ['startcustomization' => 1]]
  368. );
  369. } else {
  370. $redirectUrl = $product->getProductUrl();
  371. }
  372. $this->_checkoutSession->setRedirectUrl($redirectUrl);
  373. if ($this->_checkoutSession->getUseNotice() === null) {
  374. $this->_checkoutSession->setUseNotice(true);
  375. }
  376. throw new \Magento\Framework\Exception\LocalizedException(__($result));
  377. }
  378. } else {
  379. throw new \Magento\Framework\Exception\LocalizedException(__('The product does not exist.'));
  380. }
  381. $this->_eventManager->dispatch(
  382. 'checkout_cart_product_add_after',
  383. ['quote_item' => $result, 'product' => $product]
  384. );
  385. $this->_checkoutSession->setLastAddedProductId($productId);
  386. return $this;
  387. }
  388. /**
  389. * Adding products to cart by ids
  390. *
  391. * @param int[] $productIds
  392. * @return $this
  393. */
  394. public function addProductsByIds($productIds)
  395. {
  396. $allAvailable = true;
  397. $allAdded = true;
  398. if (!empty($productIds)) {
  399. foreach ($productIds as $productId) {
  400. $productId = (int)$productId;
  401. if (!$productId) {
  402. continue;
  403. }
  404. $product = $this->_getProduct($productId);
  405. if ($product->getId() && $product->isVisibleInCatalog()) {
  406. try {
  407. $this->getQuote()->addProduct($product);
  408. } catch (\Exception $e) {
  409. $allAdded = false;
  410. }
  411. } else {
  412. $allAvailable = false;
  413. }
  414. }
  415. if (!$allAvailable) {
  416. $this->messageManager->addErrorMessage(__("We don't have some of the products you want."));
  417. }
  418. if (!$allAdded) {
  419. $this->messageManager->addErrorMessage(__("We don't have as many of some products as you want."));
  420. }
  421. }
  422. return $this;
  423. }
  424. /**
  425. * Returns suggested quantities for items.
  426. * Can be used to automatically fix user entered quantities before updating cart
  427. * so that cart contains valid qty values
  428. *
  429. * The $data is an array of ($quoteItemId => (item info array with 'qty' key), ...)
  430. *
  431. * @param array $data
  432. * @return array
  433. */
  434. public function suggestItemsQty($data)
  435. {
  436. foreach ($data as $itemId => $itemInfo) {
  437. if (!isset($itemInfo['qty'])) {
  438. continue;
  439. }
  440. $qty = (float)$itemInfo['qty'];
  441. if ($qty <= 0) {
  442. continue;
  443. }
  444. $quoteItem = $this->getQuote()->getItemById($itemId);
  445. if (!$quoteItem) {
  446. continue;
  447. }
  448. $product = $quoteItem->getProduct();
  449. if (!$product) {
  450. continue;
  451. }
  452. $data[$itemId]['before_suggest_qty'] = $qty;
  453. $data[$itemId]['qty'] = $this->stockState->suggestQty(
  454. $product->getId(),
  455. $qty,
  456. $product->getStore()->getWebsiteId()
  457. );
  458. }
  459. return $data;
  460. }
  461. /**
  462. * Update cart items information
  463. *
  464. * @param array $data
  465. * @return $this
  466. * @throws \Magento\Framework\Exception\LocalizedException
  467. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  468. * @SuppressWarnings(PHPMD.NPathComplexity)
  469. */
  470. public function updateItems($data)
  471. {
  472. $infoDataObject = new \Magento\Framework\DataObject($data);
  473. $this->_eventManager->dispatch(
  474. 'checkout_cart_update_items_before',
  475. ['cart' => $this, 'info' => $infoDataObject]
  476. );
  477. $qtyRecalculatedFlag = false;
  478. foreach ($data as $itemId => $itemInfo) {
  479. $item = $this->getQuote()->getItemById($itemId);
  480. if (!$item) {
  481. continue;
  482. }
  483. if (!empty($itemInfo['remove']) || isset($itemInfo['qty']) && $itemInfo['qty'] == '0') {
  484. $this->removeItem($itemId);
  485. continue;
  486. }
  487. $qty = isset($itemInfo['qty']) ? (double)$itemInfo['qty'] : false;
  488. if ($qty > 0) {
  489. $item->setQty($qty);
  490. if ($item->getHasError()) {
  491. throw new \Magento\Framework\Exception\LocalizedException(__($item->getMessage()));
  492. }
  493. if (isset($itemInfo['before_suggest_qty']) && $itemInfo['before_suggest_qty'] != $qty) {
  494. $qtyRecalculatedFlag = true;
  495. $this->messageManager->addNoticeMessage(
  496. __('Quantity was recalculated from %1 to %2', $itemInfo['before_suggest_qty'], $qty),
  497. 'quote_item' . $item->getId()
  498. );
  499. }
  500. }
  501. }
  502. if ($qtyRecalculatedFlag) {
  503. $this->messageManager->addNoticeMessage(
  504. __('We adjusted product quantities to fit the required increments.')
  505. );
  506. }
  507. $this->_eventManager->dispatch(
  508. 'checkout_cart_update_items_after',
  509. ['cart' => $this, 'info' => $infoDataObject]
  510. );
  511. return $this;
  512. }
  513. /**
  514. * Remove item from cart
  515. *
  516. * @param int $itemId
  517. * @return $this
  518. * @codeCoverageIgnore
  519. */
  520. public function removeItem($itemId)
  521. {
  522. $this->getQuote()->removeItem($itemId);
  523. return $this;
  524. }
  525. /**
  526. * Save cart
  527. *
  528. * @return $this
  529. */
  530. public function save()
  531. {
  532. $this->_eventManager->dispatch('checkout_cart_save_before', ['cart' => $this]);
  533. $this->getQuote()->getBillingAddress();
  534. $this->getQuote()->getShippingAddress()->setCollectShippingRates(true);
  535. $this->getQuote()->collectTotals();
  536. $this->quoteRepository->save($this->getQuote());
  537. $this->_checkoutSession->setQuoteId($this->getQuote()->getId());
  538. /**
  539. * Cart save usually called after changes with cart items.
  540. */
  541. $this->_eventManager->dispatch('checkout_cart_save_after', ['cart' => $this]);
  542. $this->reinitializeState();
  543. return $this;
  544. }
  545. /**
  546. * Save cart (implement interface method)
  547. *
  548. * @return void
  549. * @codeCoverageIgnore
  550. */
  551. public function saveQuote()
  552. {
  553. $this->save();
  554. }
  555. /**
  556. * Mark all quote items as deleted (empty shopping cart)
  557. *
  558. * @return $this
  559. * @codeCoverageIgnore
  560. */
  561. public function truncate()
  562. {
  563. $this->getQuote()->removeAllItems();
  564. return $this;
  565. }
  566. /**
  567. * Get product ids.
  568. *
  569. * @return int[]
  570. */
  571. public function getProductIds()
  572. {
  573. if (null === $this->_productIds) {
  574. $this->_productIds = [];
  575. if ($this->getSummaryQty() > 0) {
  576. foreach ($this->getQuote()->getAllItems() as $item) {
  577. $this->_productIds[] = $item->getProductId();
  578. }
  579. }
  580. $this->_productIds = array_unique($this->_productIds);
  581. }
  582. return $this->_productIds;
  583. }
  584. /**
  585. * Get shopping cart items summary (includes config settings)
  586. *
  587. * @return int|float
  588. */
  589. public function getSummaryQty()
  590. {
  591. $quoteId = $this->_checkoutSession->getQuoteId();
  592. //If there is no quote id in session trying to load quote
  593. //and get new quote id. This is done for cases when quote was created
  594. //not by customer (from backend for example).
  595. if (!$quoteId && $this->_customerSession->isLoggedIn()) {
  596. $this->_checkoutSession->getQuote();
  597. $quoteId = $this->_checkoutSession->getQuoteId();
  598. }
  599. if ($quoteId && $this->_summaryQty === null) {
  600. $useQty = $this->_scopeConfig->getValue(
  601. 'checkout/cart_link/use_qty',
  602. \Magento\Store\Model\ScopeInterface::SCOPE_STORE
  603. );
  604. $this->_summaryQty = $useQty ? $this->getItemsQty() : $this->getItemsCount();
  605. }
  606. return $this->_summaryQty;
  607. }
  608. /**
  609. * Get shopping cart items count
  610. *
  611. * @return int
  612. * @codeCoverageIgnore
  613. */
  614. public function getItemsCount()
  615. {
  616. return $this->getQuote()->getItemsCount() * 1;
  617. }
  618. /**
  619. * Get shopping cart summary qty
  620. *
  621. * @return int|float
  622. * @codeCoverageIgnore
  623. */
  624. public function getItemsQty()
  625. {
  626. return $this->getQuote()->getItemsQty() * 1;
  627. }
  628. /**
  629. * Update item in shopping cart (quote)
  630. * $requestInfo - either qty (int) or buyRequest in form of array or \Magento\Framework\DataObject
  631. * $updatingParams - information on how to perform update, passed to Quote->updateItem() method
  632. *
  633. * @param int $itemId
  634. * @param int|array|\Magento\Framework\DataObject $requestInfo
  635. * @param null|array|\Magento\Framework\DataObject $updatingParams
  636. * @return \Magento\Quote\Model\Quote\Item|string
  637. * @throws \Magento\Framework\Exception\LocalizedException
  638. *
  639. * @see \Magento\Quote\Model\Quote::updateItem()
  640. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  641. */
  642. public function updateItem($itemId, $requestInfo = null, $updatingParams = null)
  643. {
  644. try {
  645. $item = $this->getQuote()->getItemById($itemId);
  646. if (!$item) {
  647. throw new \Magento\Framework\Exception\LocalizedException(__('This quote item does not exist.'));
  648. }
  649. $productId = $item->getProduct()->getId();
  650. $product = $this->_getProduct($productId);
  651. $request = $this->_getProductRequest($requestInfo);
  652. if ($productId) {
  653. $stockItem = $this->stockRegistry->getStockItem($productId, $product->getStore()->getWebsiteId());
  654. $minimumQty = $stockItem->getMinSaleQty();
  655. // If product was not found in cart and there is set minimal qty for it
  656. if ($minimumQty
  657. && $minimumQty > 0
  658. && !$request->getQty()
  659. && !$this->getQuote()->hasProductId($productId)
  660. ) {
  661. $request->setQty($minimumQty);
  662. }
  663. }
  664. $result = $this->getQuote()->updateItem($itemId, $request, $updatingParams);
  665. } catch (\Magento\Framework\Exception\LocalizedException $e) {
  666. $this->_checkoutSession->setUseNotice(false);
  667. $result = $e->getMessage();
  668. }
  669. /**
  670. * We can get string if updating process had some errors
  671. */
  672. if (is_string($result)) {
  673. if ($this->_checkoutSession->getUseNotice() === null) {
  674. $this->_checkoutSession->setUseNotice(true);
  675. }
  676. throw new \Magento\Framework\Exception\LocalizedException(__($result));
  677. }
  678. $this->_eventManager->dispatch(
  679. 'checkout_cart_product_update_after',
  680. ['quote_item' => $result, 'product' => $product]
  681. );
  682. $this->_checkoutSession->setLastAddedProductId($productId);
  683. return $result;
  684. }
  685. /**
  686. * Getter for RequestInfoFilter
  687. *
  688. * @deprecated 100.1.2
  689. * @return \Magento\Checkout\Model\Cart\RequestInfoFilterInterface
  690. */
  691. private function getRequestInfoFilter()
  692. {
  693. if ($this->requestInfoFilter === null) {
  694. $this->requestInfoFilter = \Magento\Framework\App\ObjectManager::getInstance()
  695. ->get(\Magento\Checkout\Model\Cart\RequestInfoFilterInterface::class);
  696. }
  697. return $this->requestInfoFilter;
  698. }
  699. }