10
10
use Magento \Catalog \Api \ProductRepositoryInterface ;
11
11
use Magento \Framework \Exception \NoSuchEntityException ;
12
12
use Magento \Quote \Api \CartRepositoryInterface ;
13
- use Magento \Quote \Api \Data \CartInterface ;
14
13
use Magento \Quote \Model \Cart \BuyRequest \BuyRequestBuilder ;
15
14
use Magento \Quote \Model \Cart \Data \AddProductsToCartOutput ;
16
15
use Magento \Quote \Model \MaskedQuoteIdToQuoteIdInterface ;
17
16
use Magento \Quote \Model \Quote ;
18
17
use Magento \Framework \Message \MessageInterface ;
18
+ use Magento \Quote \Model \Quote \Item ;
19
+ use Magento \Quote \Model \QuoteFactory ;
19
20
20
21
/**
21
22
* Unified approach to add products to the Shopping Cart.
@@ -67,7 +68,7 @@ class AddProductsToCart
67
68
private $ requestBuilder ;
68
69
69
70
/**
70
- * @var \Magento\Quote\Model\ QuoteFactory
71
+ * @var QuoteFactory
71
72
*/
72
73
private $ quoteFactory ;
73
74
@@ -76,14 +77,14 @@ class AddProductsToCart
76
77
* @param CartRepositoryInterface $cartRepository
77
78
* @param MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId
78
79
* @param BuyRequestBuilder $requestBuilder
79
- * @param \Magento\Quote\Model\ QuoteFactory $quoteFactory
80
+ * @param QuoteFactory $quoteFactory
80
81
*/
81
82
public function __construct (
82
83
ProductRepositoryInterface $ productRepository ,
83
84
CartRepositoryInterface $ cartRepository ,
84
85
MaskedQuoteIdToQuoteIdInterface $ maskedQuoteIdToQuoteId ,
85
86
BuyRequestBuilder $ requestBuilder ,
86
- \ Magento \ Quote \ Model \ QuoteFactory $ quoteFactory
87
+ QuoteFactory $ quoteFactory
87
88
) {
88
89
$ this ->productRepository = $ productRepository ;
89
90
$ this ->cartRepository = $ cartRepository ;
@@ -115,17 +116,9 @@ public function execute(string $maskedCartId, array $cartItems): AddProductsToCa
115
116
}
116
117
117
118
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 );
121
120
if ($ errors ) {
122
121
array_push ($ allErrors , ...$ errors );
123
- } else {
124
- $ cart ->removeAllItems ();
125
- foreach ($ tempCart ->getAllItems () as $ quoteItem ) {
126
- $ quoteItem ->setQuote ($ cart );
127
- $ cart ->addItem ($ quoteItem );
128
- }
129
122
}
130
123
}
131
124
@@ -142,20 +135,23 @@ public function execute(string $maskedCartId, array $cartItems): AddProductsToCa
142
135
/**
143
136
* Adds a particular item to the shopping cart
144
137
*
145
- * @param CartInterface| Quote $cart
138
+ * @param Quote $cart
146
139
* @param Data\CartItem $cartItem
147
140
* @param int $cartItemPosition
148
141
* @return array
149
142
*/
150
- private function addItemToCart (CartInterface $ cart , Data \CartItem $ cartItem , int $ cartItemPosition ): array
143
+ private function addItemToCart (Quote $ cart , Data \CartItem $ cartItem , int $ cartItemPosition ): array
151
144
{
152
145
$ sku = $ cartItem ->getSku ();
153
146
$ errors = [];
147
+ $ result = null ;
148
+ $ product = null ;
149
+ $ tempCart = $ this ->cloneQuote ($ cart );
150
+ $ tempCart ->setHasError (false );
154
151
155
152
if ($ cartItem ->getQuantity () <= 0 ) {
156
153
$ errors [] = $ this ->createError (__ ('The product quantity should be greater than 0 ' )->render ());
157
154
} else {
158
- $ product = null ;
159
155
try {
160
156
$ product = $ this ->productRepository ->get ($ sku , false , null , true );
161
157
} catch (NoSuchEntityException $ e ) {
@@ -166,9 +162,8 @@ private function addItemToCart(CartInterface $cart, Data\CartItem $cartItem, int
166
162
}
167
163
168
164
if ($ product !== null ) {
169
- $ result = null ;
170
165
try {
171
- $ result = $ cart ->addProduct ($ product , $ this ->requestBuilder ->build ($ cartItem ));
166
+ $ result = $ tempCart ->addProduct ($ product , $ this ->requestBuilder ->build ($ cartItem ));
172
167
} catch (\Throwable $ e ) {
173
168
$ errors [] = $ this ->createError (
174
169
__ ($ e ->getMessage ())->render (),
@@ -184,6 +179,10 @@ private function addItemToCart(CartInterface $cart, Data\CartItem $cartItem, int
184
179
}
185
180
}
186
181
182
+ if (empty ($ errors )) {
183
+ $ this ->addQuoteItem ($ cart , $ result );
184
+ }
185
+
187
186
return $ errors ;
188
187
}
189
188
@@ -226,11 +225,11 @@ private function getErrorCode(string $message): string
226
225
/**
227
226
* Creates a new output from existing errors
228
227
*
229
- * @param CartInterface $cart
228
+ * @param Quote $cart
230
229
* @param array $errors
231
230
* @return AddProductsToCartOutput
232
231
*/
233
- private function prepareErrorOutput (CartInterface $ cart , array $ errors = []): AddProductsToCartOutput
232
+ private function prepareErrorOutput (Quote $ cart , array $ errors = []): AddProductsToCartOutput
234
233
{
235
234
$ output = new AddProductsToCartOutput ($ cart , $ errors );
236
235
$ cart ->setHasError (false );
@@ -239,9 +238,37 @@ private function prepareErrorOutput(CartInterface $cart, array $errors = []): Ad
239
238
}
240
239
241
240
/**
242
- * Create temporary quote, which will incapsulate non-checked data.
241
+ * Add quote item from temporary quote to real quote
243
242
*
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.
245
272
*
246
273
* @param Quote $quote
247
274
* @return Quote
@@ -254,13 +281,17 @@ private function cloneQuote(Quote $quote)
254
281
$ temporaryQuote ->setData ($ quote ->getData ());
255
282
$ temporaryQuote ->setId (null );//as it is clone, we need to flush ids
256
283
$ temporaryQuote ->setStore ($ quote ->getStore ())->setIsSuperMode ($ quote ->getIsSuperMode ());
257
- /** @var Quote\Item $quoteItem */
284
+
285
+ /** @var Item $quoteItem */
258
286
foreach ($ quote ->getAllItems () as $ quoteItem ) {
259
287
$ temporaryItem = clone $ quoteItem ;
260
288
$ temporaryItem ->setQuote ($ temporaryQuote );
261
289
$ temporaryQuote ->addItem ($ temporaryItem );
262
290
$ quoteItem ->setClonnedItem ($ temporaryItem );
263
-
291
+ }
292
+ /** @var Item $quoteItem */
293
+ foreach ($ quote ->getAllItems () as $ quoteItem ) {
294
+ $ temporaryItem = $ quoteItem ->getClonnedItem ();
264
295
//Check for parent item
265
296
$ parentItem = null ;
266
297
if ($ quoteItem ->getParentItem ()) {
@@ -272,6 +303,8 @@ private function cloneQuote(Quote $quote)
272
303
if ($ parentItem && $ parentItem ->getClonnedItem ()) {
273
304
$ temporaryItem ->setParentItem ($ parentItem ->getClonnedItem ());
274
305
}
306
+ $ quoteItem ->unsClonnedItem ();
307
+ $ temporaryItem ->setOriginalItem ($ quoteItem );
275
308
}
276
309
277
310
return $ temporaryQuote ;
0 commit comments