PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.4
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.4
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 1.2.0 All 47 releases
fluent-cart / api / Resource / FrontendResource / CartResource.php

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

836 lines 26.4 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 // An item already in the cart whose variation row has since
356 // disappeared (product/variation deleted) is dropped gracefully.
357 // An id that was never in the cart and resolves to nothing is a
358 // client error — silently answering "Cart updated successfully"
359 // hid typos and probing as a 200 no-op.
360 if ($existingItem !== null) {
361 return $cart->removeItem($itemId);
362 }
363
364 return new WP_Error(
365 'invalid_item',
366 __('Invalid item.', 'fluent-cart')
367 );
368 }
369
370 $soldIndividually = $isCustom
371 ? !empty($variation->sold_individually)
372 : (bool) $variation->soldIndividually();
373
374 if ($soldIndividually) {
375 if ($quantity >= 1) {
376 $quantity = 1;
377 }
378 $byInput = true;
379 }
380
381 if($isCustom) {
382 $cart = $cart->addByCustom(
383 is_array($variation) ? $variation : (array) $variation,
384 [
385 'quantity' => $quantity,
386 'is_custom' => $isCustom,
387 ]
388 );
389
390 }
391 else {
392 $cart = $cart->addByVariation($variation, [
393 'quantity' => $quantity,
394 'by_input' => $byInput,
395 'will_validate' => true,
396 'replace' => false,
397 'is_custom' => $isCustom,
398 ]);
399 }
400
401
402 if (is_wp_error($cart)) {
403 return $cart;
404 }
405
406 $utmData = static::prepareUtmData($data);
407 if ($utmData) {
408 // Replaced, not merged. A cart row is reused across visits, so merging
409 // key by key accumulated a union of every touch that ever reached it and
410 // the column stopped describing any single one. The browser has already
411 // resolved which touch this is, so its block is the answer.
412 $cart->utm_data = $utmData;
413 $cart->save();
414 }
415
416 return $cart;
417 }
418
419 public static function prepareUtmData(array $params): array
420 {
421 $data = [];
422 $allowedUtmParams = [
423 'utm_campaign',
424 'utm_content',
425 'utm_term',
426 'utm_source',
427 'utm_medium',
428 'utm_id',
429 'refer_url',
430 'fbclid',
431 'gclid'
432 ];
433
434 foreach ($allowedUtmParams as $utmParam) {
435 if (isset($params[$utmParam])) {
436 $data[$utmParam] = $params[$utmParam];
437 }
438 }
439 return $data;
440 }
441
442 /**
443 * Delete cart based on the provided user ID or cart hash.
444 *
445 * @param int $id Required. The user ID associated with the cart.
446 * @param array $params Optional. Additional parameters for cart deletion.
447 * [
448 * 'cart_hash' => (string) Optional. The cart hash for additional identification.
449 * ]
450 *
451 */
452 public static function delete($id, $params = [])
453 {
454 $cart = static::get();
455
456 if (empty($cart)) {
457 return null;
458 }
459
460 $deleted = $cart->delete();
461
462 if ($deleted) {
463 Cookie::deleteCartHash();
464 }
465
466 return $deleted;
467 }
468
469 public static function getStatus(): array
470 {
471 $cart = static::get(
472 [
473 'create' => false // Do not create a new cart if it doesn't exist
474 ]
475 );
476
477 if (!$cart) {
478 return [];
479 }
480
481 return [
482 'cart_hash' => $cart->cart_hash,
483 'cart_data' => $cart->cart_data,
484 'cart_user' => $cart->user_id,
485 ];
486 }
487
488 public static function isLicensedProduct($productVariation): bool
489 {
490 return Helper::hasLicense(Arr::get($productVariation, 'product'));
491 }
492
493
494 private static function validateShouldAddProduct($productVariation, $existingItemsArray)
495 {
496 if (Arr::get($productVariation, 'product.post_status') !== 'publish') {
497 return new WP_Error(
498 'item_not_available',
499 __('Item is not available.', 'fluent-cart')
500 );
501 }
502
503 $variationIds = (new Collection($existingItemsArray))->pluck('object_id');
504 $paymentType = Arr::get($productVariation, 'other_info.payment_type', false);
505
506 $hasInstantCheckoutParam = !empty(App::request()->get(Helper::INSTANT_CHECKOUT_URL_PARAM));
507
508 //early return as don't allow subscription item to add in cart
509 if ($paymentType !== 'onetime' && !$hasInstantCheckoutParam) {
510 return new WP_Error(
511 'item_not_available',
512 __('Item is not available.', 'fluent-cart')
513 );
514 }
515 $hasSubscription = static::hasSubscriptionProduct($existingItemsArray);
516
517 if (!$variationIds->contains(Arr::get($productVariation, 'id')) || empty($existingItemsArray)) {
518 return new WP_Error(
519 'item_not_available',
520 __('Item is not available.', 'fluent-cart')
521 );
522
523 }
524
525 if ($paymentType === 'onetime' && !$hasSubscription) {
526 return true;
527 }
528
529 if ($paymentType === 'onetime' && $hasSubscription) {
530 return new WP_Error(
531 'subscription_items_can_not_combined',
532 __('Subscription items can\'t be combined with other products in the cart.', 'fluent-cart')
533 );
534 }
535
536 return new WP_Error(
537 'item_not_available',
538 __('Item is not available.', 'fluent-cart')
539 );
540 }
541
542 public static function hasSubscriptionProduct($existingItemsArray = []): bool
543 {
544 $subscriptionProduct = (new Collection($existingItemsArray))->pluck('other_info')->filter(function ($info) {
545 $otherInfo = (array)$info;
546 $type = Arr::get($otherInfo, 'payment_type', false);
547 return $type === 'subscription';
548 });
549 return $subscriptionProduct->count() > 0;
550 }
551
552 private static function removeItemFromCart($existingItemsArray, $index): array
553 {
554 unset($existingItemsArray[$index]);
555 $message = __('Item removed from cart', 'fluent-cart');
556 return [
557 'message' => $message,
558 'cart_data' => $existingItemsArray,
559 ];
560 }
561
562 public static function updateItemQuantityInCart($productVariation, $existingItemsArray, $index, $quantity = 1, $isFilteredItem = false): array
563 {
564 $canBeAdded = true;
565
566
567 if (!$isFilteredItem) {
568 $canBeAdded = static::validateShouldAddProduct($productVariation, $existingItemsArray);
569 }
570
571
572 if (is_wp_error($canBeAdded)) {
573 return [
574 'code' => 'failed',
575 'message' => $canBeAdded->get_error_message()
576 ];
577 }
578
579 $updatedQuantity = $existingItemsArray[$index]['quantity'] + $quantity;
580
581 if ($updatedQuantity < 0) {
582 $updatedQuantity = 0;
583 }
584
585 if (!$isFilteredItem) {
586
587 if (!CartHelper::shouldAddItemToCart($productVariation, $updatedQuantity)) {
588 return [
589 'code' => 'failed',
590 'message' => __("You've reached the maximum quantity for this product.", 'fluent-cart')
591 ];
592 }
593 }
594
595 if ($productVariation instanceof ProductVariation) {
596 $item = CartHelper::generateCartItemFromVariation($productVariation, $updatedQuantity);
597 } else {
598 $item = CartHelper::generateCartItemCustomItem($productVariation, $updatedQuantity);
599 }
600
601
602 $existingItemsArray[$index] = $item;
603 return [
604 'message' => __('Quantity updated!', 'fluent-cart'),
605 'cart_data' => $existingItemsArray,
606 ];
607 }
608
609 public static function addItemInCart($productVariation, $existingItemsArray, $index, $quantity = 1, $isFilteredItem = false): array
610 {
611
612 if ($quantity < 1) {
613 $quantity = 1;
614 }
615 if (!$isFilteredItem) {
616 if (!CartHelper::shouldAddItemToCart($productVariation, $quantity)) {
617 return [
618 'code' => 'failed',
619 'message' => sprintf(
620 /* translators: %s is the product title */
621 __('%s is out of stock', 'fluent-cart'),
622 Arr::get($productVariation, 'variation_title')
623 ),
624 ];
625 }
626
627 $paymentType = $productVariation instanceof ProductVariation
628 ? $productVariation->payment_type
629 : Arr::get($productVariation, 'payment_type');
630
631 if ($paymentType === 'subscription' && $quantity > 1) {
632 return [
633 'code' => 'failed',
634 'message' => __('You cannot purchase more than one subscription at a time.', 'fluent-cart'),
635 ];
636 }
637
638 if (!empty($existingItemsArray)) {
639 $hasSubscription = static::hasSubscriptionProduct($existingItemsArray);
640
641 if ($paymentType === 'subscription' || $hasSubscription) {
642 return [
643 'code' => 'failed',
644 'message' => __("Subscription items can't be combined with other products in the cart.", 'fluent-cart'),
645 ];
646 }
647 }
648 }
649
650 if ($productVariation instanceof ProductVariation) {
651 $item = CartHelper::generateCartItemFromVariation($productVariation, $quantity);
652 } else {
653 $item = CartHelper::generateCartItemCustomItem($productVariation, $quantity);
654 }
655
656
657 $existingItemsArray[] = static::getCartSingleItemPreparedArray(
658 [
659 'variation' => $productVariation,
660 'quantity' => $quantity
661 ]
662 );
663
664
665 return [
666 'message' => __('Item added in cart!', 'fluent-cart'),
667 'cart_data' => $existingItemsArray,
668 ];
669 }
670
671 private static function updateCartItemsQuantity($params = []): array
672 {
673 $itemId = Arr::get($params, 'item_id');
674
675 $incrementBy = Arr::get($params, 'increment_by');
676 $existingItemsArray = Arr::get($params, 'existing_items', []);
677 if (!is_array($existingItemsArray)) {
678 $existingItemsArray = [];
679 }
680
681
682 $index = -1;
683
684 foreach ($existingItemsArray as $itemIndex => $existingItem) {
685 if (Arr::get($existingItem, 'object_id') == $itemId) {
686 $index = $itemIndex;
687 break;
688 }
689 }
690
691
692 /** @var $productVariation ProductVariation */
693 if ($incrementBy == 0) {
694 return static::removeItemFromCart($existingItemsArray, $index);
695 }
696
697 $productVariation = ProductVariation::query()->where('id', $itemId)->with([
698 'product',
699 'product.detail',
700 'product.licensesMeta',
701 'product_detail',
702 'media',
703 'shippingClass'
704 ])->first();
705
706
707 $isFilteredItem = false;
708 if (empty($productVariation)) {
709 $isFilteredItem = true;
710 $productVariation = apply_filters('fluent_cart/cart_item_product_variation', $productVariation, $itemId, $incrementBy, $existingItemsArray);
711 }
712
713
714 if (empty($productVariation)) {
715 return [
716 'code' => 'failed',
717 'message' => __('Item is not available.', 'fluent-cart')
718 ];
719 }
720
721 //($index === 0 || !empty($index)) && isset($existingItemsArray[$index])
722 //inline check will not work
723
724 $isValidIndex = false;
725 if ($index != -1) {
726 $isValidIndex = true;
727 }
728
729 if ($isValidIndex && isset($existingItemsArray[$index])) {
730
731 return static::updateItemQuantityInCart(
732 $productVariation,
733 $existingItemsArray,
734 $index,
735 $incrementBy,
736 $isFilteredItem,
737 );
738 }
739
740 return static::addItemInCart(
741 $productVariation,
742 $existingItemsArray,
743 $index,
744 $incrementBy,
745 $isFilteredItem,
746 );
747 }
748
749
750 private static function getCartSingleItemPreparedArray($params = []): array
751 {
752
753 $variation = Arr::get($params, 'variation');
754 $quantity = Arr::get($params, 'quantity');
755 return CartHelper::generateCartItemFromVariation($variation, $quantity);
756
757 }
758
759 /**
760 * Check if cart exists
761 */
762
763 public static function getOrSetCartForThisDevice($autoCreate = false)
764 {
765
766 $cartHash = Cookie::getCartHash();
767
768 if ($cartHash) {
769 $cart = static::getQuery()
770 ->where('stage', '!=', 'completed')
771 ->where('cart_hash', $cartHash)
772 ->where('cart_group', 'global')
773 ->first();
774
775 if ($cart) {
776 return $cart;
777 }
778 }
779
780 $userId = get_current_user_id();
781 if ($userId) {
782 // Latest cart first — without an order, first() picks by primary key
783 // (cart_hash), which resurrects an arbitrary old cart for the user.
784 $cart = static::getQuery()
785 ->where('user_id', $userId)
786 ->where('stage', '!=', 'completed')
787 ->where('cart_group', 'global')
788 ->orderBy('updated_at', 'DESC')
789 ->first();
790
791 if ($cart) {
792 return $cart;
793 }
794 }
795
796 if (!$autoCreate) {
797 return null;
798 }
799
800 $cart = new Cart();
801 $cart->cart_data = [];
802
803 $cart = CartHelper::addCommonCartData($cart);
804
805 $cart->save();
806
807 Cookie::setCartHash($cart->cart_hash);
808
809 return $cart;
810 }
811
812 /**
813 * This method should be called only if no cart is found in a current device
814 */
815 private static function setupNewCart()
816 {
817 $cartArray['cart_data'] = [];
818 if ($userId = get_current_user_id()) {
819 $cartArray['user_id'] = $userId;
820 }
821 $cartArray['cart_group'] = 'global';
822 return Cart::query()->create($cartArray);
823
824 }
825
826 public static function resetCartData()
827 {
828 $cart = CartResource::get();
829
830 if (is_array($cart->cart_data) && !empty($cart->cart_data)) {
831 $cart->cart_data = [];
832 $cart->save();
833 }
834 }
835 }
836