PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.5.1
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.5.1
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 / app / Modules / Shipping / ShippingModule.php

ShippingModule.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.5.1, at app/Modules/Shipping/ShippingModule.php

175 lines 5.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\App\Modules\Shipping;
4
5 use FluentCart\App\App;
6 use FluentCart\App\Helpers\AddressHelper;
7 use FluentCart\App\Helpers\CartHelper;
8 use FluentCart\App\Modules\Shipping\Http\Handlers\ScriptHandler;
9 use FluentCart\App\Modules\Shipping\Services\Filter\ShippingZoneFilter;
10 use FluentCart\App\Vite;
11 use FluentCart\Framework\Support\Arr;
12
13 class ShippingModule
14 {
15 public static function register()
16 {
17 $self = new static();
18 add_action('fluentcart_loaded', [$self, 'init']);
19
20 add_filter('fluent_cart/checkout/before_patch_checkout_data', [$self, 'maybeRecalculateShippingCharges'], 9, 2);
21
22 add_action('fluent_cart/cart/cart_data_items_updated', [$self, 'handleItemsChanges'], 9, 1);
23 }
24
25 public function init($app)
26 {
27 $app->router->group(function ($router) {
28 require_once __DIR__ . '/Http/shipping-api.php';
29 });
30
31 (new ScriptHandler())->register();
32 }
33
34 public function handleItemsChanges($data)
35 {
36 $scope = Arr::get($data, 'scope');
37
38 $ignores = [
39 'apply_coupons',
40 'discounts_recalculated',
41 'remove_coupon',
42 'payment_method_fee_recalculate',
43 ];
44
45 if (in_array($scope, $ignores)) {
46 return;
47 }
48
49 $cart = Arr::get($data, 'cart');
50 if (!$cart->requireShipping()) {
51 return;
52 }
53
54 $fillData = $this->getRecalculatedCartDataArr([
55 'cart_data' => $cart->cart_data,
56 'checkout_data' => $cart->checkout_data
57 ], $cart);
58
59 $cart->fill($fillData);
60 $cart->save();
61 }
62
63 public function maybeRecalculateShippingCharges($fillData, $data)
64 {
65 $cart = $data['cart'];
66 if (!$cart->requireShipping()) {
67 return $fillData;
68 }
69
70 $watchingKeys = [
71 'shipping_country',
72 'shipping_state',
73 'shipping_method_id'
74 ];
75
76 $changes = Arr::get($data, 'changes', []);
77 if (!array_intersect(array_keys($changes), $watchingKeys)) {
78 // No changes detected
79 return $fillData;
80 }
81
82 Arr::set($fillData, 'hook_changes.shipping', true);
83 $fillData = $this->getRecalculatedCartDataArr($fillData, $cart);
84
85 return $fillData;
86 }
87
88 private function getRecalculatedCartDataArr($fillData, $cart)
89 {
90 $shippingCountry = Arr::get($fillData, 'checkout_data.form_data.shipping_country', null);
91 $shippingState = Arr::get($fillData, 'checkout_data.form_data.shipping_state', null);
92
93 $availableShippingMethods = AddressHelper::getShippingMethods($shippingCountry, $shippingState);
94
95 if (!$availableShippingMethods || is_wp_error($availableShippingMethods)) {
96 Arr::set($fillData, 'checkout_data.shipping_data.shipping_charge', 0);
97 Arr::set($fillData, 'checkout_data.shipping_data.shipping_method_id', null);
98
99 $cartData = Arr::get($fillData, 'cart_data', []);
100 foreach ($cartData as &$cartItem) {
101 $cartItem['shipping_charge'] = 0;
102 $cartItem['itemwise_shipping_charge'] = 0;
103 }
104
105 Arr::set($fillData, 'cart_data', $cartData);
106
107 return $fillData;
108 }
109
110 $prevShippingMethodId = Arr::get($fillData, 'checkout_data.shipping_data.shipping_method_id', null);
111
112 $shippingMethod = Arr::first($availableShippingMethods);
113 if ($prevShippingMethodId) {
114 foreach ($availableShippingMethods as $method) {
115 if ($method->id == $prevShippingMethodId) {
116 $shippingMethod = $method;
117 break;
118 }
119 }
120 }
121
122 // Use profile-aware calculation if any cart items have shipping classes
123 $cartData = Arr::get($fillData, 'cart_data', []);
124 $hasShippingClasses = $this->cartHasShippingClasses($cartData);
125
126 if ($hasShippingClasses && $shippingCountry) {
127 $calculations = CartHelper::calculateShippingByProfile(
128 $shippingMethod->id,
129 $cartData,
130 $shippingCountry,
131 $shippingState,
132 'items'
133 );
134 } else {
135 $calculations = CartHelper::calculateShippingMethodCharge($shippingMethod, $cartData, 'items');
136 }
137
138 $newCharge = Arr::get($calculations, 'shipping_amount', 0);
139 $items = Arr::get($calculations, 'items', []);
140
141 Arr::set($fillData, 'cart_data', $items);
142
143 Arr::set($fillData, 'checkout_data.shipping_data.shipping_charge', $newCharge);
144 Arr::set($fillData, 'checkout_data.shipping_data.shipping_method_id', $shippingMethod->id);
145
146 return $fillData;
147 }
148
149 private function cartHasShippingClasses($cartData)
150 {
151 if (empty($cartData)) {
152 return false;
153 }
154
155 $postIds = array_unique(array_column($cartData, 'post_id'));
156 if (empty($postIds)) {
157 return false;
158 }
159
160 $products = \FluentCart\App\Models\Product::query()
161 ->whereIn('ID', $postIds)
162 ->with(['detail'])
163 ->get();
164
165 foreach ($products as $product) {
166 if ($product->detail && !empty($product->detail->other_info['shipping_class'])) {
167 return true;
168 }
169 }
170
171 return false;
172 }
173
174 }
175