PluginProbe
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO / 1.4.14
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO v1.4.14
1.4.14 1.4.13 1.4.12 1.4.11 1.4.10 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.54 1.3.53 1.3.52 1.3.51 1.3.50 1.3.49 1.3.48 1.3.47 1.3.46 1.3.45 All 177 releases
disco / app / Calc / CalcPercentPerProduct.php

CalcPercentPerProduct.php in Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO 1.4.14, at app/Calc/CalcPercentPerProduct.php

183 lines 5.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php // phpcs:ignoreFile
2
3 namespace Disco\App\Calc;
4
5 /**
6 * Class CalcPercentPerProduct
7 *
8 * @package Disco
9 * @subpackage Disco\App\Calc
10 * @author Ohidul Islam <wahid0003@gmail.com>
11 * @link https://webappick.com
12 * @license https://opensource.org/licenses/gpl-license.php GNU Public License
13 * @category Plugin
14 */
15 class CalcPercentPerProduct extends CalcAbstract {
16
17 /**
18 * @var array<string, float> $item
19 */
20 private $rule;
21
22 /**
23 * @var array<string, float> $item
24 */
25 private $item;
26
27 /**
28 * @var object $cart Cart.
29 * @phpstan-ignore-next-line
30 */
31 private $cart;
32
33 /**
34 * @var string $discount_intent
35 */
36 private $discount_intent;
37
38 /**
39 * @var mixed $discounted_quantities
40 */
41 private $discounted_quantities;
42
43 /**
44 * CalcPercentPerProduct constructor.
45 *
46 * @param array $rule Campaign Rule.
47 * @param array $item Cart Item.
48 * @param object $cart Cart.
49 * @param object $campaign Campaign.
50 */
51 public function __construct( $rule, $item, $cart, $campaign ) {
52 $this->rule = $rule;
53 $this->item = $item;
54 $this->cart = $cart;
55
56 // @phpstan-ignore-next-line
57 $this->discount_intent = $campaign->get_discount_intent(); // phpcs:ignore
58 }
59
60 /**
61 * Calculate Discount.
62 * This function calculates the discount amount based on the discount type, value and item quantity.
63 *
64 * @return array $discount
65 */
66 public function calculate(): array {
67 $discount = $this->calculate_discount();
68
69 return array(
70 'price' => $this->calculate_price( $discount ),
71 'discount' => $discount,
72 'line_subtotal' => $this->calculate_line_subtotal( $discount ),
73 'discounted_quantities' => $this->discounted_quantities,
74 );
75 }
76
77 /**
78 * Calculate Discount.
79 *
80 * @return float Discount Amount.
81 */
82 public function calculate_discount(): float { //phpcs:ignore
83 $discount_amount = 0;
84 $discount_value = $this->rule['discount_value'];
85 $price = CalcFactory::get_price( $this->item );
86 $quantity = (int) $this->item['quantity'];
87
88 // "Count Quantity As" combined / variations: discount only the eligible units.
89 if ( isset( $this->item['disco_forced_qty'] ) ) {
90 $forced = max( 0, (int) $this->item['disco_forced_qty'] );
91 $product_discount = $price ? $price * $discount_value / 100 : 0;
92 $this->discounted_quantities = $forced;
93
94 return $forced * $product_discount;
95 }
96 $min = $this->rule['min'] ? (int) $this->rule['min'] : 0; //phpcs:ignore
97 $max = ! empty( $this->rule['max'] ) ? (int) $this->rule['max'] : ( $this->discount_intent === 'Bulk' ? PHP_INT_MAX : 0 ); // phpcs:ignore
98 $recursive = ! empty( $this->rule['recursive'] ) && $this->rule['recursive'] === 'yes'; // phpcs:ignore
99
100 // Default discount for quantities.
101 $discount_for_quantities = $min;
102
103 /**
104 * Bulk / range capping — only when NOT recursive. Recursive rules ignore
105 * max: the bundle size is always min, so the qualifying quantity must not
106 * be capped to max here, otherwise floor( qty / base ) would divide by
107 * max instead of min and undercount the bundles.
108 */
109 if ( ! $recursive && $max && $quantity >= $max ) {
110 $discount_for_quantities = $max;
111 }
112
113 // If quantity between min and max then apply discount.
114 if ( ! $recursive && $quantity >= $min && $quantity <= $max ) {
115 $discount_for_quantities = $quantity;
116 }
117
118 // Apply for the Bundle & BOGO Discount when recursive is set.
119 $multiplier = 1;
120
121 if ( $recursive && $min > 0 && $quantity >= $min ) {
122 /**
123 * Recursive: the number of bundles is floor( qty / min ). Divide by
124 * min, never by $discount_for_quantities — for BuyXGetY the latter
125 * holds the reward quantity (get_quantity) and would inflate the
126 * multiplier (e.g. buy 2 get 1 with 2 in cart → 1 bundle, not 2).
127 */
128 $multiplier = (int) floor( $quantity / $min );
129 $discount_for_quantities *= $multiplier;
130 }
131
132 // Discount per product.
133 $product_discount = 0;
134
135 if ( $price ) {
136 $product_discount = $price * $discount_value / 100;
137 }
138
139 // Limit discount to Min or Max quantity.
140 if ( $quantity >= $discount_for_quantities ) {
141 $discount_for_quantities = min( $quantity, $discount_for_quantities );
142
143 // Set the discounted quantity for BOGO.
144 if ( ! empty( $this->rule['get_quantity'] ) ) {
145 $discount_for_quantities = (int) $this->rule['get_quantity'];
146 $discount_for_quantities *= $multiplier;
147 }
148
149 $discount_amount = $discount_for_quantities * $product_discount;
150 }
151
152 $this->discounted_quantities = $discount_for_quantities;
153
154 return $discount_amount;
155 }
156
157 /**
158 * Calculate Price.
159 *
160 * @param float $discount Discount Amount.
161 * @return float Price.
162 */
163 public function calculate_price( $discount ): float {
164 $discounted_subtotal = $this->calculate_line_subtotal( $discount );
165
166 return $discounted_subtotal / $this->item['quantity'];
167 }
168
169 /**
170 * Calculate Line Subtotal.
171 *
172 * @param float $discount discount amount.
173 */
174 public function calculate_line_subtotal( $discount ): float {
175 if ( isset( $this->item['line_subtotal'] ) ) {
176 return $this->item['line_subtotal'] - $discount;
177 }
178
179 return 0.0;
180 }
181
182 }
183