Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Cart.php
Go to the documentation of this file.
1 <?php
7 namespace Magento\Checkout\Model;
8 
14 
24 class Cart extends DataObject implements CartInterface
25 {
31  protected $_summaryQty;
32 
38  protected $_productIds;
39 
45  protected $_eventManager;
46 
52  protected $_scopeConfig;
53 
57  protected $_storeManager;
58 
62  protected $_resourceCart;
63 
67  protected $_checkoutSession;
68 
72  protected $_customerSession;
73 
77  protected $messageManager;
78 
82  protected $stockRegistry;
83 
87  protected $stockState;
88 
92  protected $quoteRepository;
93 
97  protected $productRepository;
98 
102  private $requestInfoFilter;
103 
120  public function __construct(
121  \Magento\Framework\Event\ManagerInterface $eventManager,
122  \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
124  \Magento\Checkout\Model\ResourceModel\Cart $resourceCart,
125  Session $checkoutSession,
126  \Magento\Customer\Model\Session $customerSession,
127  \Magento\Framework\Message\ManagerInterface $messageManager,
128  \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry,
129  \Magento\CatalogInventory\Api\StockStateInterface $stockState,
132  array $data = []
133  ) {
134  $this->_eventManager = $eventManager;
135  $this->_scopeConfig = $scopeConfig;
136  $this->_storeManager = $storeManager;
137  $this->_resourceCart = $resourceCart;
138  $this->_checkoutSession = $checkoutSession;
139  $this->_customerSession = $customerSession;
140  $this->messageManager = $messageManager;
141  $this->stockRegistry = $stockRegistry;
142  $this->stockState = $stockState;
143  $this->quoteRepository = $quoteRepository;
144  parent::__construct($data);
145  $this->productRepository = $productRepository;
146  }
147 
154  protected function _getResource()
155  {
156  return $this->_resourceCart;
157  }
158 
165  public function getCheckoutSession()
166  {
168  }
169 
176  public function getCustomerSession()
177  {
179  }
180 
186  public function getItems()
187  {
188  if (!$this->getQuote()->getId()) {
189  return [];
190  }
191  return $this->getQuote()->getItemsCollection();
192  }
193 
199  public function getQuoteProductIds()
200  {
201  $products = $this->getData('product_ids');
202  if ($products === null) {
203  $products = [];
204  foreach ($this->getQuote()->getAllItems() as $item) {
205  $products[$item->getProductId()] = $item->getProductId();
206  }
207  $this->setData('product_ids', $products);
208  }
209  return $products;
210  }
211 
217  public function getQuote()
218  {
219  if (!$this->hasData('quote')) {
220  $this->setData('quote', $this->_checkoutSession->getQuote());
221  }
222  return $this->_getData('quote');
223  }
224 
232  public function setQuote(\Magento\Quote\Model\Quote $quote)
233  {
234  $this->setData('quote', $quote);
235  return $this;
236  }
237 
243  protected function reinitializeState()
244  {
245  $quote = $this->getQuote()->setCheckoutMethod('');
246  $this->_checkoutSession->setCartWasUpdated(true);
247  // TODO: Move this logic to Multishipping module as plug-in.
248  // reset for multiple address checkout
249  if ($this->_checkoutSession->getCheckoutState() !== Session::CHECKOUT_STATE_BEGIN
250  && $this->_checkoutSession->getCheckoutState() !== null) {
251  $quote->removeAllAddresses()->removePayment();
252  $this->_checkoutSession->resetCheckout();
253  }
254  return $this;
255  }
256 
264  public function addOrderItem($orderItem, $qtyFlag = null)
265  {
266  /* @var $orderItem \Magento\Sales\Model\Order\Item */
267  if ($orderItem->getParentItem() === null) {
268  $storeId = $this->_storeManager->getStore()->getId();
269  try {
274  $product = $this->productRepository->getById($orderItem->getProductId(), false, $storeId, true);
275  } catch (NoSuchEntityException $e) {
276  return $this;
277  }
278  $info = $orderItem->getProductOptionByCode('info_buyRequest');
279  $info = new \Magento\Framework\DataObject($info);
280  if ($qtyFlag === null) {
281  $info->setQty($orderItem->getQtyOrdered());
282  } else {
283  $info->setQty(1);
284  }
285 
286  $this->addProduct($product, $info);
287  }
288  return $this;
289  }
290 
298  protected function _getProduct($productInfo)
299  {
300  $product = null;
301  if ($productInfo instanceof Product) {
302  $product = $productInfo;
303  if (!$product->getId()) {
304  throw new \Magento\Framework\Exception\LocalizedException(
305  __("The product wasn't found. Verify the product and try again.")
306  );
307  }
308  } elseif (is_int($productInfo) || is_string($productInfo)) {
309  $storeId = $this->_storeManager->getStore()->getId();
310  try {
311  $product = $this->productRepository->getById($productInfo, false, $storeId);
312  } catch (NoSuchEntityException $e) {
313  throw new \Magento\Framework\Exception\LocalizedException(
314  __("The product wasn't found. Verify the product and try again."),
315  $e
316  );
317  }
318  } else {
319  throw new \Magento\Framework\Exception\LocalizedException(
320  __("The product wasn't found. Verify the product and try again.")
321  );
322  }
323  $currentWebsiteId = $this->_storeManager->getStore()->getWebsiteId();
324  if (!is_array($product->getWebsiteIds()) || !in_array($currentWebsiteId, $product->getWebsiteIds())) {
325  throw new \Magento\Framework\Exception\LocalizedException(
326  __("The product wasn't found. Verify the product and try again.")
327  );
328  }
329  return $product;
330  }
331 
339  protected function _getProductRequest($requestInfo)
340  {
341  if ($requestInfo instanceof \Magento\Framework\DataObject) {
343  } elseif (is_numeric($requestInfo)) {
344  $request = new \Magento\Framework\DataObject(['qty' => $requestInfo]);
345  } elseif (is_array($requestInfo)) {
346  $request = new \Magento\Framework\DataObject($requestInfo);
347  } else {
348  throw new \Magento\Framework\Exception\LocalizedException(
349  __('We found an invalid request for adding product to quote.')
350  );
351  }
352  $this->getRequestInfoFilter()->filter($request);
353 
354  return $request;
355  }
356 
366  public function addProduct($productInfo, $requestInfo = null)
367  {
368  $product = $this->_getProduct($productInfo);
370  $productId = $product->getId();
371 
372  if ($productId) {
373  $stockItem = $this->stockRegistry->getStockItem($productId, $product->getStore()->getWebsiteId());
374  $minimumQty = $stockItem->getMinSaleQty();
375  //If product quantity is not specified in request and there is set minimal qty for it
376  if ($minimumQty
377  && $minimumQty > 0
378  && !$request->getQty()
379  ) {
380  $request->setQty($minimumQty);
381  }
382 
383  try {
384  $result = $this->getQuote()->addProduct($product, $request);
385  } catch (\Magento\Framework\Exception\LocalizedException $e) {
386  $this->_checkoutSession->setUseNotice(false);
387  $result = $e->getMessage();
388  }
392  if (is_string($result)) {
393  if ($product->hasOptionsValidationFail()) {
394  $redirectUrl = $product->getUrlModel()->getUrl(
395  $product,
396  ['_query' => ['startcustomization' => 1]]
397  );
398  } else {
399  $redirectUrl = $product->getProductUrl();
400  }
401  $this->_checkoutSession->setRedirectUrl($redirectUrl);
402  if ($this->_checkoutSession->getUseNotice() === null) {
403  $this->_checkoutSession->setUseNotice(true);
404  }
405  throw new \Magento\Framework\Exception\LocalizedException(__($result));
406  }
407  } else {
408  throw new \Magento\Framework\Exception\LocalizedException(__('The product does not exist.'));
409  }
410 
411  $this->_eventManager->dispatch(
412  'checkout_cart_product_add_after',
413  ['quote_item' => $result, 'product' => $product]
414  );
415  $this->_checkoutSession->setLastAddedProductId($productId);
416  return $this;
417  }
418 
425  public function addProductsByIds($productIds)
426  {
427  $allAvailable = true;
428  $allAdded = true;
429 
430  if (!empty($productIds)) {
431  foreach ($productIds as $productId) {
432  $productId = (int)$productId;
433  if (!$productId) {
434  continue;
435  }
436  $product = $this->_getProduct($productId);
437  if ($product->getId() && $product->isVisibleInCatalog()) {
438  try {
439  $this->getQuote()->addProduct($product);
440  } catch (\Exception $e) {
441  $allAdded = false;
442  }
443  } else {
444  $allAvailable = false;
445  }
446  }
447 
448  if (!$allAvailable) {
449  $this->messageManager->addErrorMessage(__("We don't have some of the products you want."));
450  }
451  if (!$allAdded) {
452  $this->messageManager->addErrorMessage(__("We don't have as many of some products as you want."));
453  }
454  }
455  return $this;
456  }
457 
468  public function suggestItemsQty($data)
469  {
470  foreach ($data as $itemId => $itemInfo) {
471  if (!isset($itemInfo['qty'])) {
472  continue;
473  }
474  $qty = (float)$itemInfo['qty'];
475  if ($qty <= 0) {
476  continue;
477  }
478 
479  $quoteItem = $this->getQuote()->getItemById($itemId);
480  if (!$quoteItem) {
481  continue;
482  }
483 
484  $product = $quoteItem->getProduct();
485  if (!$product) {
486  continue;
487  }
488 
489  $data[$itemId]['before_suggest_qty'] = $qty;
490  $data[$itemId]['qty'] = $this->stockState->suggestQty(
491  $product->getId(),
492  $qty,
493  $product->getStore()->getWebsiteId()
494  );
495  }
496  return $data;
497  }
498 
508  public function updateItems($data)
509  {
510  $infoDataObject = new \Magento\Framework\DataObject($data);
511  $this->_eventManager->dispatch(
512  'checkout_cart_update_items_before',
513  ['cart' => $this, 'info' => $infoDataObject]
514  );
515 
516  $qtyRecalculatedFlag = false;
517  foreach ($data as $itemId => $itemInfo) {
518  $item = $this->getQuote()->getItemById($itemId);
519  if (!$item) {
520  continue;
521  }
522 
523  if (!empty($itemInfo['remove']) || isset($itemInfo['qty']) && $itemInfo['qty'] == '0') {
524  $this->removeItem($itemId);
525  continue;
526  }
527 
528  $qty = isset($itemInfo['qty']) ? (double)$itemInfo['qty'] : false;
529  if ($qty > 0) {
530  $item->setQty($qty);
531 
532  if ($item->getHasError()) {
533  throw new \Magento\Framework\Exception\LocalizedException(__($item->getMessage()));
534  }
535 
536  if (isset($itemInfo['before_suggest_qty']) && $itemInfo['before_suggest_qty'] != $qty) {
537  $qtyRecalculatedFlag = true;
538  $this->messageManager->addNoticeMessage(
539  __('Quantity was recalculated from %1 to %2', $itemInfo['before_suggest_qty'], $qty),
540  'quote_item' . $item->getId()
541  );
542  }
543  }
544  }
545 
546  if ($qtyRecalculatedFlag) {
547  $this->messageManager->addNoticeMessage(
548  __('We adjusted product quantities to fit the required increments.')
549  );
550  }
551 
552  $this->_eventManager->dispatch(
553  'checkout_cart_update_items_after',
554  ['cart' => $this, 'info' => $infoDataObject]
555  );
556 
557  return $this;
558  }
559 
567  public function removeItem($itemId)
568  {
569  $this->getQuote()->removeItem($itemId);
570  return $this;
571  }
572 
578  public function save()
579  {
580  $this->_eventManager->dispatch('checkout_cart_save_before', ['cart' => $this]);
581 
582  $this->getQuote()->getBillingAddress();
583  $this->getQuote()->getShippingAddress()->setCollectShippingRates(true);
584  $this->getQuote()->collectTotals();
585  $this->quoteRepository->save($this->getQuote());
586  $this->_checkoutSession->setQuoteId($this->getQuote()->getId());
590  $this->_eventManager->dispatch('checkout_cart_save_after', ['cart' => $this]);
591  $this->reinitializeState();
592  return $this;
593  }
594 
601  public function saveQuote()
602  {
603  $this->save();
604  }
605 
612  public function truncate()
613  {
614  $this->getQuote()->removeAllItems();
615  return $this;
616  }
617 
621  public function getProductIds()
622  {
623  if (null === $this->_productIds) {
624  $this->_productIds = [];
625  if ($this->getSummaryQty() > 0) {
626  foreach ($this->getQuote()->getAllItems() as $item) {
627  $this->_productIds[] = $item->getProductId();
628  }
629  }
630  $this->_productIds = array_unique($this->_productIds);
631  }
632  return $this->_productIds;
633  }
634 
640  public function getSummaryQty()
641  {
642  $quoteId = $this->_checkoutSession->getQuoteId();
643 
644  //If there is no quote id in session trying to load quote
645  //and get new quote id. This is done for cases when quote was created
646  //not by customer (from backend for example).
647  if (!$quoteId && $this->_customerSession->isLoggedIn()) {
648  $this->_checkoutSession->getQuote();
649  $quoteId = $this->_checkoutSession->getQuoteId();
650  }
651 
652  if ($quoteId && $this->_summaryQty === null) {
653  $useQty = $this->_scopeConfig->getValue(
654  'checkout/cart_link/use_qty',
656  );
657  $this->_summaryQty = $useQty ? $this->getItemsQty() : $this->getItemsCount();
658  }
659  return $this->_summaryQty;
660  }
661 
668  public function getItemsCount()
669  {
670  return $this->getQuote()->getItemsCount() * 1;
671  }
672 
679  public function getItemsQty()
680  {
681  return $this->getQuote()->getItemsQty() * 1;
682  }
683 
698  public function updateItem($itemId, $requestInfo = null, $updatingParams = null)
699  {
700  try {
701  $item = $this->getQuote()->getItemById($itemId);
702  if (!$item) {
703  throw new \Magento\Framework\Exception\LocalizedException(__('This quote item does not exist.'));
704  }
705  $productId = $item->getProduct()->getId();
706  $product = $this->_getProduct($productId);
708 
709  if ($productId) {
710  $stockItem = $this->stockRegistry->getStockItem($productId, $product->getStore()->getWebsiteId());
711  $minimumQty = $stockItem->getMinSaleQty();
712  // If product was not found in cart and there is set minimal qty for it
713  if ($minimumQty
714  && $minimumQty > 0
715  && !$request->getQty()
716  && !$this->getQuote()->hasProductId($productId)
717  ) {
718  $request->setQty($minimumQty);
719  }
720  }
721 
722  $result = $this->getQuote()->updateItem($itemId, $request, $updatingParams);
723  } catch (\Magento\Framework\Exception\LocalizedException $e) {
724  $this->_checkoutSession->setUseNotice(false);
725  $result = $e->getMessage();
726  }
727 
731  if (is_string($result)) {
732  if ($this->_checkoutSession->getUseNotice() === null) {
733  $this->_checkoutSession->setUseNotice(true);
734  }
735  throw new \Magento\Framework\Exception\LocalizedException(__($result));
736  }
737 
738  $this->_eventManager->dispatch(
739  'checkout_cart_product_update_after',
740  ['quote_item' => $result, 'product' => $product]
741  );
742  $this->_checkoutSession->setLastAddedProductId($productId);
743  return $result;
744  }
745 
752  private function getRequestInfoFilter()
753  {
754  if ($this->requestInfoFilter === null) {
755  $this->requestInfoFilter = \Magento\Framework\App\ObjectManager::getInstance()
756  ->get(\Magento\Checkout\Model\Cart\RequestInfoFilterInterface::class);
757  }
758  return $this->requestInfoFilter;
759  }
760 }
updateItem($itemId, $requestInfo=null, $updatingParams=null)
Definition: Cart.php:698
_getProductRequest($requestInfo)
Definition: Cart.php:339
getData($key='', $index=null)
Definition: DataObject.php:119
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
$orderItem
Definition: order.php:30
addOrderItem($orderItem, $qtyFlag=null)
Definition: Cart.php:264
$quote
$storeManager
__()
Definition: __.php:13
addProduct($productInfo, $requestInfo=null)
Definition: Cart.php:366
__construct(\Magento\Framework\Event\ManagerInterface $eventManager, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Checkout\Model\ResourceModel\Cart $resourceCart, Session $checkoutSession, \Magento\Customer\Model\Session $customerSession, \Magento\Framework\Message\ManagerInterface $messageManager, \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry, \Magento\CatalogInventory\Api\StockStateInterface $stockState, \Magento\Quote\Api\CartRepositoryInterface $quoteRepository, ProductRepositoryInterface $productRepository, array $data=[])
Definition: Cart.php:120
$quoteItem
Definition: quote.php:38
setQuote(\Magento\Quote\Model\Quote $quote)
Definition: Cart.php:232
foreach($optionCollection as $option) $requestInfo
setData($key, $value=null)
Definition: DataObject.php:72
addProductsByIds($productIds)
Definition: Cart.php:425
_getProduct($productInfo)
Definition: Cart.php:298
foreach( $_productCollection as $_product)() ?>" class $info
Definition: listing.phtml:52