PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.0
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.0
1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 trunk All 48 releases
fluent-cart / api / Resource / FrontendResource / CartResource.php

CartResource.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.6.0, at api/Resource/FrontendResource/CartResource.php

820 lines 25.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\Api\Resource\FrontendResource;
4
5 use FluentCart\Api\Cookie\Cookie;
6 use FluentCart\Api\Resource\BaseResourceApi;
7 use FluentCart\App\App;
8 use FluentCart\App\Helpers\AddressHelper;
9 use FluentCart\App\Helpers\CartHelper;
10 use FluentCart\App\Helpers\Helper;
11 use FluentCart\App\Models\Cart;
12 use FluentCart\App\Models\Customer;
13 use FluentCart\App\Models\ProductVariation;
14 use FluentCart\App\Services\RateLimiter;
15 use FluentCart\Framework\Database\Orm\Builder;
16 use FluentCart\Framework\Support\Arr;
17 use FluentCart\Framework\Support\Collection;
18 use WP_Error;
19
20 class CartResource extends BaseResourceApi
21 {
22
23 /**
24 * Per-request memo for get(). In production every HTTP request runs in a
25 * fresh PHP process, so this lives exactly one request. Long-running
26 * processes that simulate multiple requests (test suites, CLI) must clear
27 * it between simulated requests via resetCartCache() — as a
28 * function-static it was unreachable and leaked the first request's cart
29 * into every subsequent one.
30 *
31 * Only a resolved Cart is memoized; a null ("no cart") result is
32 * deliberately re-queried on the next call — matching the original
33 * function-static behavior, where isset(null) === false.
34 *
35 * @var Cart|null|false false = not resolved yet
36 */
37 private static $cartCache = false;
38
39 public static function resetCartCache(): void
40 {
41 static::$cartCache = false;
42 }
43
44 public static function getQuery(): Builder
45 {
46 return Cart::query();
47 }
48
49 public static function generateCartForInstantCheckout($variationId, $quantity = 1, $params = [])
50 {
51 RateLimiter::isSpamming('generate_instant_checkout_cart_attempt', 10, 60, true);
52
53 $isCustom = Arr::get($params, 'is_custom', false);
54
55 if($isCustom) {
56 $variation = Arr::get($params, 'variation');
57 $variation = CartHelper::normalizeCustomFields($variation);
58 }
59 else {
60 // product_detail must be eager-loaded — generateCartItemFromVariation
61 // reads $variation['product_detail']['variation_type'] to stamp
62 // the cart item's variation_type. Without it the field is null on
63 // instant-checkout carts and CartRenderer can't tell whether to
64 // hide the variant-title line for simple products.
65 $variation = ProductVariation::query()
66 ->with(['product', 'product_detail', 'media', 'shippingClass'])
67 ->where('id', $variationId)->first();
68
69 $variation = apply_filters('fluent_cart/cart/item_modify', $variation, [
70 'item_id' => $variationId,
71 'quantity' => $quantity,
72 ]);
73 }
74
75 if (!$variation) {
76 return new WP_Error(__('Invalid Product', 'fluent-cart'));
77 }
78
79 $quantity = apply_filters('fluent_cart/item_max_quantity', $quantity, [
80 'variation' => $variation,
81 'product' => !$isCustom ? $variation->product : []
82 ]);
83
84 if ($variation->payment_type === 'subscription') {
85 $quantity = 1;
86 }
87
88 if(!$isCustom) {
89 $canPurchase = $variation->canPurchase($quantity);
90 if (is_wp_error($canPurchase)) {
91 return $canPurchase;
92 }
93 }
94
95 $cartQuery = Cart::query()
96 ->whereJsonLength('cart_data', 1)
97 ->whereRaw("JSON_UNQUOTE(JSON_EXTRACT(cart_data, '$[0].id')) = ?", [(string)$variationId])
98 ->whereRaw("JSON_UNQUOTE(JSON_EXTRACT(cart_data, '$[0].quantity')) = ?", [(string)$quantity])
99 ->where('cart_group', 'instant')
100 ->where('stage', '==', 'draft');
101
102 if (is_user_logged_in()) {
103 $cartQuery->where('user_id', get_current_user_id());
104 } else {
105 $cartQuery->whereNull('user_id');
106 }
107
108 $cart = $cartQuery->first();
109
110 if (!$cart) {
111 if(!$isCustom) {
112 $cart = CartHelper::generateCartFromVariation($variation, $quantity);
113 }
114 else {
115 // Legacy object-to-array conversion. Kept for backward compatibility.
116 $cart = CartHelper::generateCartFromCustomVariation(json_decode(json_encode($variation), true), $quantity);
117 }
118 } else {
119 // Refresh cart_data from the current variation on every instant hit.
120 // The inputs (variationId + quantity) are deterministic URL params,
121 // so regenerating is idempotent — and it picks up any fields that
122 // were missing on a previously-created draft (variation_type for
123 // advanced-variation rows, refreshed pricing, updated featured
124 // media). Without this, a stale draft from before a code change
125 // keeps rendering with its old shape.
126 if (!$isCustom) {
127 $cart->cart_data = [
128 CartHelper::generateCartItemFromVariation($variation, $quantity)
129 ];
130 } else {
131 $cart->cart_data = [
132 CartHelper::generateCartItemCustomItem(json_decode(json_encode($variation), true), $quantity)
133 ];
134 }
135 }
136
137 if (is_user_logged_in()) {
138 $cart->user_id = get_current_user_id();
139 }
140
141 $cart->cart_group = 'instant';
142
143 $cart->cart_hash = md5(time() . wp_generate_uuid4());
144
145 $cart->save();
146 return $cart;
147
148 }
149
150 /**
151 * Retrieve cart based on the provided parameters.
152 *
153 * This function looks for a cart associated with the provided cart hash. If no cart is found,
154 * it creates a new cart for anonymous users. If the user is logged in, it associates the cart
155 * with the logged-in user.
156 *
157 * @param array $params Optional. Additional parameters for cart retrieval.
158 * [
159 * // Include optional parameters, if any.
160 * ]
161 *
162 */
163 public static function get(array $params = [])
164 {
165 if (static::$cartCache !== false && static::$cartCache !== null) {
166 return static::$cartCache;
167 }
168
169 $autoCreate = Arr::get($params, 'create', false);
170
171 $cartHash = Arr::get($params, 'hash');
172
173 //$cartHash = App::request()->get('fct_cart_hash');
174
175 if ($cartHash) {
176 $cartQuery = static::getQuery()
177 ->where('cart_hash', $cartHash)
178 ->where('stage', '!=', 'completed')
179 ->where('cart_group', 'instant');
180
181 $tempCart = $cartQuery->first();
182
183 static::$cartCache = $tempCart;
184
185 if (!$autoCreate) {
186 return $tempCart;
187 }
188 }
189
190 static::$cartCache = static::getOrSetCartForThisDevice($autoCreate);
191
192 return static::$cartCache;
193 }
194
195 public static function find($id, $params = [])
196 {
197
198 }
199
200 /**
201 * Create cart with the provided item data.
202 *
203 * @param array $data Required. Array containing the necessary parameters
204 * [
205 * 'id' => (int) Required.The ID of the item,
206 * 'quantity' => (int) Optional.The quantity of the item
207 * ]
208 * @param array $params Optional. Additional parameters for cart creation or update.
209 * [
210 * // Include optional parameters, if any.
211 * ]
212 *
213 */
214 public static function create($data, $params = [])
215 {
216 $itemId = Arr::get($data, 'id');
217 $quantity = Arr::get($data, 'quantity', 1);
218
219 if ($quantity <= 0) {
220 return static::makeErrorResponse([
221 ['code' => 403, 'message' => __('Quantity can not be negative.', 'fluent-cart')]
222 ]);
223 }
224
225 $cart = CartResource::get([
226 'create' => true
227 ]);
228 $cartArray = $cart->cart_data;
229
230 $cartArray = self::updateCartItemsQuantity(
231 [
232 'item_id' => $itemId,
233 'increment_by' => $quantity,
234 'existing_items' => $cartArray
235 ]
236 );
237
238 if (Arr::get($cartArray, 'code', '') === 'failed') {
239 return static::makeErrorResponse([
240 ['code' => 423, 'message' => Arr::get($cartArray, 'message', __('Cart validation error!', 'fluent-cart'))]
241 ]);
242 }
243
244 $cart->cart_data = Arr::get($cartArray, 'cart_data');
245 $message = Arr::get($cartArray, 'message');
246
247 $isCreated = $cart->save();
248
249 if ($isCreated) {
250 return static::makeSuccessResponse(
251 $isCreated,
252 __('Successfully added!', 'fluent-cart')
253 );
254 }
255
256 return static::makeErrorResponse([
257 ['code' => 400, 'message' => __('Could not add', 'fluent-cart')]
258 ]);
259 }
260
261 /**
262 * Update the quantity of an item in the cart.
263 *
264 * @param array $data Required. Array containing the necessary parameters for item quantity
265 * [
266 * 'item_id' => (int) Required.The ID of the product_variation,
267 * 'quantity'=> (int) Optional.The quantity of the item
268 * ]
269 * @param int $id Required. The ID of the cart.
270 * @param array $params Optional. Additional parameters for updating cart
271 * [
272 * // Include optional parameters, if any.
273 * ]
274 *
275 */
276 public static function update($data, $id = '', $params = [])
277 {
278 $cart = self::get([
279 'create' => true,
280 'hash' => Arr::get($params, 'hash'),
281 ]);
282
283 $itemId = (int)Arr::get($data, 'item_id');
284 $quantity = Arr::get($data, 'quantity', 0);
285 $byInput = (bool)Arr::get($data, 'by_input', false);
286
287 if (!$itemId) {
288 return new WP_Error(
289 'invalid_item',
290 __('Invalid item.', 'fluent-cart')
291 );
292 }
293
294 $existingItem = $cart->findExistingItemAndIndex($itemId);
295 $existingItem = Arr::get($existingItem, 1);
296
297 $rawIsCustom = $existingItem !== null
298 ? Arr::get($existingItem, 'is_custom', false)
299 : Arr::get($data, 'is_custom', false);
300
301 $isCustom = in_array(
302 strtolower((string) $rawIsCustom),
303 ['1', 'true'],
304 true
305 );
306
307 if($isCustom){
308 // Detect item and quantity change, let external modify item
309 if ($existingItem) {
310 $changedVariation = apply_filters('fluent_cart/cart/custom_item_quantity_changed', $existingItem,
311 [
312 'old_quantity' => (int) Arr::get($existingItem, 'quantity', 0),
313 'new_quantity' => $quantity,
314 'by_input' => $byInput,
315 'is_changed' => true,
316 'is_custom' => $isCustom,
317 ]);
318
319 if (!is_object($changedVariation)) {
320 $changedVariation = (object) $changedVariation;
321 }
322
323 $variation = $changedVariation;
324
325 $quantity = isset($changedVariation->quantity)
326 ? (int) $changedVariation->quantity
327 : 0;
328 }
329 else {
330 $variation = apply_filters('fluent_cart/cart/validate_custom_item', $existingItem, [
331 'item_id' => $itemId,
332 'quantity' => $quantity,
333 'is_custom' => $isCustom,
334 ]);
335
336 if (!is_object($variation)) {
337 $variation = (object) $variation;
338 }
339 }
340
341 if (!$variation || !is_object($variation)) {
342 return new WP_Error('invalid_custom_item',
343 __('Invalid custom item data.', 'fluent-cart'));
344 }
345
346 }else{
347 $variation = ProductVariation::query()->where('id', $itemId)->with('product')->first();
348 $variation = apply_filters('fluent_cart/cart/item_modify', $variation, [
349 'item_id' => $itemId,
350 'quantity' => $quantity,
351 ]);
352 }
353
354 if (!$variation) {
355 return $cart->removeItem($itemId);
356 }
357
358 $soldIndividually = $isCustom
359 ? !empty($variation->sold_individually)
360 : (bool) $variation->soldIndividually();
361
362 if ($soldIndividually) {
363 if ($quantity >= 1) {
364 $quantity = 1;
365 }
366 $byInput = true;
367 }
368
369 if($isCustom) {
370 $cart = $cart->addByCustom(
371 is_array($variation) ? $variation : (array) $variation,
372 [
373 'quantity' => $quantity,
374 'is_custom' => $isCustom,
375 ]
376 );
377
378 }
379 else {
380 $cart = $cart->addByVariation($variation, [
381 'quantity' => $quantity,
382 'by_input' => $byInput,
383 'will_validate' => true,
384 'replace' => false,
385 'is_custom' => $isCustom,
386 ]);
387 }
388
389
390 if (is_wp_error($cart)) {
391 return $cart;
392 }
393
394 $utmData = static::prepareUtmData($data);
395 if ($utmData) {
396 $cart->utm_data = array_merge(is_array($cart->utm_data) ? $cart->utm_data : [], $utmData);
397 $cart->save();
398 }
399
400 return $cart;
401 }
402
403 public static function prepareUtmData(array $params): array
404 {
405 $data = [];
406 $allowedUtmParams = [
407 'utm_campaign',
408 'utm_content',
409 'utm_term',
410 'utm_source',
411 'utm_medium',
412 'utm_id',
413 'refer_url',
414 'fbclid',
415 'gclid'
416 ];
417
418 foreach ($allowedUtmParams as $utmParam) {
419 if (isset($params[$utmParam])) {
420 $data[$utmParam] = $params[$utmParam];
421 }
422 }
423 return $data;
424 }
425
426 /**
427 * Delete cart based on the provided user ID or cart hash.
428 *
429 * @param int $id Required. The user ID associated with the cart.
430 * @param array $params Optional. Additional parameters for cart deletion.
431 * [
432 * 'cart_hash' => (string) Optional. The cart hash for additional identification.
433 * ]
434 *
435 */
436 public static function delete($id, $params = [])
437 {
438 $cart = static::get();
439
440 if (empty($cart)) {
441 return null;
442 }
443
444 $deleted = $cart->delete();
445
446 if ($deleted) {
447 Cookie::deleteCartHash();
448 }
449
450 return $deleted;
451 }
452
453 public static function getStatus(): array
454 {
455 $cart = static::get(
456 [
457 'create' => false // Do not create a new cart if it doesn't exist
458 ]
459 );
460
461 if (!$cart) {
462 return [];
463 }
464
465 return [
466 'cart_hash' => $cart->cart_hash,
467 'cart_data' => $cart->cart_data,
468 'cart_user' => $cart->user_id,
469 ];
470 }
471
472 public static function isLicensedProduct($productVariation): bool
473 {
474 return Helper::hasLicense(Arr::get($productVariation, 'product'));
475 }
476
477
478 private static function validateShouldAddProduct($productVariation, $existingItemsArray)
479 {
480 if (Arr::get($productVariation, 'product.post_status') !== 'publish') {
481 return new WP_Error(
482 'item_not_available',
483 __('Item is not available.', 'fluent-cart')
484 );
485 }
486
487 $variationIds = (new Collection($existingItemsArray))->pluck('object_id');
488 $paymentType = Arr::get($productVariation, 'other_info.payment_type', false);
489
490 $hasInstantCheckoutParam = !empty(App::request()->get(Helper::INSTANT_CHECKOUT_URL_PARAM));
491
492 //early return as don't allow subscription item to add in cart
493 if ($paymentType !== 'onetime' && !$hasInstantCheckoutParam) {
494 return new WP_Error(
495 'item_not_available',
496 __('Item is not available.', 'fluent-cart')
497 );
498 }
499 $hasSubscription = static::hasSubscriptionProduct($existingItemsArray);
500
501 if (!$variationIds->contains(Arr::get($productVariation, 'id')) || empty($existingItemsArray)) {
502 return new WP_Error(
503 'item_not_available',
504 __('Item is not available.', 'fluent-cart')
505 );
506
507 }
508
509 if ($paymentType === 'onetime' && !$hasSubscription) {
510 return true;
511 }
512
513 if ($paymentType === 'onetime' && $hasSubscription) {
514 return new WP_Error(
515 'subscription_items_can_not_combined',
516 __('Subscription items can\'t be combined with other products in the cart.', 'fluent-cart')
517 );
518 }
519
520 return new WP_Error(
521 'item_not_available',
522 __('Item is not available.', 'fluent-cart')
523 );
524 }
525
526 public static function hasSubscriptionProduct($existingItemsArray = []): bool
527 {
528 $subscriptionProduct = (new Collection($existingItemsArray))->pluck('other_info')->filter(function ($info) {
529 $otherInfo = (array)$info;
530 $type = Arr::get($otherInfo, 'payment_type', false);
531 return $type === 'subscription';
532 });
533 return $subscriptionProduct->count() > 0;
534 }
535
536 private static function removeItemFromCart($existingItemsArray, $index): array
537 {
538 unset($existingItemsArray[$index]);
539 $message = __('Item removed from cart', 'fluent-cart');
540 return [
541 'message' => $message,
542 'cart_data' => $existingItemsArray,
543 ];
544 }
545
546 public static function updateItemQuantityInCart($productVariation, $existingItemsArray, $index, $quantity = 1, $isFilteredItem = false): array
547 {
548 $canBeAdded = true;
549
550
551 if (!$isFilteredItem) {
552 $canBeAdded = static::validateShouldAddProduct($productVariation, $existingItemsArray);
553 }
554
555
556 if (is_wp_error($canBeAdded)) {
557 return [
558 'code' => 'failed',
559 'message' => $canBeAdded->get_error_message()
560 ];
561 }
562
563 $updatedQuantity = $existingItemsArray[$index]['quantity'] + $quantity;
564
565 if ($updatedQuantity < 0) {
566 $updatedQuantity = 0;
567 }
568
569 if (!$isFilteredItem) {
570
571 if (!CartHelper::shouldAddItemToCart($productVariation, $updatedQuantity)) {
572 return [
573 'code' => 'failed',
574 'message' => __("You've reached the maximum quantity for this product.", 'fluent-cart')
575 ];
576 }
577 }
578
579 if ($productVariation instanceof ProductVariation) {
580 $item = CartHelper::generateCartItemFromVariation($productVariation, $updatedQuantity);
581 } else {
582 $item = CartHelper::generateCartItemCustomItem($productVariation, $updatedQuantity);
583 }
584
585
586 $existingItemsArray[$index] = $item;
587 return [
588 'message' => __('Quantity updated!', 'fluent-cart'),
589 'cart_data' => $existingItemsArray,
590 ];
591 }
592
593 public static function addItemInCart($productVariation, $existingItemsArray, $index, $quantity = 1, $isFilteredItem = false): array
594 {
595
596 if ($quantity < 1) {
597 $quantity = 1;
598 }
599 if (!$isFilteredItem) {
600 if (!CartHelper::shouldAddItemToCart($productVariation, $quantity)) {
601 return [
602 'code' => 'failed',
603 'message' => sprintf(
604 /* translators: %s is the product title */
605 __('%s is out of stock', 'fluent-cart'),
606 Arr::get($productVariation, 'variation_title')
607 ),
608 ];
609 }
610
611 $paymentType = $productVariation instanceof ProductVariation
612 ? $productVariation->payment_type
613 : Arr::get($productVariation, 'payment_type');
614
615 if ($paymentType === 'subscription' && $quantity > 1) {
616 return [
617 'code' => 'failed',
618 'message' => __('You cannot purchase more than one subscription at a time.', 'fluent-cart'),
619 ];
620 }
621
622 if (!empty($existingItemsArray)) {
623 $hasSubscription = static::hasSubscriptionProduct($existingItemsArray);
624
625 if ($paymentType === 'subscription' || $hasSubscription) {
626 return [
627 'code' => 'failed',
628 'message' => __("Subscription items can't be combined with other products in the cart.", 'fluent-cart'),
629 ];
630 }
631 }
632 }
633
634 if ($productVariation instanceof ProductVariation) {
635 $item = CartHelper::generateCartItemFromVariation($productVariation, $quantity);
636 } else {
637 $item = CartHelper::generateCartItemCustomItem($productVariation, $quantity);
638 }
639
640
641 $existingItemsArray[] = static::getCartSingleItemPreparedArray(
642 [
643 'variation' => $productVariation,
644 'quantity' => $quantity
645 ]
646 );
647
648
649 return [
650 'message' => __('Item added in cart!', 'fluent-cart'),
651 'cart_data' => $existingItemsArray,
652 ];
653 }
654
655 private static function updateCartItemsQuantity($params = []): array
656 {
657 $itemId = Arr::get($params, 'item_id');
658
659 $incrementBy = Arr::get($params, 'increment_by');
660 $existingItemsArray = Arr::get($params, 'existing_items', []);
661 if (!is_array($existingItemsArray)) {
662 $existingItemsArray = [];
663 }
664
665
666 $index = -1;
667
668 foreach ($existingItemsArray as $itemIndex => $existingItem) {
669 if (Arr::get($existingItem, 'object_id') == $itemId) {
670 $index = $itemIndex;
671 break;
672 }
673 }
674
675
676 /** @var $productVariation ProductVariation */
677 if ($incrementBy == 0) {
678 return static::removeItemFromCart($existingItemsArray, $index);
679 }
680
681 $productVariation = ProductVariation::query()->where('id', $itemId)->with([
682 'product',
683 'product.detail',
684 'product.licensesMeta',
685 'product_detail',
686 'media',
687 'shippingClass'
688 ])->first();
689
690
691 $isFilteredItem = false;
692 if (empty($productVariation)) {
693 $isFilteredItem = true;
694 $productVariation = apply_filters('fluent_cart/cart_item_product_variation', $productVariation, $itemId, $incrementBy, $existingItemsArray);
695 }
696
697
698 if (empty($productVariation)) {
699 return [
700 'code' => 'failed',
701 'message' => __('Item is not available.', 'fluent-cart')
702 ];
703 }
704
705 //($index === 0 || !empty($index)) && isset($existingItemsArray[$index])
706 //inline check will not work
707
708 $isValidIndex = false;
709 if ($index != -1) {
710 $isValidIndex = true;
711 }
712
713 if ($isValidIndex && isset($existingItemsArray[$index])) {
714
715 return static::updateItemQuantityInCart(
716 $productVariation,
717 $existingItemsArray,
718 $index,
719 $incrementBy,
720 $isFilteredItem,
721 );
722 }
723
724 return static::addItemInCart(
725 $productVariation,
726 $existingItemsArray,
727 $index,
728 $incrementBy,
729 $isFilteredItem,
730 );
731 }
732
733
734 private static function getCartSingleItemPreparedArray($params = []): array
735 {
736
737 $variation = Arr::get($params, 'variation');
738 $quantity = Arr::get($params, 'quantity');
739 return CartHelper::generateCartItemFromVariation($variation, $quantity);
740
741 }
742
743 /**
744 * Check if cart exists
745 */
746
747 public static function getOrSetCartForThisDevice($autoCreate = false)
748 {
749
750 $cartHash = Cookie::getCartHash();
751
752 if ($cartHash) {
753 $cart = static::getQuery()
754 ->where('stage', '!=', 'completed')
755 ->where('cart_hash', $cartHash)
756 ->where('cart_group', 'global')
757 ->first();
758
759 if ($cart) {
760 return $cart;
761 }
762 }
763
764 $userId = get_current_user_id();
765 if ($userId) {
766 // Latest cart first — without an order, first() picks by primary key
767 // (cart_hash), which resurrects an arbitrary old cart for the user.
768 $cart = static::getQuery()
769 ->where('user_id', $userId)
770 ->where('stage', '!=', 'completed')
771 ->where('cart_group', 'global')
772 ->orderBy('updated_at', 'DESC')
773 ->first();
774
775 if ($cart) {
776 return $cart;
777 }
778 }
779
780 if (!$autoCreate) {
781 return null;
782 }
783
784 $cart = new Cart();
785 $cart->cart_data = [];
786
787 $cart = CartHelper::addCommonCartData($cart);
788
789 $cart->save();
790
791 Cookie::setCartHash($cart->cart_hash);
792
793 return $cart;
794 }
795
796 /**
797 * This method should be called only if no cart is found in a current device
798 */
799 private static function setupNewCart()
800 {
801 $cartArray['cart_data'] = [];
802 if ($userId = get_current_user_id()) {
803 $cartArray['user_id'] = $userId;
804 }
805 $cartArray['cart_group'] = 'global';
806 return Cart::query()->create($cartArray);
807
808 }
809
810 public static function resetCartData()
811 {
812 $cart = CartResource::get();
813
814 if (is_array($cart->cart_data) && !empty($cart->cart_data)) {
815 $cart->cart_data = [];
816 $cart->save();
817 }
818 }
819 }
820