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

174 lines 5.2 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 ];
43
44 if (in_array($scope, $ignores)) {
45 return;
46 }
47
48 $cart = Arr::get($data, 'cart');
49 if (!$cart->requireShipping()) {
50 return;
51 }
52
53 $fillData = $this->getRecalculatedCartDataArr([
54 'cart_data' => $cart->cart_data,
55 'checkout_data' => $cart->checkout_data
56 ], $cart);
57
58 $cart->fill($fillData);
59 $cart->save();
60 }
61
62 public function maybeRecalculateShippingCharges($fillData, $data)
63 {
64 $cart = $data['cart'];
65 if (!$cart->requireShipping()) {
66 return $fillData;
67 }
68
69 $watchingKeys = [
70 'shipping_country',
71 'shipping_state',
72 'shipping_method_id'
73 ];
74
75 $changes = Arr::get($data, 'changes', []);
76 if (!array_intersect(array_keys($changes), $watchingKeys)) {
77 // No changes detected
78 return $fillData;
79 }
80
81 Arr::set($fillData, 'hook_changes.shipping', true);
82 $fillData = $this->getRecalculatedCartDataArr($fillData, $cart);
83
84 return $fillData;
85 }
86
87 private function getRecalculatedCartDataArr($fillData, $cart)
88 {
89 $shippingCountry = Arr::get($fillData, 'checkout_data.form_data.shipping_country', null);
90 $shippingState = Arr::get($fillData, 'checkout_data.form_data.shipping_state', null);
91
92 $availableShippingMethods = AddressHelper::getShippingMethods($shippingCountry, $shippingState);
93
94 if (!$availableShippingMethods || is_wp_error($availableShippingMethods)) {
95 Arr::set($fillData, 'checkout_data.shipping_data.shipping_charge', 0);
96 Arr::set($fillData, 'checkout_data.shipping_data.shipping_method_id', null);
97
98 $cartData = Arr::get($fillData, 'cart_data', []);
99 foreach ($cartData as &$cartItem) {
100 $cartItem['shipping_charge'] = 0;
101 $cartItem['itemwise_shipping_charge'] = 0;
102 }
103
104 Arr::set($fillData, 'cart_data', $cartData);
105
106 return $fillData;
107 }
108
109 $prevShippingMethodId = Arr::get($fillData, 'checkout_data.shipping_data.shipping_method_id', null);
110
111 $shippingMethod = Arr::first($availableShippingMethods);
112 if ($prevShippingMethodId) {
113 foreach ($availableShippingMethods as $method) {
114 if ($method->id == $prevShippingMethodId) {
115 $shippingMethod = $method;
116 break;
117 }
118 }
119 }
120
121 // Use profile-aware calculation if any cart items have shipping classes
122 $cartData = Arr::get($fillData, 'cart_data', []);
123 $hasShippingClasses = $this->cartHasShippingClasses($cartData);
124
125 if ($hasShippingClasses && $shippingCountry) {
126 $calculations = CartHelper::calculateShippingByProfile(
127 $shippingMethod->id,
128 $cartData,
129 $shippingCountry,
130 $shippingState,
131 'items'
132 );
133 } else {
134 $calculations = CartHelper::calculateShippingMethodCharge($shippingMethod, $cartData, 'items');
135 }
136
137 $newCharge = Arr::get($calculations, 'shipping_amount', 0);
138 $items = Arr::get($calculations, 'items', []);
139
140 Arr::set($fillData, 'cart_data', $items);
141
142 Arr::set($fillData, 'checkout_data.shipping_data.shipping_charge', $newCharge);
143 Arr::set($fillData, 'checkout_data.shipping_data.shipping_method_id', $shippingMethod->id);
144
145 return $fillData;
146 }
147
148 private function cartHasShippingClasses($cartData)
149 {
150 if (empty($cartData)) {
151 return false;
152 }
153
154 $postIds = array_unique(array_column($cartData, 'post_id'));
155 if (empty($postIds)) {
156 return false;
157 }
158
159 $products = \FluentCart\App\Models\Product::query()
160 ->whereIn('ID', $postIds)
161 ->with(['detail'])
162 ->get();
163
164 foreach ($products as $product) {
165 if ($product->detail && !empty($product->detail->other_info['shipping_class'])) {
166 return true;
167 }
168 }
169
170 return false;
171 }
172
173 }
174