123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Checkout\Model;
- use Magento\Catalog\Api\ProductRepositoryInterface;
- use Magento\Catalog\Model\Product;
- use Magento\Checkout\Model\Cart\CartInterface;
- use Magento\Framework\DataObject;
- use Magento\Framework\Exception\NoSuchEntityException;
- /**
- * Shopping cart model
- *
- * @api
- * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
- * @deprecated 100.1.0 Use \Magento\Quote\Model\Quote instead
- * @see \Magento\Quote\Api\Data\CartInterface
- * @since 100.0.2
- */
- class Cart extends DataObject implements CartInterface
- {
- /**
- * Shopping cart items summary quantity(s)
- *
- * @var int|null
- */
- protected $_summaryQty;
- /**
- * List of product ids in shopping cart
- *
- * @var int[]|null
- */
- protected $_productIds;
- /**
- * Core event manager proxy
- *
- * @var \Magento\Framework\Event\ManagerInterface
- */
- protected $_eventManager;
- /**
- * Core store config
- *
- * @var \Magento\Framework\App\Config\ScopeConfigInterface
- */
- protected $_scopeConfig;
- /**
- * @var \Magento\Store\Model\StoreManagerInterface
- */
- protected $_storeManager;
- /**
- * @var \Magento\Checkout\Model\ResourceModel\Cart
- */
- protected $_resourceCart;
- /**
- * @var Session
- */
- protected $_checkoutSession;
- /**
- * @var \Magento\Customer\Model\Session
- */
- protected $_customerSession;
- /**
- * @var \Magento\Framework\Message\ManagerInterface
- */
- protected $messageManager;
- /**
- * @var \Magento\CatalogInventory\Api\StockRegistryInterface
- */
- protected $stockRegistry;
- /**
- * @var \Magento\CatalogInventory\Api\StockStateInterface
- */
- protected $stockState;
- /**
- * @var \Magento\Quote\Api\CartRepositoryInterface
- */
- protected $quoteRepository;
- /**
- * @var ProductRepositoryInterface
- */
- protected $productRepository;
- /**
- * @var \Magento\Checkout\Model\Cart\RequestInfoFilterInterface
- */
- private $requestInfoFilter;
- /**
- * @param \Magento\Framework\Event\ManagerInterface $eventManager
- * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
- * @param \Magento\Store\Model\StoreManagerInterface $storeManager
- * @param \Magento\Checkout\Model\ResourceModel\Cart $resourceCart
- * @param Session $checkoutSession
- * @param \Magento\Customer\Model\Session $customerSession
- * @param \Magento\Framework\Message\ManagerInterface $messageManager
- * @param \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry
- * @param \Magento\CatalogInventory\Api\StockStateInterface $stockState
- * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository
- * @param ProductRepositoryInterface $productRepository
- * @param array $data
- * @codeCoverageIgnore
- * @SuppressWarnings(PHPMD.ExcessiveParameterList)
- */
- public function __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 = []
- ) {
- $this->_eventManager = $eventManager;
- $this->_scopeConfig = $scopeConfig;
- $this->_storeManager = $storeManager;
- $this->_resourceCart = $resourceCart;
- $this->_checkoutSession = $checkoutSession;
- $this->_customerSession = $customerSession;
- $this->messageManager = $messageManager;
- $this->stockRegistry = $stockRegistry;
- $this->stockState = $stockState;
- $this->quoteRepository = $quoteRepository;
- parent::__construct($data);
- $this->productRepository = $productRepository;
- }
- /**
- * Get shopping cart resource model
- *
- * @return \Magento\Checkout\Model\ResourceModel\Cart
- * @codeCoverageIgnore
- */
- protected function _getResource()
- {
- return $this->_resourceCart;
- }
- /**
- * Retrieve checkout session model
- *
- * @return Session
- * @codeCoverageIgnore
- */
- public function getCheckoutSession()
- {
- return $this->_checkoutSession;
- }
- /**
- * Retrieve customer session model
- *
- * @return \Magento\Customer\Model\Session
- * @codeCoverageIgnore
- */
- public function getCustomerSession()
- {
- return $this->_customerSession;
- }
- /**
- * List of shopping cart items
- *
- * @return \Magento\Eav\Model\Entity\Collection\AbstractCollection|array
- */
- public function getItems()
- {
- if (!$this->getQuote()->getId()) {
- return [];
- }
- return $this->getQuote()->getItemsCollection();
- }
- /**
- * Retrieve array of cart product ids
- *
- * @return array
- */
- public function getQuoteProductIds()
- {
- $products = $this->getData('product_ids');
- if ($products === null) {
- $products = [];
- foreach ($this->getQuote()->getAllItems() as $item) {
- $products[$item->getProductId()] = $item->getProductId();
- }
- $this->setData('product_ids', $products);
- }
- return $products;
- }
- /**
- * Get quote object associated with cart. By default it is current customer session quote
- *
- * @return \Magento\Quote\Model\Quote
- */
- public function getQuote()
- {
- if (!$this->hasData('quote')) {
- $this->setData('quote', $this->_checkoutSession->getQuote());
- }
- return $this->_getData('quote');
- }
- /**
- * Set quote object associated with the cart
- *
- * @param \Magento\Quote\Model\Quote $quote
- * @return $this
- * @codeCoverageIgnore
- */
- public function setQuote(\Magento\Quote\Model\Quote $quote)
- {
- $this->setData('quote', $quote);
- return $this;
- }
- /**
- * Reinitialize cart quote state
- *
- * @return $this
- */
- protected function reinitializeState()
- {
- $quote = $this->getQuote()->setCheckoutMethod('');
- $this->_checkoutSession->setCartWasUpdated(true);
- // TODO: Move this logic to Multishipping module as plug-in.
- // reset for multiple address checkout
- if ($this->_checkoutSession->getCheckoutState() !== Session::CHECKOUT_STATE_BEGIN
- && $this->_checkoutSession->getCheckoutState() !== null) {
- $quote->removeAllAddresses()->removePayment();
- $this->_checkoutSession->resetCheckout();
- }
- return $this;
- }
- /**
- * Convert order item to quote item
- *
- * @param \Magento\Sales\Model\Order\Item $orderItem
- * @param true|null $qtyFlag if is null set product qty like in order
- * @return $this
- */
- public function addOrderItem($orderItem, $qtyFlag = null)
- {
- /* @var $orderItem \Magento\Sales\Model\Order\Item */
- if ($orderItem->getParentItem() === null) {
- $storeId = $this->_storeManager->getStore()->getId();
- try {
- /**
- * We need to reload product in this place, because products
- * with the same id may have different sets of order attributes.
- */
- $product = $this->productRepository->getById($orderItem->getProductId(), false, $storeId, true);
- } catch (NoSuchEntityException $e) {
- return $this;
- }
- $info = $orderItem->getProductOptionByCode('info_buyRequest');
- $info = new \Magento\Framework\DataObject($info);
- if ($qtyFlag === null) {
- $info->setQty($orderItem->getQtyOrdered());
- } else {
- $info->setQty(1);
- }
- $this->addProduct($product, $info);
- }
- return $this;
- }
- /**
- * Get product object based on requested product information
- *
- * @param Product|int|string $productInfo
- * @return Product
- * @throws \Magento\Framework\Exception\LocalizedException
- */
- protected function _getProduct($productInfo)
- {
- $product = null;
- if ($productInfo instanceof Product) {
- $product = $productInfo;
- if (!$product->getId()) {
- throw new \Magento\Framework\Exception\LocalizedException(
- __("The product wasn't found. Verify the product and try again.")
- );
- }
- } elseif (is_int($productInfo) || is_string($productInfo)) {
- $storeId = $this->_storeManager->getStore()->getId();
- try {
- $product = $this->productRepository->getById($productInfo, false, $storeId);
- } catch (NoSuchEntityException $e) {
- throw new \Magento\Framework\Exception\LocalizedException(
- __("The product wasn't found. Verify the product and try again."),
- $e
- );
- }
- } else {
- throw new \Magento\Framework\Exception\LocalizedException(
- __("The product wasn't found. Verify the product and try again.")
- );
- }
- $currentWebsiteId = $this->_storeManager->getStore()->getWebsiteId();
- if (!is_array($product->getWebsiteIds()) || !in_array($currentWebsiteId, $product->getWebsiteIds())) {
- throw new \Magento\Framework\Exception\LocalizedException(
- __("The product wasn't found. Verify the product and try again.")
- );
- }
- return $product;
- }
- /**
- * Get request for product add to cart procedure
- *
- * @param \Magento\Framework\DataObject|int|array $requestInfo
- * @return \Magento\Framework\DataObject
- * @throws \Magento\Framework\Exception\LocalizedException
- */
- protected function _getProductRequest($requestInfo)
- {
- if ($requestInfo instanceof \Magento\Framework\DataObject) {
- $request = $requestInfo;
- } elseif (is_numeric($requestInfo)) {
- $request = new \Magento\Framework\DataObject(['qty' => $requestInfo]);
- } elseif (is_array($requestInfo)) {
- $request = new \Magento\Framework\DataObject($requestInfo);
- } else {
- throw new \Magento\Framework\Exception\LocalizedException(
- __('We found an invalid request for adding product to quote.')
- );
- }
- $this->getRequestInfoFilter()->filter($request);
- return $request;
- }
- /**
- * Add product to shopping cart (quote)
- *
- * @param int|Product $productInfo
- * @param \Magento\Framework\DataObject|int|array $requestInfo
- * @return $this
- * @throws \Magento\Framework\Exception\LocalizedException
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
- */
- public function addProduct($productInfo, $requestInfo = null)
- {
- $product = $this->_getProduct($productInfo);
- $request = $this->_getProductRequest($requestInfo);
- $productId = $product->getId();
- if ($productId) {
- $stockItem = $this->stockRegistry->getStockItem($productId, $product->getStore()->getWebsiteId());
- $minimumQty = $stockItem->getMinSaleQty();
- //If product quantity is not specified in request and there is set minimal qty for it
- if ($minimumQty
- && $minimumQty > 0
- && !$request->getQty()
- ) {
- $request->setQty($minimumQty);
- }
- try {
- $this->_eventManager->dispatch(
- 'checkout_cart_product_add_before',
- ['info' => $requestInfo, 'product' => $product]
- );
- $result = $this->getQuote()->addProduct($product, $request);
- } catch (\Magento\Framework\Exception\LocalizedException $e) {
- $this->_checkoutSession->setUseNotice(false);
- $result = $e->getMessage();
- }
- /**
- * String we can get if prepare process has error
- */
- if (is_string($result)) {
- if ($product->hasOptionsValidationFail()) {
- $redirectUrl = $product->getUrlModel()->getUrl(
- $product,
- ['_query' => ['startcustomization' => 1]]
- );
- } else {
- $redirectUrl = $product->getProductUrl();
- }
- $this->_checkoutSession->setRedirectUrl($redirectUrl);
- if ($this->_checkoutSession->getUseNotice() === null) {
- $this->_checkoutSession->setUseNotice(true);
- }
- throw new \Magento\Framework\Exception\LocalizedException(__($result));
- }
- } else {
- throw new \Magento\Framework\Exception\LocalizedException(__('The product does not exist.'));
- }
- $this->_eventManager->dispatch(
- 'checkout_cart_product_add_after',
- ['quote_item' => $result, 'product' => $product]
- );
- $this->_checkoutSession->setLastAddedProductId($productId);
- return $this;
- }
- /**
- * Adding products to cart by ids
- *
- * @param int[] $productIds
- * @return $this
- */
- public function addProductsByIds($productIds)
- {
- $allAvailable = true;
- $allAdded = true;
- if (!empty($productIds)) {
- foreach ($productIds as $productId) {
- $productId = (int)$productId;
- if (!$productId) {
- continue;
- }
- $product = $this->_getProduct($productId);
- if ($product->getId() && $product->isVisibleInCatalog()) {
- try {
- $this->getQuote()->addProduct($product);
- } catch (\Exception $e) {
- $allAdded = false;
- }
- } else {
- $allAvailable = false;
- }
- }
- if (!$allAvailable) {
- $this->messageManager->addErrorMessage(__("We don't have some of the products you want."));
- }
- if (!$allAdded) {
- $this->messageManager->addErrorMessage(__("We don't have as many of some products as you want."));
- }
- }
- return $this;
- }
- /**
- * Returns suggested quantities for items.
- * Can be used to automatically fix user entered quantities before updating cart
- * so that cart contains valid qty values
- *
- * The $data is an array of ($quoteItemId => (item info array with 'qty' key), ...)
- *
- * @param array $data
- * @return array
- */
- public function suggestItemsQty($data)
- {
- foreach ($data as $itemId => $itemInfo) {
- if (!isset($itemInfo['qty'])) {
- continue;
- }
- $qty = (float)$itemInfo['qty'];
- if ($qty <= 0) {
- continue;
- }
- $quoteItem = $this->getQuote()->getItemById($itemId);
- if (!$quoteItem) {
- continue;
- }
- $product = $quoteItem->getProduct();
- if (!$product) {
- continue;
- }
- $data[$itemId]['before_suggest_qty'] = $qty;
- $data[$itemId]['qty'] = $this->stockState->suggestQty(
- $product->getId(),
- $qty,
- $product->getStore()->getWebsiteId()
- );
- }
- return $data;
- }
- /**
- * Update cart items information
- *
- * @param array $data
- * @return $this
- * @throws \Magento\Framework\Exception\LocalizedException
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
- * @SuppressWarnings(PHPMD.NPathComplexity)
- */
- public function updateItems($data)
- {
- $infoDataObject = new \Magento\Framework\DataObject($data);
- $this->_eventManager->dispatch(
- 'checkout_cart_update_items_before',
- ['cart' => $this, 'info' => $infoDataObject]
- );
- $qtyRecalculatedFlag = false;
- foreach ($data as $itemId => $itemInfo) {
- $item = $this->getQuote()->getItemById($itemId);
- if (!$item) {
- continue;
- }
- if (!empty($itemInfo['remove']) || isset($itemInfo['qty']) && $itemInfo['qty'] == '0') {
- $this->removeItem($itemId);
- continue;
- }
- $qty = isset($itemInfo['qty']) ? (double)$itemInfo['qty'] : false;
- if ($qty > 0) {
- $item->setQty($qty);
- if ($item->getHasError()) {
- throw new \Magento\Framework\Exception\LocalizedException(__($item->getMessage()));
- }
- if (isset($itemInfo['before_suggest_qty']) && $itemInfo['before_suggest_qty'] != $qty) {
- $qtyRecalculatedFlag = true;
- $this->messageManager->addNoticeMessage(
- __('Quantity was recalculated from %1 to %2', $itemInfo['before_suggest_qty'], $qty),
- 'quote_item' . $item->getId()
- );
- }
- }
- }
- if ($qtyRecalculatedFlag) {
- $this->messageManager->addNoticeMessage(
- __('We adjusted product quantities to fit the required increments.')
- );
- }
- $this->_eventManager->dispatch(
- 'checkout_cart_update_items_after',
- ['cart' => $this, 'info' => $infoDataObject]
- );
- return $this;
- }
- /**
- * Remove item from cart
- *
- * @param int $itemId
- * @return $this
- * @codeCoverageIgnore
- */
- public function removeItem($itemId)
- {
- $this->getQuote()->removeItem($itemId);
- return $this;
- }
- /**
- * Save cart
- *
- * @return $this
- */
- public function save()
- {
- $this->_eventManager->dispatch('checkout_cart_save_before', ['cart' => $this]);
- $this->getQuote()->getBillingAddress();
- $this->getQuote()->getShippingAddress()->setCollectShippingRates(true);
- $this->getQuote()->collectTotals();
- $this->quoteRepository->save($this->getQuote());
- $this->_checkoutSession->setQuoteId($this->getQuote()->getId());
- /**
- * Cart save usually called after changes with cart items.
- */
- $this->_eventManager->dispatch('checkout_cart_save_after', ['cart' => $this]);
- $this->reinitializeState();
- return $this;
- }
- /**
- * Save cart (implement interface method)
- *
- * @return void
- * @codeCoverageIgnore
- */
- public function saveQuote()
- {
- $this->save();
- }
- /**
- * Mark all quote items as deleted (empty shopping cart)
- *
- * @return $this
- * @codeCoverageIgnore
- */
- public function truncate()
- {
- $this->getQuote()->removeAllItems();
- return $this;
- }
- /**
- * Get product ids.
- *
- * @return int[]
- */
- public function getProductIds()
- {
- if (null === $this->_productIds) {
- $this->_productIds = [];
- if ($this->getSummaryQty() > 0) {
- foreach ($this->getQuote()->getAllItems() as $item) {
- $this->_productIds[] = $item->getProductId();
- }
- }
- $this->_productIds = array_unique($this->_productIds);
- }
- return $this->_productIds;
- }
- /**
- * Get shopping cart items summary (includes config settings)
- *
- * @return int|float
- */
- public function getSummaryQty()
- {
- $quoteId = $this->_checkoutSession->getQuoteId();
- //If there is no quote id in session trying to load quote
- //and get new quote id. This is done for cases when quote was created
- //not by customer (from backend for example).
- if (!$quoteId && $this->_customerSession->isLoggedIn()) {
- $this->_checkoutSession->getQuote();
- $quoteId = $this->_checkoutSession->getQuoteId();
- }
- if ($quoteId && $this->_summaryQty === null) {
- $useQty = $this->_scopeConfig->getValue(
- 'checkout/cart_link/use_qty',
- \Magento\Store\Model\ScopeInterface::SCOPE_STORE
- );
- $this->_summaryQty = $useQty ? $this->getItemsQty() : $this->getItemsCount();
- }
- return $this->_summaryQty;
- }
- /**
- * Get shopping cart items count
- *
- * @return int
- * @codeCoverageIgnore
- */
- public function getItemsCount()
- {
- return $this->getQuote()->getItemsCount() * 1;
- }
- /**
- * Get shopping cart summary qty
- *
- * @return int|float
- * @codeCoverageIgnore
- */
- public function getItemsQty()
- {
- return $this->getQuote()->getItemsQty() * 1;
- }
- /**
- * Update item in shopping cart (quote)
- * $requestInfo - either qty (int) or buyRequest in form of array or \Magento\Framework\DataObject
- * $updatingParams - information on how to perform update, passed to Quote->updateItem() method
- *
- * @param int $itemId
- * @param int|array|\Magento\Framework\DataObject $requestInfo
- * @param null|array|\Magento\Framework\DataObject $updatingParams
- * @return \Magento\Quote\Model\Quote\Item|string
- * @throws \Magento\Framework\Exception\LocalizedException
- *
- * @see \Magento\Quote\Model\Quote::updateItem()
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
- */
- public function updateItem($itemId, $requestInfo = null, $updatingParams = null)
- {
- try {
- $item = $this->getQuote()->getItemById($itemId);
- if (!$item) {
- throw new \Magento\Framework\Exception\LocalizedException(__('This quote item does not exist.'));
- }
- $productId = $item->getProduct()->getId();
- $product = $this->_getProduct($productId);
- $request = $this->_getProductRequest($requestInfo);
- if ($productId) {
- $stockItem = $this->stockRegistry->getStockItem($productId, $product->getStore()->getWebsiteId());
- $minimumQty = $stockItem->getMinSaleQty();
- // If product was not found in cart and there is set minimal qty for it
- if ($minimumQty
- && $minimumQty > 0
- && !$request->getQty()
- && !$this->getQuote()->hasProductId($productId)
- ) {
- $request->setQty($minimumQty);
- }
- }
- $result = $this->getQuote()->updateItem($itemId, $request, $updatingParams);
- } catch (\Magento\Framework\Exception\LocalizedException $e) {
- $this->_checkoutSession->setUseNotice(false);
- $result = $e->getMessage();
- }
- /**
- * We can get string if updating process had some errors
- */
- if (is_string($result)) {
- if ($this->_checkoutSession->getUseNotice() === null) {
- $this->_checkoutSession->setUseNotice(true);
- }
- throw new \Magento\Framework\Exception\LocalizedException(__($result));
- }
- $this->_eventManager->dispatch(
- 'checkout_cart_product_update_after',
- ['quote_item' => $result, 'product' => $product]
- );
- $this->_checkoutSession->setLastAddedProductId($productId);
- return $result;
- }
- /**
- * Getter for RequestInfoFilter
- *
- * @deprecated 100.1.2
- * @return \Magento\Checkout\Model\Cart\RequestInfoFilterInterface
- */
- private function getRequestInfoFilter()
- {
- if ($this->requestInfoFilter === null) {
- $this->requestInfoFilter = \Magento\Framework\App\ObjectManager::getInstance()
- ->get(\Magento\Checkout\Model\Cart\RequestInfoFilterInterface::class);
- }
- return $this->requestInfoFilter;
- }
- }
|