PluginProbe
Packeta / trunk
Packeta vtrunk
2.3.2 2.3.1 trunk 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.3.0 1.3.1 1.3.2 1.4 1.4.1 1.4.2 1.4.3 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 All 56 releases
packeta / src / Packetery / Module / Checkout / RateCalculator.php

RateCalculator.php in Packeta trunk, at src/Packetery/Module/Checkout/RateCalculator.php

247 lines 6.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class RateCalculator.
4 *
5 * @package Packetery
6 */
7
8 declare( strict_types=1 );
9
10 namespace Packetery\Module\Checkout;
11
12 use Packetery\Module\Carrier;
13 use Packetery\Module\DiagnosticsLogger\DiagnosticsLogger;
14 use Packetery\Module\Framework\WcAdapter;
15 use Packetery\Module\Framework\WpAdapter;
16 use WC_Cart;
17 use WC_Order;
18
19 /**
20 * Class RateCalculator. Calculates cost for WooCommerce shipping rate.
21 *
22 * @package Packetery
23 */
24 class RateCalculator {
25
26 /**
27 * @var CurrencySwitcherService
28 */
29 private $currencySwitcherService;
30
31 /**
32 * @var WpAdapter
33 */
34 private $wpAdapter;
35
36 /**
37 * @var WcAdapter
38 */
39 private $wcAdapter;
40
41 /**
42 * @var DiagnosticsLogger
43 */
44 private $diagnosticsLogger;
45
46 public function __construct(
47 WpAdapter $wpAdapter,
48 WcAdapter $wcAdapter,
49 CurrencySwitcherService $currencySwitcherService,
50 DiagnosticsLogger $diagnosticsLogger
51 ) {
52 $this->wpAdapter = $wpAdapter;
53 $this->wcAdapter = $wcAdapter;
54 $this->currencySwitcherService = $currencySwitcherService;
55 $this->diagnosticsLogger = $diagnosticsLogger;
56 }
57
58 /**
59 * Computes custom rate cost for carrier using cart contents.
60 *
61 * @param Carrier\Options $options Carrier options.
62 * @param float $cartPrice Price.
63 * @param float $totalCartProductValue Total cart product value.
64 * @param float|int $cartWeight Weight.
65 *
66 * @return ?float
67 */
68 public function getRateCost( Carrier\Options $options, float $cartPrice, float $totalCartProductValue, $cartWeight ): ?float {
69 return $this->getShippingRateCost(
70 $options,
71 $cartPrice,
72 $totalCartProductValue,
73 $cartWeight,
74 $this->isFreeShippingCouponApplied( $this->wcAdapter->cart() )
75 );
76 }
77
78 /**
79 * Computes custom rate cost for carrier using cart contents.
80 *
81 * @param Carrier\Options $options Carrier options.
82 * @param float $cartPrice Price.
83 * @param float $totalCartProductValue Total cart product value.
84 * @param float|int $cartWeight Weight.
85 * @param bool $isFreeShippingCouponApplied Is free shipping coupon applied?
86 *
87 * @return ?float
88 */
89 public function getShippingRateCost(
90 Carrier\Options $options,
91 float $cartPrice,
92 float $totalCartProductValue,
93 $cartWeight,
94 bool $isFreeShippingCouponApplied
95 ): ?float {
96 $cost = null;
97 $carrierOptions = $options->toArray();
98
99 if ( isset( $carrierOptions[ Carrier\OptionsPage::FORM_FIELD_WEIGHT_LIMITS ] ) && $options->getPricingType() === Carrier\Options::PRICING_TYPE_BY_WEIGHT ) {
100 foreach ( $carrierOptions[ Carrier\OptionsPage::FORM_FIELD_WEIGHT_LIMITS ] as $weightLimit ) {
101 if ( $cartWeight <= $weightLimit['weight'] ) {
102 $cost = $weightLimit['price'];
103
104 break;
105 }
106 }
107 }
108
109 if ( isset( $carrierOptions[ Carrier\OptionsPage::FORM_FIELD_PRODUCT_VALUE_LIMITS ] ) && $options->getPricingType() === Carrier\Options::PRICING_TYPE_BY_PRODUCT_VALUE ) {
110 foreach ( $carrierOptions[ Carrier\OptionsPage::FORM_FIELD_PRODUCT_VALUE_LIMITS ] as $productValueLimit ) {
111 if ( $totalCartProductValue <= $productValueLimit['value'] ) {
112 $cost = $productValueLimit['price'];
113
114 break;
115 }
116 }
117 }
118 $this->diagnosticsLogger->log(
119 'Rate calculator',
120 [
121 'cost' => $cost,
122 'options' => $options,
123 'cartPrice' => $cartPrice,
124 'totalCartProductValue' => $totalCartProductValue,
125 'cartWeight' => $cartWeight,
126 'isFreeShippingCouponApplied' => $isFreeShippingCouponApplied,
127 'carrierOptions' => $carrierOptions,
128 ]
129 );
130 if ( $cost === null ) {
131 return null;
132 }
133
134 $freeShippingLimit = null;
135 if ( $carrierOptions['free_shipping_limit'] ) {
136 $freeShippingLimit = $this->currencySwitcherService->getConvertedPrice( $carrierOptions['free_shipping_limit'] );
137 $this->diagnosticsLogger->log(
138 'Rate calculator - free shipping limit',
139 [
140 'freeShippingLimit' => $freeShippingLimit,
141 ]
142 );
143 if ( $cartPrice >= $freeShippingLimit ) {
144 $cost = 0;
145 }
146 }
147
148 $hasCouponFreeShippingActive = $options->hasCouponFreeShippingActive();
149 $this->diagnosticsLogger->log(
150 'Rate calculator - coupon free shipping',
151 [
152 'hasCouponFreeShippingActive' => $hasCouponFreeShippingActive,
153 ]
154 );
155 if ( $cost !== 0 && $isFreeShippingCouponApplied === true && $hasCouponFreeShippingActive === true ) {
156 $cost = 0;
157 }
158
159 $filterParameters = [
160 'carrier_id' => $carrierOptions['id'],
161 'free_shipping_limit' => $freeShippingLimit,
162 Carrier\OptionsPage::FORM_FIELD_PRICING_TYPE => $options->getPricingType(),
163 Carrier\OptionsPage::FORM_FIELD_WEIGHT_LIMITS => $carrierOptions[ Carrier\OptionsPage::FORM_FIELD_WEIGHT_LIMITS ],
164 Carrier\OptionsPage::FORM_FIELD_PRODUCT_VALUE_LIMITS => $carrierOptions[ Carrier\OptionsPage::FORM_FIELD_PRODUCT_VALUE_LIMITS ] ?? [],
165 ];
166
167 $this->diagnosticsLogger->log(
168 'Rate calculator - cost and filter parameters',
169 [
170 'filterParameters' => $filterParameters,
171 'cost' => $cost,
172 ]
173 );
174
175 /**
176 * Filter shipping rate cost in checkout
177 *
178 * @since 1.4.1
179 */
180 return (float) $this->wpAdapter->applyFilters( 'packeta_shipping_price', (float) $cost, $filterParameters );
181 }
182
183 /**
184 * Gets applicable COD surcharge.
185 *
186 * @param array $carrierOptions Carrier options.
187 * @param float $cartPrice Cart price.
188 *
189 * @return float
190 */
191 public function getCODSurcharge( array $carrierOptions, float $cartPrice ): float {
192 if ( isset( $carrierOptions['surcharge_limits'] ) ) {
193 foreach ( $carrierOptions['surcharge_limits'] as $surchargeLimit ) {
194 if ( $cartPrice <= $surchargeLimit['order_price'] ) {
195 return (float) $surchargeLimit['surcharge'];
196 }
197 }
198 }
199
200 if ( isset( $carrierOptions['default_COD_surcharge'] ) && is_numeric( $carrierOptions['default_COD_surcharge'] ) ) {
201 return (float) $carrierOptions['default_COD_surcharge'];
202 }
203
204 return 0.0;
205 }
206
207 /**
208 * @param string $name
209 * @param string $optionId
210 * @param float $taxExclusiveCost
211 * @param float[]|null $taxes Taxes. It is going to be calculated if null.
212 *
213 * @return array<string, string|float|array>
214 */
215 public function createShippingRate( string $name, string $optionId, float $taxExclusiveCost, ?array $taxes ): array {
216 return [
217 'label' => $name,
218 'id' => $optionId,
219 'cost' => $taxExclusiveCost,
220 'taxes' => $taxes ?? '',
221 'calc_tax' => 'per_order',
222 ];
223 }
224
225 /**
226 * Tells if free shipping coupon is applied.
227 *
228 * @param WC_Cart|WC_Order|null $cartOrOrder Cart or order.
229 *
230 * @return bool
231 */
232 public function isFreeShippingCouponApplied( $cartOrOrder ): bool {
233 if ( $cartOrOrder === null ) {
234 return false;
235 }
236
237 $coupons = $cartOrOrder->get_coupons();
238 foreach ( $coupons as $coupon ) {
239 if ( method_exists( $coupon, 'get_free_shipping' ) && $coupon->get_free_shipping() ) {
240 return true;
241 }
242 }
243
244 return false;
245 }
246 }
247