Skip to content

Commit 6e5529f

Browse files
committed
ACP2E-368: Issue when adding multiple items in addProductsToCart graphQL mutation
1 parent b61fce5 commit 6e5529f

File tree

1 file changed

+57
-24
lines changed

1 file changed

+57
-24
lines changed

app/code/Magento/Quote/Model/Cart/AddProductsToCart.php

Lines changed: 57 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@
1010
use Magento\Catalog\Api\ProductRepositoryInterface;
1111
use Magento\Framework\Exception\NoSuchEntityException;
1212
use Magento\Quote\Api\CartRepositoryInterface;
13-
use Magento\Quote\Api\Data\CartInterface;
1413
use Magento\Quote\Model\Cart\BuyRequest\BuyRequestBuilder;
1514
use Magento\Quote\Model\Cart\Data\AddProductsToCartOutput;
1615
use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface;
1716
use Magento\Quote\Model\Quote;
1817
use Magento\Framework\Message\MessageInterface;
18+
use Magento\Quote\Model\Quote\Item;
19+
use Magento\Quote\Model\QuoteFactory;
1920

2021
/**
2122
* Unified approach to add products to the Shopping Cart.
@@ -67,7 +68,7 @@ class AddProductsToCart
6768
private $requestBuilder;
6869

6970
/**
70-
* @var \Magento\Quote\Model\QuoteFactory
71+
* @var QuoteFactory
7172
*/
7273
private $quoteFactory;
7374

@@ -76,14 +77,14 @@ class AddProductsToCart
7677
* @param CartRepositoryInterface $cartRepository
7778
* @param MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId
7879
* @param BuyRequestBuilder $requestBuilder
79-
* @param \Magento\Quote\Model\QuoteFactory $quoteFactory
80+
* @param QuoteFactory $quoteFactory
8081
*/
8182
public function __construct(
8283
ProductRepositoryInterface $productRepository,
8384
CartRepositoryInterface $cartRepository,
8485
MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId,
8586
BuyRequestBuilder $requestBuilder,
86-
\Magento\Quote\Model\QuoteFactory $quoteFactory
87+
QuoteFactory $quoteFactory
8788
) {
8889
$this->productRepository = $productRepository;
8990
$this->cartRepository = $cartRepository;
@@ -115,17 +116,9 @@ public function execute(string $maskedCartId, array $cartItems): AddProductsToCa
115116
}
116117

117118
foreach ($cartItems as $cartItemPosition => $cartItem) {
118-
$tempCart = $this->cloneQuote($cart);
119-
$tempCart->setHasError(false);
120-
$errors = $this->addItemToCart($tempCart, $cartItem, $cartItemPosition);
119+
$errors = $this->addItemToCart($cart, $cartItem, $cartItemPosition);
121120
if ($errors) {
122121
array_push($allErrors, ...$errors);
123-
} else {
124-
$cart->removeAllItems();
125-
foreach ($tempCart->getAllItems() as $quoteItem) {
126-
$quoteItem->setQuote($cart);
127-
$cart->addItem($quoteItem);
128-
}
129122
}
130123
}
131124

@@ -142,20 +135,23 @@ public function execute(string $maskedCartId, array $cartItems): AddProductsToCa
142135
/**
143136
* Adds a particular item to the shopping cart
144137
*
145-
* @param CartInterface|Quote $cart
138+
* @param Quote $cart
146139
* @param Data\CartItem $cartItem
147140
* @param int $cartItemPosition
148141
* @return array
149142
*/
150-
private function addItemToCart(CartInterface $cart, Data\CartItem $cartItem, int $cartItemPosition): array
143+
private function addItemToCart(Quote $cart, Data\CartItem $cartItem, int $cartItemPosition): array
151144
{
152145
$sku = $cartItem->getSku();
153146
$errors = [];
147+
$result = null;
148+
$product = null;
149+
$tempCart = $this->cloneQuote($cart);
150+
$tempCart->setHasError(false);
154151

155152
if ($cartItem->getQuantity() <= 0) {
156153
$errors[] = $this->createError(__('The product quantity should be greater than 0')->render());
157154
} else {
158-
$product = null;
159155
try {
160156
$product = $this->productRepository->get($sku, false, null, true);
161157
} catch (NoSuchEntityException $e) {
@@ -166,9 +162,8 @@ private function addItemToCart(CartInterface $cart, Data\CartItem $cartItem, int
166162
}
167163

168164
if ($product !== null) {
169-
$result = null;
170165
try {
171-
$result = $cart->addProduct($product, $this->requestBuilder->build($cartItem));
166+
$result = $tempCart->addProduct($product, $this->requestBuilder->build($cartItem));
172167
} catch (\Throwable $e) {
173168
$errors[] = $this->createError(
174169
__($e->getMessage())->render(),
@@ -184,6 +179,10 @@ private function addItemToCart(CartInterface $cart, Data\CartItem $cartItem, int
184179
}
185180
}
186181

182+
if (empty($errors)) {
183+
$this->addQuoteItem($cart, $result);
184+
}
185+
187186
return $errors;
188187
}
189188

@@ -226,11 +225,11 @@ private function getErrorCode(string $message): string
226225
/**
227226
* Creates a new output from existing errors
228227
*
229-
* @param CartInterface $cart
228+
* @param Quote $cart
230229
* @param array $errors
231230
* @return AddProductsToCartOutput
232231
*/
233-
private function prepareErrorOutput(CartInterface $cart, array $errors = []): AddProductsToCartOutput
232+
private function prepareErrorOutput(Quote $cart, array $errors = []): AddProductsToCartOutput
234233
{
235234
$output = new AddProductsToCartOutput($cart, $errors);
236235
$cart->setHasError(false);
@@ -239,9 +238,37 @@ private function prepareErrorOutput(CartInterface $cart, array $errors = []): Ad
239238
}
240239

241240
/**
242-
* Create temporary quote, which will incapsulate non-checked data.
241+
* Add quote item from temporary quote to real quote
243242
*
244-
* Under unchecked data, means, some data that can not pass validation or etc
243+
* @param Quote $quote
244+
* @param Item $quoteItem
245+
* @return void
246+
*/
247+
private function addQuoteItem(Quote $quote, Item $quoteItem): void
248+
{
249+
if ($quoteItem->getOriginalItem() && $quoteItem->getOriginalItem()->getId()) {
250+
$quote->deleteItem($quoteItem->getOriginalItem());
251+
$quoteItem->unsOriginalItem();
252+
}
253+
254+
$quoteItem->setQuote($quote);
255+
$quote->addItem($quoteItem);
256+
if ($quoteItem->getHasChildren()) {
257+
foreach ($quoteItem->getChildren() as $childQuoteItem) {
258+
$childQuoteItem->setQuote($quote);
259+
$quote->addItem($childQuoteItem);
260+
}
261+
}
262+
263+
$parentQuoteItem = $quoteItem->getParentItem();
264+
if ($parentQuoteItem) {
265+
$parentQuoteItem->setQuote($quote);
266+
$quote->addItem($parentQuoteItem);
267+
}
268+
}
269+
270+
/**
271+
* Create a clone quote.
245272
*
246273
* @param Quote $quote
247274
* @return Quote
@@ -254,13 +281,17 @@ private function cloneQuote(Quote $quote)
254281
$temporaryQuote->setData($quote->getData());
255282
$temporaryQuote->setId(null);//as it is clone, we need to flush ids
256283
$temporaryQuote->setStore($quote->getStore())->setIsSuperMode($quote->getIsSuperMode());
257-
/** @var Quote\Item $quoteItem */
284+
285+
/** @var Item $quoteItem */
258286
foreach ($quote->getAllItems() as $quoteItem) {
259287
$temporaryItem = clone $quoteItem;
260288
$temporaryItem->setQuote($temporaryQuote);
261289
$temporaryQuote->addItem($temporaryItem);
262290
$quoteItem->setClonnedItem($temporaryItem);
263-
291+
}
292+
/** @var Item $quoteItem */
293+
foreach ($quote->getAllItems() as $quoteItem) {
294+
$temporaryItem = $quoteItem->getClonnedItem();
264295
//Check for parent item
265296
$parentItem = null;
266297
if ($quoteItem->getParentItem()) {
@@ -272,6 +303,8 @@ private function cloneQuote(Quote $quote)
272303
if ($parentItem && $parentItem->getClonnedItem()) {
273304
$temporaryItem->setParentItem($parentItem->getClonnedItem());
274305
}
306+
$quoteItem->unsClonnedItem();
307+
$temporaryItem->setOriginalItem($quoteItem);
275308
}
276309

277310
return $temporaryQuote;

0 commit comments

Comments
 (0)