PluginProbe
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO / 1.1.9
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO v1.1.9
1.4.15 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 All 178 releases
disco / app / Disco.php

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

307 lines 7.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Disco Class File.
4 *
5 * @package Disco
6 * @subpackage \App\Disco.php
7 * @since 1.0.0
8 */
9
10 namespace Disco\App;
11
12 use Disco\App\Features\UserLimit;
13 use Disco\App\Utility\Settings;
14
15 /**
16 * Class Disco
17 *
18 * @package Disco
19 * @subpackage \App
20 * @author Ohidul Islam <wahid0003@gmail.com>
21 * @link https://webappick.com
22 * @license https://opensource.org/licenses/gpl-license.php GNU Public License
23 * @category Discount
24 */
25 class Disco {
26
27 use \Disco\App\Intents\IntentHelper;
28
29 /**
30 * @var array $intents Intents.
31 */
32 private $intents;
33
34 /**
35 * @var int $applied_campaign_id Applied Campaign.
36 */
37 private $applied_campaign_id;
38
39
40 /**
41 * Apply discount to product.
42 *
43 * @param float $price Product Price.
44 * @param \WC_Product $product Product Object.
45 * @return float
46 * @throws \Exception If setting is not found.
47 */
48 public function get_product_discounted_price( $price, $product ) {//phpcs:ignore
49 if ( $product instanceof \WC_Product ) {
50 // Init product base intents and exclude cart-based intents.
51 $this->intents = $this->prepare_intents( array( 'Product' ) );
52
53 // Get a product price type for discount from settings
54 $product_price_type = Settings::get( 'product_price_type' );
55
56 if ( 'regular_price' === $product_price_type ) {
57 if ( $product->get_type() === 'simple' ) {
58 $price = (float) $product->get_regular_price();
59 }
60 }
61
62 // If no intent is available, return the original price.
63 if ( empty( $this->intents ) ) {
64 return $price;
65 }
66
67 $discounts = array();
68
69 $prev_discount = PHP_INT_MAX;
70
71 // Foreach intent, apply the discount.
72 foreach ( $this->intents as $intent ) {
73 /**
74 * Get a discount limit form campaign.
75 *
76 * Compare with total product meta and apply discount
77 */
78 $discount_limit = $intent->campaign->discount_max_user;
79 $total_applied_campaign = ( new UserLimit )->disco_get_total_applied_campaign( $intent->campaign->id );
80
81 if (
82 ! empty( $discount_limit )
83 && (
84 $discount_limit >= 0
85 && $total_applied_campaign >= $discount_limit
86 )
87 ) {
88 continue;
89 }
90
91 $discount = $intent->get_discounts( (float) $price, $product );
92
93 if ( empty( $discount ) ) {
94 continue;
95 }
96
97 // Get applied discount campaign.
98 if ( $discount > 0 && $prev_discount > $discount ) {
99 $this->applied_campaign_id = $intent->campaign->id;
100 $prev_discount = $discount;
101 }
102
103 $discounts[] = $discount;
104 }
105
106 // If no discount is applied, return the original price.
107 if ( empty( $discounts ) ) {
108 return $price;
109 }
110
111 // Get the min or max discount amount according to plugin settings.
112 $new_price = $this->min_max_average( $discounts );
113
114 if ( $new_price < $price ) {
115 // Get an applied campaign from DiscountLimit class.
116 ( new UserLimit )->disco_start_session_on_checkout( $this->applied_campaign_id );
117
118 // Update the products on sale status.
119 apply_filters( 'woocommerce_product_is_on_sale', true, $product );
120
121 return $new_price;
122 }
123 }
124
125 return $price;
126 }
127
128 /** Get Cart Discount.
129 *
130 * @param \WC_Cart $cart Cart Object.
131 * @return \WC_Cart
132 * @throws \Exception If the cart is empty.
133 */
134 public function get_cart_discount( $cart ) { //phpcs:ignore
135 if ( $cart->is_empty() ) {
136 return $cart;
137 }
138
139 // Init Cart - Based Intents except Product & Shipping Intent.
140 $this->intents = $this->prepare_intents( array( 'Cart' ) );
141
142 if ( ! empty( $this->intents ) && $cart->get_cart_contents_count() > 0 ) {
143 $discounts = array();
144
145 foreach ( $this->intents as $intent ) { // Foreach intent, apply the discount.
146 $items = $this->get_items_for_discount( $cart, $intent->campaign );
147
148 $discount = $intent->get_discounts( $items, $cart );
149
150 if ( empty( $discount ) ) {
151 continue;
152 }
153
154 $discounts[] = $discount;
155 }
156
157 // Apply discount to cart subtotal .
158 if ( ! empty( $discounts ) ) {
159 // Get the min or max discount amount according to plugin settings.
160 $cart_fee = $this->min_max_average( $discounts );
161 // TODO: The Discount must be less than cart subtotal.
162 $cart->add_fee( __( 'Discount', 'disco' ), -$cart_fee );
163 }
164 }
165
166 return $cart;
167 }
168
169 /**
170 * Apply Bulk & Bundle discount to cart items.
171 *
172 * @return \WC_Cart|void
173 * @throws \Exception If translation not found.
174 */
175 public function get_cart_items_discount() {//phpcs:ignore
176 if ( ! $this->cart_is_valid() ) {
177 return;
178 }
179
180 // Init Cart - Based Intents except Product & Shipping Intent.
181 $this->intents = $this->prepare_intents( array( 'Bulk', 'Bundle', 'BOGO' ) );
182
183
184 $cart = WC()->cart;
185 $discounts = $this->prepare_item_discounts( $this->intents );
186
187 // return $discounts;
188 if ( empty( $discounts ) ) {
189 return $cart;
190 }
191
192 $items = $cart->get_cart();
193
194 $total_discount = 0;
195
196 foreach ( $items as $item ) {
197 // Get item id.
198 $id = $this->get_cart_item_id( $item );
199
200 if ( empty( $discounts[ $id ] ) ) {
201 continue;
202 }
203
204 $item_object = $item['data'];
205 $quantity = (int) $item['quantity'];
206 $price_key = $discounts[ $id ]['key'];
207 $regular_price = $discounts[ $id ]['original_price'];
208 $discounted_price = $discounts[ $id ]['final_price'];
209 $discounted_amount = $discounts[ $id ]['discounts'][ $price_key ];
210 $discount_types = $discounts[ $id ]['discount_types'][ $price_key ];
211
212 // If the discounted price is greater than or equal to the regular price, then skip.
213 if ( $discounted_price >= $regular_price ) {
214 continue;
215 }
216
217 // Update the item meta data.
218 $item_object->update_meta_data( '_item_offers', $discounts[ $id ] );
219 $item_object->update_meta_data( '_item_savings', $discounted_amount );
220
221 // If the discounted price is less than or equal to 0, then set the regular price.
222 if ( $discounted_price <= 0 ) {
223 $discounted_price = $regular_price;
224 }
225
226 // Set the new item price.
227 if ( 'fixed_per_product' === $discount_types ) {
228 $item_object->set_price( $discounted_price );
229 } elseif ( 'fixed' === $discount_types ) {
230 $total_discount += $discounted_amount;
231 } else {
232 $total_discount += $discounted_amount * $quantity;
233 }
234 }
235
236 // Add the discount to the cart total.
237 if ( $total_discount > 0 ) {
238 $cart->add_fee( __( 'Discount', 'disco' ), -$total_discount );
239 }
240
241 // Set the cart session.
242 $cart->set_session();
243
244 return $cart;
245 }
246
247 /**
248 * Apply the discount to shipping.
249 *
250 * @return bool
251 */
252 public function apply_free_shipping() {
253 if ( ! $this->cart_is_valid() ) {
254 return false;
255 }
256
257 $cart = WC()->cart;
258 $this->intents = $this->prepare_intents( array( 'Shipping' ) );
259 $shippings = array();
260
261 if ( ! empty( $this->intents ) ) {
262 foreach ( $this->intents as $intent ) {
263 $items = $this->get_items_for_discount( $cart, $intent->campaign );
264 $shippings[] = $intent->get_discounts( $items, $cart );
265 }
266 }
267
268 return in_array( 'free_shipping', $shippings, true );
269 }
270
271 /**
272 * Get offers for a product.
273 *
274 * @param array|null $items item ids.
275 * @return string
276 */
277 public function get_offers( $items = null ) {
278 // Init Cart-Based Intents except Product & Shipping Intent.
279 $this->intents = $this->prepare_intents( array( 'Product', 'Shipping' ) );
280 $table = "<table style='border-collapse: collapse;' class=''>";
281 $table .= '<tr><th>Quantity</th><th>Discount</th></tr>';
282
283 $cart = WC()->cart;
284
285 foreach ( $this->intents as $intent ) {
286 if ( is_null( $items ) || ! $cart->is_empty() ) {
287 $items = $this->get_items_for_discount( $cart, $intent->campaign );
288 } else {
289 $items = array();
290 }
291
292 $discounts = $intent->get_offers( $items, $cart );
293
294 if ( empty( $discounts ) ) {
295 continue;
296 }
297
298 foreach ( $discounts as $discount ) {
299 $table .= '<tr style="font-size: smaller;line-height:15px"><td>' . $discount['condition'] . '</td><td>' . $discount['discount'] . '</td></tr>';
300 }
301 }
302
303 return $table . '</table>';
304 }
305
306 }
307