PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / 3.12.2
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell v3.12.2
3.13.3 3.13.2 3.13.1 3.13.0 3.12.13 3.12.12 3.12.11 3.12.10 3.12.9 3.12.8 3.12.7 3.12.6 3.12.5 3.12.4 3.12.3 3.12.1 3.12.2 3.12.0 3.11.1 3.11.0 3.10.9 3.10.8 3.10.7 3.10.6 2.8.16 All 261 releases
wpfunnels / public / modules / type / class-wpfnl-public-wc.php

class-wpfnl-public-wc.php in WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell 3.12.2, at public/modules/type/class-wpfnl-public-wc.php

682 lines 28.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Woocommerce dependent public class
4 *
5 * @package WPFunnels\FunnelType
6 */
7 namespace WPFunnels\FunnelType;
8
9 use WPFunnels\Wpfnl_functions;
10 use WPFunnels\FunnelType\Wpfnl_Public_Funnel_Type;
11 use WPFunnels\lms\helper\Wpfnl_lms_learndash_functions;
12 use WPFunnels\Meta\Wpfnl_Default_Meta;
13 use WPFunnels\Discount\WpfnlDiscount;
14
15 class Wpfnl_Public_Wc extends Wpfnl_Public_Funnel_Type
16 {
17
18 /**
19 * When order bump accept/reject for woocommerce
20 *
21 * @return Array
22 */
23 public function wpfnl_order_bump_trigger( $step_id, $product_id, $quantity, $key, $user_id, $funnel_id , $checker ){
24
25 //=== Custom price configured when you add sale price or apply coupon or add discount value ===//
26 $ob_settings = get_post_meta($step_id, 'order-bump-settings', true);
27 $ob_settings = apply_filters( 'wpfunnels/order_bump_settings_on_frontend', $ob_settings, $funnel_id, $step_id );
28 $replaceable_ob = $this->get_replaceable_ob_products( $ob_settings );
29 $order_bump_settings = $ob_settings[$key];
30 $_product = wc_get_product($product_id);
31
32 $data = array();
33 if( $_product ){
34 $discount_type = $order_bump_settings['discountOption'];
35 $discount_apply_to = $_product->is_on_sale() ? 'sale' : 'regular' ;
36 $product_price = $this->get_product_price( $_product, $discount_apply_to );
37 $original_price = $product_price; // Store original price before discount
38
39 if( 'discount-percentage' === $discount_type || 'discount-price' === $discount_type ) {
40 $discount_apply_to = isset($order_bump_settings['discountapply']) ? $order_bump_settings['discountapply'] : 'regular';
41 $discount_value = isset($order_bump_settings['discountValue']) ? $order_bump_settings['discountValue'] : 0;
42 $product_price = $this->get_product_price( $_product, $discount_apply_to );
43 $original_price = $product_price; // Store price before applying order bump discount
44 if( 'discount-price' === $discount_type && 1 < $quantity ){
45 $discount_value = $this->get_percentage( $product_price, $discount_value, $quantity );
46 $discount_type = 'discount-percentage';
47 }
48
49 $product_price = $this->calculate_custom_price( $discount_type, $discount_value, $product_price );
50 // Now $original_price has the price before order bump discount, and $product_price has the discounted price
51 }
52
53 // Get custom product title from order bump settings
54 // For auto-match mode, use actual product name instead of placeholder
55 $is_auto_match = isset($order_bump_settings['offerSelectionMode']) && $order_bump_settings['offerSelectionMode'] === 'auto-match';
56 if( $is_auto_match ) {
57 $custom_product_title = $_product->get_name();
58 } else {
59 $custom_product_title = isset($order_bump_settings['productName']) ? $order_bump_settings['productName'] : '';
60 }
61
62 // Clean and store prices for cart and display
63 $discounted_price = preg_replace('/[^\d.]/', '', $product_price );
64 $original_price_clean = preg_replace('/[^\d.]/', '', $original_price );
65
66 $ob_cart_item_data = [
67 'custom_price' => $discounted_price,
68 'wpfnl_order_bump' => true,
69 'wpfnl_ob_title' => $custom_product_title,
70 'wpfnl_ob_quantity' => $quantity,
71 'wpfnl_ob_original_price' => $original_price_clean, // Store original price for display
72 ];
73
74
75 /**
76 * Apply filters to modify the orderbump product price data.
77 *
78 * @param float $custom_price The custom price of the product.
79 * @return float The modified custom price.
80 *
81 * @since 3.1.2
82 */
83 $ob_cart_item_data['custom_price'] = apply_filters( 'wpfunnels/modify_orderbump_product_price_data', $ob_cart_item_data['custom_price'] );
84
85 $should_replace_first_product = isset($order_bump_settings['isReplace']) ? $order_bump_settings['isReplace'] : 'no';
86 $replace_settings = isset($order_bump_settings['replaceSettings']) ? $order_bump_settings['replaceSettings'] : [
87 'isAllReplace' => 'yes',
88 'selectedProducts' => [],
89 ];
90 add_filter( 'woocommerce_checkout_cart_item_quantity', array($this, 'wpfnl_checkout_cart_item_quantity'), 10, 3 );
91 if ($checker == "true") {
92 $data = $this->wpfnl_order_bump_accept( $step_id, $product_id, $quantity, $key, $user_id, $funnel_id, $replaceable_ob, $ob_cart_item_data, $should_replace_first_product, $replace_settings, $order_bump_settings );
93 }else{
94 $data = $this->wpfnl_order_bump_reject( $step_id, $product_id, $quantity, $key, $user_id, $funnel_id, $replaceable_ob, $ob_cart_item_data, $should_replace_first_product, $replace_settings );
95 }
96 }
97
98 return $data;
99 }
100
101
102 /**
103 * Get percentage of product price that should be replaced by product price when discount type is discount-price option.
104 *
105 * @param float $product_price The price of the product.
106 * @param float $discount_value The discount value.
107 * @param int $quantity The quantity of the product.
108 *
109 * @return float The percentage of product price that should be replaced.
110 *
111 * @since 3.4.15
112 */
113 public function get_percentage( $product_price, $discount_value, $quantity ) {
114 $percentage = 0;
115 $product_price = floatval( $product_price );
116 $quantity = intval( $quantity );
117 $discount_value = floatval( $discount_value );
118
119 if( $discount_value > 0 && ( $product_price * $quantity ) > 0 ){
120 $percentage = ( $discount_value * 100 ) / ( $product_price * $quantity );
121 }
122 return $percentage;
123 }
124
125
126 /**
127 * When order bump accept for woocommerce
128 *
129 * @param $step_id, $product_id, $quantity, $key, $user_id, $funnel_id, $replaceable_ob, $ob_cart_item_data, $should_replace_first_product, $replace_settings, $order_bump_settings
130 *
131 * @return Array
132 */
133 private function wpfnl_order_bump_accept( $step_id, $product_id, $quantity, $key, $user_id, $funnel_id, $replaceable_ob, $ob_cart_item_data, $should_replace_first_product, $replace_settings, $order_bump_settings = array() ){
134
135 if( Wpfnl_functions::is_wc_active() ){
136 $cookie_name = 'wpfnl_order_bump';
137 $cookie = isset( $_COOKIE[$cookie_name] ) ? json_decode( wp_unslash( $_COOKIE[$cookie_name] ), true ) : array();
138
139 $cookie['order_bump_accepted'] = 'yes';
140
141 // Check if 'order_bump_product' exists and is an array, if not initialize it as an array
142 if (!isset($cookie['order_bump_product']) || !is_array($cookie['order_bump_product'])) {
143 $cookie['order_bump_product'] = array();
144 }
145
146 // Append the product_id to the 'order_bump_product' array if it doesn't already exist
147 if (!in_array($product_id, $cookie['order_bump_product'])) {
148 $cookie['order_bump_product'][] = $product_id;
149 }
150
151 ob_start();
152 setcookie( $cookie_name, wp_json_encode( $cookie ), time() + 3600 * 6, '/', COOKIE_DOMAIN );
153 ob_end_flush();
154
155 WC()->session->set('order_bump_accepted', 'yes');
156 // if order bump is checked we will empty the cart in the first place. The we have to check if isReplace is yes or no.
157 // if replace first product is enabled, then we will only add the order bump product
158 // else we will add all the checkout product along with the order bump product
159 if ( $should_replace_first_product == 'yes' ) {
160
161 $checkout_products = get_post_meta( $step_id, '_wpfnl_checkout_products', true);
162 $is_gbf = get_post_meta( $funnel_id, 'is_global_funnel', true);
163
164 if(( isset($replace_settings['isAllReplace']) && 'yes' === $replace_settings['isAllReplace'] ) || 'yes' === $is_gbf ){
165 if( 'yes' === $is_gbf ){
166 if(isset( $_COOKIE['wpfunnels_global_funnel_specific_product'] ) ){
167 $checkout_products = json_decode( wp_unslash( $_COOKIE['wpfunnels_global_funnel_specific_product'] ), true );
168 }
169 }
170
171 // When isAllReplace is 'yes', replace ALL products (main products + other order bumps)
172 // Empty the cart completely
173 \WC()->cart->empty_cart();
174
175 // Add only the new order bump product
176 // Check if product_id is actually a variation ID
177 $_temp_product = wc_get_product($product_id);
178 if( $_temp_product && $_temp_product->is_type('variation') ) {
179 // It's a variation - get parent ID
180 $parent_id = $_temp_product->get_parent_id();
181 $variation_id = $product_id;
182 $variation_data = $_temp_product->get_variation_attributes();
183 \WC()->cart->add_to_cart($parent_id, $quantity, $variation_id, $variation_data, $ob_cart_item_data);
184 } else {
185 // Simple product
186 \WC()->cart->add_to_cart($product_id, $quantity, 0, [], $ob_cart_item_data);
187 }
188 }else{
189 if( isset($replace_settings['selectedProducts']) ){
190 foreach ( \WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
191 // Skip if this cart item is an order bump - we only want to replace main products
192 if ( isset($cart_item['wpfnl_order_bump']) && $cart_item['wpfnl_order_bump'] ) {
193 continue;
194 }
195
196 $car_product_id = isset($cart_item['variation_id']) && $cart_item['variation_id'] ? $cart_item['variation_id'] : $cart_item['product_id'];
197 $key = array_search( $car_product_id, array_column($replace_settings['selectedProducts'], 'id'));
198 if( $key !== false ){
199 \WC()->cart->remove_cart_item($cart_item_key);
200
201 // Check if product_id is actually a variation ID
202 $_temp_product = wc_get_product($product_id);
203 if( $_temp_product && $_temp_product->is_type('variation') ) {
204 // It's a variation - get parent ID
205 $parent_id = $_temp_product->get_parent_id();
206 $variation_id = $product_id;
207 $variation_data = $_temp_product->get_variation_attributes();
208 \WC()->cart->add_to_cart($parent_id, $quantity, $variation_id, $variation_data, $ob_cart_item_data);
209 } else {
210 // Simple product
211 \WC()->cart->add_to_cart( $product_id, $quantity, 0, [], $ob_cart_item_data);
212 }
213 break;
214 }
215 }
216 }
217 }
218 } else {
219 // Check if product_id is actually a variation ID
220 $_temp_product = wc_get_product($product_id);
221 if( $_temp_product && $_temp_product->is_type('variation') ) {
222 // It's a variation - get parent ID
223 $parent_id = $_temp_product->get_parent_id();
224 $variation_id = $product_id;
225 $variation_data = $_temp_product->get_variation_attributes();
226 \WC()->cart->add_to_cart($parent_id, $quantity, $variation_id, $variation_data, $ob_cart_item_data);
227 } else {
228 // Simple product
229 \WC()->cart->add_to_cart( $product_id, $quantity, 0, [], $ob_cart_item_data);
230 }
231 }
232
233 // Generate Product Object and Name.
234 $product = wc_get_product( $product_id );
235 // Use custom title if available, otherwise use product name
236 $product_name = !empty($ob_cart_item_data['wpfnl_ob_title']) ? $ob_cart_item_data['wpfnl_ob_title'] : ($product ? $product->get_name() : '');
237
238 // Calculate display price considering quantity and discount
239 $unit_price = floatval($ob_cart_item_data['custom_price']);
240 $original_unit_price = floatval($ob_cart_item_data['wpfnl_ob_original_price']);
241 $quantity_int = intval($quantity);
242
243 $total_price = $unit_price * $quantity_int;
244 $original_total_price = $original_unit_price * $quantity_int;
245
246 // Format price display (show as sale price if there's a discount)
247 // Round to 2 decimal places for accurate comparison
248 $total_price = round($total_price, 2);
249 $original_total_price = round($original_total_price, 2);
250
251 if ($original_total_price > $total_price) {
252 $formatted_price = wc_format_sale_price($original_total_price, $total_price);
253 } else {
254 $formatted_price = wc_price($total_price);
255 }
256
257 // Get custom description from order bump settings, fallback to WooCommerce product description
258 // For auto-match mode, always use actual product description
259 $product_description = '';
260 $is_auto_match = isset($order_bump_settings['offerSelectionMode']) && $order_bump_settings['offerSelectionMode'] === 'auto-match';
261
262 if( $is_auto_match && $product ) {
263 // For auto-match, use actual product description
264 $product_description = $product->get_description() ?: $product->get_short_description();
265 } else {
266 // For manual mode, use custom description from settings (keep empty if not set)
267 $product_description = isset($order_bump_settings['productDescriptionText']) ? $order_bump_settings['productDescriptionText'] : '';
268 }
269
270 $data = [
271 'status' => 'success',
272 'message' => __('Successfully added', 'wpfnl'),
273 'order_bump' => true,
274 'product_name' => $product_name,
275 'product_description' => $product_description,
276 'product_price' => $formatted_price,
277 'product_image' => $product ? wp_get_attachment_url( $product->get_image_id() ) : '',
278 'isAllReplace' => ($should_replace_first_product == 'yes' && isset($replace_settings['isAllReplace']) && 'yes' === $replace_settings['isAllReplace']) ? true : false,
279 ];
280 do_action( 'wpfunnels/order_bump_accepted', $step_id, $product_id );
281
282 return $data;
283 }
284 return [];
285 }
286
287
288 /**
289 * When order bump reject for woocommerce
290 *
291 * @param $step_id, $product_id, $quantity, $key, $user_id, $funnel_id, $replaceable_ob, $ob_cart_item_data, $should_replace_first_product
292 *
293 * @return Array
294 */
295 private function wpfnl_order_bump_reject( $step_id, $product_id, $quantity, $key, $user_id, $funnel_id, $replaceable_ob, $ob_cart_item_data, $should_replace_first_product, $replace_settings ){
296
297 if( Wpfnl_functions::is_wc_active() ){
298
299 // fetch main products
300 $checkout_meta = new Wpfnl_Default_Meta();
301 $main_products = $checkout_meta->get_main_products( $funnel_id, $step_id );
302
303 $cookie_name = 'wpfnl_order_bump';
304 $cookie = isset( $_COOKIE[$cookie_name] ) ? json_decode( wp_unslash( $_COOKIE[$cookie_name] ), true ) : array();
305
306 $cookie['order_bump_accepted'] = 'no';
307 if( !isset($cookie['order_bump_accepted']) ){
308 $cookie['order_bump_accepted'] = 'no';
309 }
310
311 // Check if 'order_bump_product' exists and is an array
312 if (isset($cookie['order_bump_product']) && is_array($cookie['order_bump_product'])) {
313 // Find the index of the product_id in the array
314 $index = array_search($product_id, $cookie['order_bump_product']);
315 if ($index !== false) {
316 // Remove the product_id from the array
317 unset($cookie['order_bump_product'][$index]);
318 // Re-index the array to remove gaps
319 $cookie['order_bump_product'] = array_values($cookie['order_bump_product']);
320 }
321 }
322
323 ob_start();
324 setcookie( $cookie_name, wp_json_encode( $cookie ), time() + 3600 * 6, '/', COOKIE_DOMAIN );
325 ob_end_flush();
326
327 WC()->session->set('order_bump_accepted', 'no');
328
329 foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
330 if ( isset($cart_item['wpfnl_order_bump']) && $cart_item['wpfnl_order_bump'] && $cart_item['product_id'] == $product_id) {
331 //remove single product
332 // if( $cart_item['quantity'] == $quantity ){
333 WC()->cart->remove_cart_item($cart_item_key);
334 // }
335 }
336 else if ( isset($cart_item['wpfnl_order_bump']) && $cart_item['wpfnl_order_bump'] && $cart_item['variation_id'] == $product_id ) {
337 // if( $cart_item['quantity'] == $quantity ){
338
339 WC()->cart->remove_cart_item($cart_item_key);
340
341 // }
342 }
343 }
344 if ( $should_replace_first_product == 'yes' ) {
345 // Store existing order bumps before clearing (except the one being removed)
346 $existing_order_bumps = array();
347 foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
348 if ( isset($cart_item['wpfnl_order_bump']) && $cart_item['wpfnl_order_bump'] ) {
349 // Check if this is the order bump being removed
350 $cart_product_id = isset($cart_item['variation_id']) && $cart_item['variation_id'] ? $cart_item['variation_id'] : $cart_item['product_id'];
351 if( $cart_product_id != $product_id ) {
352 // This is a different order bump - keep it
353 $existing_order_bumps[$cart_item_key] = $cart_item;
354 }
355 }
356 }
357
358 \WC()->cart->empty_cart();
359 $is_gbf = get_post_meta( $funnel_id, 'is_global_funnel', true);
360 if( 'yes' === $is_gbf ){
361 if(isset( $_COOKIE['wpfunnels_global_funnel_product'] ) ){
362 $main_products = json_decode( wp_unslash( $_COOKIE['wpfunnels_global_funnel_product'] ), true );
363 $main_products = json_decode( $main_products );
364 }
365 }
366 $discount_instance = new WpfnlDiscount();
367 $discount = $discount_instance->get_discount_settings( $step_id );
368
369 foreach ( $main_products as $main_product ) {
370 $custom_price = [];
371 $product_id = isset($main_product['variation_id']) ? $main_product['variation_id'] : $main_product['id'];
372 $product = wc_get_product($product_id);
373 if( isset($discount['discountOptions'], $discount['discountapplyto']) ){
374 if( !$discount_instance->maybe_time_bound_discount( $step_id ) || ($discount_instance->maybe_time_bound_discount( $step_id ) && $discount_instance->maybe_validate_discount_time( $step_id )) ){
375 if( 'original' !== $discount['discountOptions'] ){
376 $regular_price = $product->get_regular_price();
377 $sale_price = $product->get_sale_price();
378 if( 'sale' === $discount['discountapplyto'] ){
379 $custom_price = [
380 'custom_price' => $sale_price ? $sale_price : $regular_price,
381 ];
382 }else{
383 $custom_price = [
384 'custom_price' => $regular_price ? $regular_price : $product->get_the_price(),
385 ];
386 }
387 }
388 }
389 }
390
391 if( 'variable' === $product->get_type() ){
392 $variations = $product->get_available_variations();
393 $quantity = $main_product['quantity'];
394 $this->add_default_variation($funnel_id, $step_id, $product_id, $product, $variations, $quantity);
395 }else{
396 if( 'variation' === $product->get_type() ){
397 WC()->cart->add_to_cart( $main_product['id'], $main_product['quantity'], isset($main_product['variation_id']) ? $main_product['variation_id'] : '' , isset($main_product['variations']) ?$main_product['variations'] : [], $custom_price);
398 }else{
399 WC()->cart->add_to_cart( $main_product['id'], $main_product['quantity'],0, [], $custom_price);
400 }
401 }
402 }
403
404 // Re-add existing order bumps that were preserved
405 foreach ( $existing_order_bumps as $cart_item ) {
406 $variation_id = isset($cart_item['variation_id']) ? $cart_item['variation_id'] : 0;
407 $variation = isset($cart_item['variation']) ? $cart_item['variation'] : array();
408 \WC()->cart->add_to_cart( $cart_item['product_id'], $cart_item['quantity'], $variation_id, $variation, $cart_item );
409 }
410 }
411 $data = [
412 'status' => 'success',
413 'message' => __('Successfully removed', 'wpfnl'),
414 ];
415 do_action( 'wpfunnels/order_bump_rejected', $step_id, $product_id );
416
417 return $data;
418 }
419 return [];
420 }
421
422
423 /**
424 * Add default variation to cart
425 *
426 * @param $product
427 * @param $variations
428 * @param $quantity
429 *
430 * @throws \Exception
431 */
432 private function add_default_variation($funnel_id, $checkout_id,$product_id,$product,$variations,$quantity){
433 $i = 0;
434 $formatted_variation = [];
435 $is_default_variation = false;
436 foreach ($variations as $variation) {
437
438 if($variation['is_in_stock'] ){
439
440 if($product->get_default_attributes()){
441 $attributes = $product->get_attributes();
442 $def_attributes = $product->get_default_attributes();
443 foreach($attributes as $attribute_key=>$attribute_value){
444
445 $def_attr = $product->get_default_attributes();
446 if(isset($def_attr[$attribute_key])){
447 $attribute_name = str_replace( 'attribute_', '', $attribute_key );
448 $default_value = $product->get_variation_default_attribute($attribute_name);
449 $formatted_variation['attribute_'.$attribute_name] = $default_value;
450 $is_default_variation = true;
451 // $default_attr[] = $default_value;
452
453 }
454 else{
455 $is_default_variation = true;
456 $attribute_name = str_replace( 'attribute_', '', $attribute_key );
457 $attr_value = $product->get_attribute( $attribute_name );
458 $attr_value = strtolower($attr_value);
459 if (strpos($attr_value, '|')) {
460 $attr_array = explode("|",$attr_value);
461 }else{
462 $attr_array = explode(",",$attr_value);
463 }
464 $formatted_variation['attribute_'.$attribute_name] = $attr_array[0];
465 // $default_attr[] = $attr_array[0];
466 }
467
468 }
469 }else{
470 if($i==0){
471 $attributes = $product->get_attributes();
472 foreach ( $attributes as $key => $value) {
473 $attr_value = $product->get_attribute( $key );
474 $attr_value = strtolower($attr_value);
475 if (strpos($attr_value, '|')) {
476 $attr_array = explode("|",$attr_value);
477 }else{
478 $attr_array = explode(",",$attr_value);
479 }
480 $is_custom_default_variation = true;
481 $formatted_variation['attribute_'.$key] = $attr_array[0];
482 }
483 }
484
485
486 // WC()->cart->add_to_cart($variation['variation_id'], $quantity);
487 }
488
489 if( $is_default_variation || $is_custom_default_variation){
490 $variation_id = (new \WC_Product_Data_Store_CPT())->find_matching_product_variation(
491 new \WC_Product($product_id),
492 $formatted_variation
493 );
494 if( !$variation_id ){
495 $_product = wc_get_product($product_id);
496 if( $_product ){
497 $variations = $_product->get_available_variations();
498 $variations_id = wp_list_pluck( $variations, 'variation_id' );
499 $variation_id = $variations_id[0];
500 $formatted_variation = wc_get_product_variation_attributes($variation_id);
501 }
502 }
503
504 $price_type = $this->get_product_price_type( $funnel_id, $checkout_id );
505
506 if( $price_type == 'original' || $price_type == 'sale' ){
507 $cart_item_data = [
508 'custom_price' => get_post_meta($variation_id, '_price', true) ? get_post_meta($variation_id, '_price', true) : get_post_meta($variation_id, '_regular_price', true)
509 ];
510 }else{
511 $cart_item_data = [
512 'custom_price' => get_post_meta($variation_id, '_regular_price', true) ? get_post_meta($variation_id, '_regular_price', true) : get_post_meta($variation_id, '_price', true)
513 ];
514 }
515
516 $added = WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $formatted_variation, $cart_item_data);
517
518 break; // Stop the main loop
519 }
520 $i++;
521 }
522 }
523 }
524
525
526 /**
527 * Get price type
528 */
529 public function get_product_price_type( $funnel_id, $step_id ){
530
531 $is_gbf = get_post_meta( $funnel_id, 'is_global_funnel', true );
532 if( $is_gbf == 'no' || !$is_gbf ){
533
534 $discount_instance = new WpfnlDiscount();
535 $discount = $discount_instance->get_discount_settings( $step_id );
536
537 if( is_array($discount) ){
538 if( $discount['discountOptions'] !== 'original' ){
539 if( $discount['discountapplyto'] == '' || $discount['discountapplyto'] == 'regular' ){
540 return 'regular';
541 }else{
542 return 'sale';
543 }
544 }
545 }
546 }
547 return 'original';
548 }
549
550
551 /**
552 * Get replaceable orderbump products
553 */
554 private function get_replaceable_ob_products( $ob_settings ){
555
556
557 $replaceable_ob = [];
558 foreach( $ob_settings as $key=>$settings ){
559 if( $settings['isReplace'] === 'yes' ){
560 $replaceable_ob[] = [
561 'id' => $settings['product'],
562 'quantity' => $settings['quantity'],
563 ];
564 }
565 }
566
567 return $replaceable_ob;
568
569 }
570
571
572 /**
573 * Get calculable price
574 *
575 * @param \WC_Product $product
576 * @param $discount_apply
577 *
578 * @return string
579 *
580 * @since 2.0.5
581 */
582 private function get_product_price( \WC_Product $product, $discount_apply = 'regular' ) {
583 $price = $product->get_regular_price();
584 if ($product->get_type() == 'variable' || $product->get_type() == 'variable-subscription') {
585 $price = $product->get_variation_regular_price('min') ? $product->get_variation_regular_price('min') : $product->get_price();
586 } else {
587 $price = $product->get_regular_price() ? $product->get_regular_price() : $product->get_price();
588 }
589
590 $final_price = $discount_apply === 'sale' && $product->get_sale_price() ? $product->get_sale_price() : $price;
591
592 return apply_filters('wpfunnels/modify_order_bump_price_on_main_order', $final_price);
593 }
594
595
596 /**
597 * Calculate Discount.
598 *
599 * @since 1.1.5
600 */
601 private function calculate_custom_price($discount_type, $discount_value, $product_price)
602 {
603 $custom_price = $product_price;
604
605 if (!empty($discount_type)) {
606 if ('discount-percentage' === $discount_type) {
607 if ( $discount_value > 0 && $discount_value <= 100) {
608 $custom_price = $product_price - (($product_price * $discount_value) / 100);
609 }else{
610 $custom_price = $product_price;
611 }
612 } elseif ('discount-price' === $discount_type) {
613 if ($discount_value > 0 && $product_price >= $discount_value ) {
614 $custom_price = $product_price - $discount_value;
615 }else{
616 $custom_price = $product_price;
617 }
618 }
619 }
620
621 return number_format($custom_price, 2);
622 }
623
624
625
626 /**
627 * Update quantity from checkout page
628 *
629 * @param $quantity, $cart_item, $cart_item_key
630 */
631 public function wpfnl_checkout_cart_item_quantity( $quantity, $cart_item, $cart_item_key ) {
632
633 $step_id = 0;
634 $isQuantity = 'no';
635
636 if( wp_doing_ajax() ) {
637 $step_id = isset($_POST['step_id']) ? $_POST['step_id'] : 0;
638 } else {
639 $step_id = get_the_ID();
640 }
641
642 // Check if this is an order bump product - if so, don't modify the quantity display
643 if( isset($cart_item['wpfnl_order_bump']) && $cart_item['wpfnl_order_bump'] ){
644 return $quantity;
645 }
646
647 $isQuantity = get_post_meta($step_id, '_wpfnl_quantity_support',true);
648 $order_bump_product = get_post_meta($step_id,'order-bump-settings',true);
649 $quantityLimit = get_post_meta($step_id, '_wpfnl_quantity_limit', true);
650 if($isQuantity === 'yes'){
651 // Check if this is a legacy single order bump structure
652 if(isset($order_bump_product['product']) && isset($order_bump_product['isEnabled'])){
653
654 if( ($order_bump_product['product'] == $cart_item["product_id"]) && $order_bump_product['isEnabled'] == 'yes' ){
655 return $quantity;
656 }
657 }
658
659 $variations = json_encode($cart_item['variation']);
660 $product_id = $cart_item["product_id"];
661 $quantity = $cart_item["quantity"];
662 $variation_id = $cart_item["variation_id"];
663 $isQuantityLimit = false;
664 $set_quantity = 0;
665
666 if( isset($quantityLimit['isEnabled']) && $quantityLimit['isEnabled'] === 'yes' ){
667 $set_quantity = $quantityLimit['quantity'];
668 $isQuantityLimit = true;
669 }
670
671 if( $isQuantityLimit ){
672 $quantity = "× <input type='number' min='1' step='1' max='".$set_quantity."' value='".$quantity."' class='wpfnl-quantity-setect' data-product-id='".$product_id."' data-variation='".$variations."' data-variation-id='".$variation_id."' data-quantity-limit='".$set_quantity."' data-set-quantity='yes'/>";
673 }else{
674 $quantity = "× <input type='number' min='1' step='1' value='".$quantity."' class='wpfnl-quantity-setect' data-product-id='".$product_id."' data-variation='".$variations."' data-variation-id='".$variation_id."' data-set-quantity='no' />";
675 }
676 }
677 return $quantity;
678
679 }
680
681 }
682