PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / 2.8.16
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell v2.8.16
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 / includes / utils / class-wpfnl-functions.php

class-wpfnl-functions.php in WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell 2.8.16, at includes/utils/class-wpfnl-functions.php

3,744 lines 92.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * This class is responsible for all the helper functions
4 *
5 * @package WPFunnels
6 */
7 namespace WPFunnels;
8
9 class Wpfnl_functions
10 {
11 public static $installed_plugins;
12
13 /**
14 * Get all the steps of the funnel
15 *
16 * @param $funnel_id
17 *
18 * @return array|mixed
19 */
20 public static function get_steps( $funnel_id ) {
21 $steps = get_post_meta( $funnel_id, '_steps_order', true );
22 if ( ! is_array( $steps ) ) {
23 $steps = array();
24 }
25 return $steps;
26 }
27
28
29 /**
30 * Check if the associated order is from a funnel.
31 *
32 * This function checks if the given order is associated with a funnel.
33 * It returns true if the order is from a funnel, and false otherwise.
34 * Previously 'get_funnel_id_from_order' function parameter was order id but from 2.8.0 version it changed to order object
35 *
36 * @param \WC_Order $order The WooCommerce order object.
37 * @return bool True if the order is from a funnel, false otherwise.
38 * @since 2.8.0
39 */
40 public static function check_if_funnel_order($order) {
41 if ( false === is_a( $order, 'WC_Order' ) ) {
42 return false;
43 }
44 $funnel_id = self::get_funnel_id_from_order($order);
45 if( !$funnel_id ){
46 return false;
47 }
48 return true;
49 }
50
51
52 /**
53 * Get the associated funnel ID from the order ID.
54 *
55 * This function retrieves the ID of the associated funnel for a given order.
56 * Previously data was retrieved by post meta table but from 2.8.0 version user get_meta function to retrieve meta
57 *
58 * @param \WC_Order|Int $order The WooCommerce order object or Order ID of WooCommerce order.
59 * @return int|false The ID of the associated funnel, or false if not found.
60 * @since 2.8.0
61 */
62 public static function get_funnel_id_from_order($order) {
63 if( !$order ){
64 return false;
65 }
66
67 if ( false === is_a( $order, 'WC_Order' ) ) {
68 $order_id = intval($order);
69 $order = wc_get_order( $order_id );
70 if ( false === is_a( $order, 'WC_Order' ) ) {
71 return false;
72 }
73 }
74
75 $funnel_id = $order->get_meta('_wpfunnels_funnel_id') ? $order->get_meta('_wpfunnels_funnel_id') : $order->get_meta('_wpfunnels_parent_funnel_id');
76 if (!$funnel_id) {
77 return false;
78 }
79 return intval($funnel_id);
80 }
81
82 /**
83 * Check if the given string is a date or not
84 *
85 * @param $date
86 *
87 * @return bool
88 * @since 1.0.0
89 */
90 public static function validate_date($date)
91 {
92 return (bool)strtotime($date);
93 }
94
95 /**
96 * Define constant if it is not set yet
97 *
98 * @param $name
99 * @param $value
100 *
101 * @since 2.0.3
102 */
103 public static function maybe_define_constant( $name, $value ) {
104 if ( ! defined( $name ) ) {
105 define( $name, $value );
106 }
107 }
108
109 /**
110 * Set do not cache constants
111 */
112 public static function do_not_cache() {
113 global $post;
114
115 if ( ! apply_filters( 'wpfunnels/do_not_cache', true, $post->ID ) ) {
116 return;
117 }
118 self::maybe_define_constant( 'DONOTCACHEPAGE', true );
119 self::maybe_define_constant( 'DONOTCACHEOBJECT', true );
120 self::maybe_define_constant( 'DONOTCACHEDB', true );
121 nocache_headers();
122 }
123
124 /**
125 * Return formatted date from the
126 * given date object
127 *
128 * @param $date
129 *
130 * @return false|string
131 * @since 1.0.0
132 */
133 public static function get_formatted_date($date)
134 {
135 return date('Y-m-d h:i A', strtotime($date));
136 }
137
138
139 /**
140 * Get checkout ID
141 *
142 * @return bool|int
143 */
144 public static function get_checkout_id_from_post_data() {
145 $checkout_id = !empty( $_POST[ '_wpfunnels_checkout_id' ] ) ? filter_var( wp_unslash( $_POST[ '_wpfunnels_checkout_id' ] ), FILTER_SANITIZE_NUMBER_INT ) : false;
146 return $checkout_id ? intval( $checkout_id ) : false;
147 }
148
149
150 /**
151 * Get checkout id from post
152 *
153 * @return bool|int
154 */
155 public static function get_checkout_id_from_post( $post = null )
156 {
157 if( isset($post['post_data']) ){
158 $post_data = array();
159 parse_str($post['post_data'], $post_data);
160 if( isset($post_data['_wpfunnels_checkout_id']) ){
161 return $post_data['_wpfunnels_checkout_id'];
162 }
163 }
164 return false;
165 }
166
167
168 /**
169 * Check order bump clicked or not from post data
170 *
171 * @return bool True|False
172 * @since 2.8.0
173 */
174 public static function is_orderbump_clicked_from_post_data() {
175 if( !empty( $_POST[ 'post_data' ] ) ) {
176 wp_parse_str( $_POST[ 'post_data' ], $post_data );
177 return !empty( $post_data[ '_wpfunnels_order_bump_clicked' ] ) && 'yes' === $post_data[ '_wpfunnels_order_bump_clicked' ];
178 }
179 return !empty( $_POST[ '_wpfunnels_order_bump_clicked' ] ) && 'yes' === $_POST[ '_wpfunnels_order_bump_clicked' ];
180 }
181
182
183 /**
184 * Check variation is selected or not from post data
185 *
186 * @return bool True|False
187 * @since 2.8.0
188 */
189 public static function is_variation_selected_from_post_data() {
190 if( !empty( $_POST[ 'post_data' ] ) ) {
191 wp_parse_str( $_POST[ 'post_data' ], $post_data );
192 return !empty( $post_data[ '_wpfunnels_variable_product' ] ) && 'selected' === $post_data[ '_wpfunnels_variable_product' ];
193 }
194 return !empty( $_POST[ '_wpfunnels_variable_product' ] ) && 'selected' === $_POST[ '_wpfunnels_variable_product' ];
195 }
196
197
198 /**
199 * Get funnel id
200 *
201 * @param $step_id
202 *
203 * @return mixed
204 */
205 public static function get_funnel_id_from_step($step_id) {
206 $funnel_id = get_post_meta($step_id, '_funnel_id', true);
207 return intval($funnel_id);
208 }
209
210 /**
211 * Get order id from funnel post data
212 *
213 * @return false|int
214 * @since 2.8.2
215 */
216 public static function get_order_id_from_post_data() {
217 if( !empty( $_POST[ '_wpfunnels_order_unique_identifier' ] ) ) {
218 global $wpdb;
219 $identifier = wp_unslash( $_POST[ '_wpfunnels_order_unique_identifier' ] );
220 $prepare_guery = $wpdb->prepare( "SELECT `post_id` FROM {$wpdb->postmeta} WHERE meta_key ='_wpfunnels_order_unique_identifier' and meta_value like '%s'", $identifier );
221 $get_value = $wpdb->get_row( $prepare_guery );
222 return $get_value ? intval( $get_value->post_id ) : false;
223 }
224 return false;
225 }
226
227
228 /**
229 * Get checkout id from order
230 *
231 * @param $order_id
232 *
233 * @return int
234 */
235 public static function get_checkout_id_from_order( $order_id ) {
236 $checkout_id = get_post_meta( $order_id, '_wpfunnels_checkout_id', true );
237 return $checkout_id ? intval( $checkout_id ) : false;
238 }
239
240
241 /**
242 * Get funnel from post data
243 *
244 * @return bool|int
245 */
246 public static function get_funnel_id_from_post_data() {
247 if( !empty( $_POST[ '_wpfunnels_funnel_id' ] ) ) {
248 $funnel_id = filter_var( wp_unslash( $_POST[ '_wpfunnels_funnel_id' ] ), FILTER_SANITIZE_NUMBER_INT );
249 return $funnel_id ? intval( $funnel_id ) : false;
250 }
251 return false;
252 }
253
254
255 /**
256 * Get funnel id from step page
257 *
258 * @return false|mixed
259 */
260 public static function get_funnel_id() {
261 global $post;
262 if ( $post ) {
263 $funnel_id = get_post_meta( $post->ID, '_funnel_id', true );
264 return $funnel_id ? intval( $funnel_id ) : false;
265 }
266 return false;
267 }
268
269 /**
270 * Unserialize data
271 *
272 * @param $data
273 *
274 * @return mixed
275 * @since 1.0.0
276 */
277 public static function unserialize_array_data($data)
278 {
279 return maybe_unserialize($data);
280 }
281
282
283 /**
284 * Get formatted string with phrase
285 * e.g: 1 item if singular or
286 * 2 items if plural
287 *
288 * @param Int $number
289 * @param String $singular
290 * @param String $plural
291 *
292 * @return String
293 * @since 1.0.0
294 */
295 public static function get_formatted_data_with_phrase( $number, $singular = '', $plural = 's' ) {
296 return ( is_numeric( $number ) && 0 <= $number ) ? ( 1 < $number ? $plural : $singular ) : null;
297 }
298
299
300 /**
301 * Get formatted string from funnel status
302 *
303 * @param $status
304 *
305 * @return string
306 * @since 1.0.0
307 */
308 public static function get_formatted_status( $status ) {
309 switch( $status ) {
310 case 'publish':
311 return 'Published';
312 case 'draft':
313 return 'Draft';
314 default:
315 return $status;
316 }
317 }
318
319
320 /**
321 * Generate active class for funnel menus
322 *
323 * @param $key
324 *
325 * @return bool
326 * @since 1.0.0
327 */
328 public static function define_active_class($key)
329 {
330 $page = filter_input(INPUT_GET, 'page', FILTER_SANITIZE_SPECIAL_CHARS);
331 if ($page === WPFNL_MAIN_PAGE_SLUG && $key === 'overview') {
332 return true;
333 }
334
335 if ($page === 'create_funnel' && $key === 'create_funnel') {
336 return true;
337 }
338
339 if ($page === 'wpfnl_settings' && $key === 'settings') {
340 return true;
341 }
342
343 if ($page === 'wpfunnels_integrations' && $key === 'integrations') {
344 return true;
345 }
346 }
347
348
349 /**
350 * Check If module exists or not
351 *
352 * @param $id
353 *
354 * @return bool
355 * @since 1.0.0
356 */
357 public static function check_if_module_exists( $id ) {
358 return 'publish' === get_post_status( $id ) || 'draft' === get_post_status( $id );
359 }
360
361
362 /**
363 * Check if the cpt is step or not
364 *
365 * @param $step_id
366 * @param string $type
367 *
368 * @return bool
369 */
370 public static function check_if_this_is_step_type_by_id($step_id, $type = 'landing')
371 {
372 $post_type = get_post_type($step_id);
373 if (WPFNL_STEPS_POST_TYPE === $post_type) {
374 if ($type === get_post_meta($step_id, '_step_type', true)) {
375 return true;
376 }
377 }
378 return false;
379 }
380
381
382 /**
383 * Get thankyou page id
384 *
385 * @param $funnel_id
386 *
387 * @return bool|mixed
388 *
389 * @since 2.2.6
390 */
391 public static function get_thankyou_page_id( $funnel_id ) {
392 $steps = self::get_steps( $funnel_id );
393 if( is_array( $steps ) ) {
394 foreach( $steps as $step ) {
395 if( 'thankyou' === $step[ 'step_type' ] ) {
396 return $step[ 'id' ];
397 }
398 }
399 }
400 return false;
401 }
402
403
404 /**
405 * Check if the current post type is step or not
406 *
407 * @return bool
408 * @since 2.0.3
409 */
410 public static function is_funnel_step_page( $post_type = '' )
411 {
412 if( self::get_current_post_type($post_type) === WPFNL_STEPS_POST_TYPE ) {
413 return true;
414 }
415
416 $post_id = null;
417 if ( wp_doing_ajax() || isset( $_GET['wc-ajax'] ) ) {
418 $post_id = self::get_checkout_id_from_post($_POST);
419 }
420 global $post;
421 $post = $post_id ? get_post( $post_id ) : $post;
422 $post_type = $post->post_type ?? '';
423 if( self::get_current_post_type($post_type) === WPFNL_STEPS_POST_TYPE ){
424 return true;
425 }
426 return false;
427 }
428
429
430 /**
431 * Get current post type
432 *
433 * @param $post_type
434 *
435 * @return string
436 *
437 * @since 2.3.5
438 */
439 public static function get_current_post_type( $post_type ) {
440 global $post;
441 if ( '' === $post_type && is_object( $post ) ) {
442 $post_type = $post->post_type;
443 }else{
444 $post_id = '';
445 if ( wp_doing_ajax() || isset( $_GET['wc-ajax'] ) ) {
446 $post_id = self::get_checkout_id_from_post($_POST);
447 }
448
449 if( $post_id ){
450 $post = get_post( $post_id );
451 $post_type = $post->post_type;
452 }
453 }
454 return $post_type;
455 }
456
457
458 /**
459 * Check if funnel checkout page
460 *
461 * @param $funnel_id
462 *
463 * @return bool
464 */
465 public static function is_funnel_checkout_page()
466 {
467 if(isset($_POST['post_data'])){
468 parse_str($_POST['post_data'],$post_data);
469 if(isset($post_data['_wpfunnels_checkout_id'])){
470 return [
471 'status' => true,
472 'id' => $post_data['_wpfunnels_checkout_id']
473 ];
474 }
475 }
476 return [
477 'status' => false,
478 'id' => ''
479 ];
480 }
481
482
483 /**
484 * Check if funnel exists
485 *
486 * @param $funnel_id
487 *
488 * @return bool
489 */
490 public static function is_funnel_exists($funnel_id)
491 {
492 if (!$funnel_id) return false;
493 if (FALSE === get_post_status($funnel_id)) {
494 return true;
495 }
496 return false;
497 }
498
499
500 /**
501 * Function to check if the current page is a post edit page
502 *
503 * @return bool
504 *
505 * @since 2.0.3
506 */
507 public static function is_step_edit_page(){
508
509 $step_id = -1;
510 if ( is_admin() && isset( $_REQUEST['action'] ) ) {
511 if ( 'edit' === $_REQUEST['action'] && isset( $_GET['post'] ) ) {
512 $step_id = isset( $_GET[ 'post' ] ) ? $_GET[ 'post' ] : - 1;
513 }
514 elseif ( isset( $_REQUEST['wpfunnels_gb'] ) && isset( $_POST['post_id'] ) ){ //phpcs:ignore
515 $step_id = intval( $_POST['post_id'] ); //phpcs:ignore
516 }
517 if ( $step_id === - 1 ) {
518
519 return false;
520 }
521 $get_post_type = get_post_type( $step_id );
522 if ( WPFNL_STEPS_POST_TYPE === $get_post_type ) {
523 return true;
524 }
525 }
526 return false;
527 }
528
529
530 /**
531 * Check if the cpt is step or not
532 *
533 * @param string $type
534 *
535 * @return bool
536 * @since 1.0.0
537 */
538 public static function check_if_this_is_step_type($type = 'landing')
539 {
540 $post_type = get_post_type();
541
542 if (WPFNL_STEPS_POST_TYPE === $post_type) {
543 global $post;
544 if ($type === get_post_meta($post->ID, '_step_type', true)) {
545 return true;
546 }
547 }
548 return false;
549 }
550
551
552 /**
553 * Hooks for start and end the journey
554 * of a funnel
555 */
556 public static function start_journey() {
557 $post_type = get_post_type();
558 if ( WPFNL_STEPS_POST_TYPE === $post_type ) {
559 global $post;
560 $step_id = $post->ID;
561 $funnel_id = self::get_funnel_id_from_step($step_id);
562 $steps = self::get_steps($funnel_id);
563 $funnel_data = self::get_funnel_data($funnel_id);
564 // start the journey
565 if( $steps && is_array($steps) ) {
566 if( $steps[0]['id'] === $step_id ) {
567 do_action( 'wpfunnels/funnel_journey_starts', $step_id, $funnel_id );
568 }
569 }
570
571 // end the journey
572 if( $funnel_data && isset($funnel_data['drawflow']['Home']['data']) ) {
573 $funnel_data = $funnel_data['drawflow']['Home']['data'];
574 foreach ( $funnel_data as $data ) {
575 $info = $data['data'];
576 $step_type = $info['step_type'];
577
578 if('conditional' !== $step_type) {
579 $_step_id = isset($info['step_id']) ? $info['step_id'] : '';
580 $output_con = $data['outputs'];
581
582 if( empty($output_con) ) {
583 if( $_step_id === $step_id ) {
584 do_action( 'wpfunnels/funnel_journey_end', $step_id, $funnel_id );
585 delete_option( 'optin_data' );
586 break;
587 }
588 }
589 }
590 }
591 }
592 }
593 }
594
595
596 /**
597 * Conditional node logic check
598 *
599 * @param $funnel_id
600 * @param $order
601 * @param $condition_identifier
602 * @param $current_page_id
603 * @param $checker
604 *
605 * @return bool
606 *
607 * @since 2.0.2
608 */
609 public static function check_condition( $funnel_id, $order, $condition_identifier, $current_page_id, $checker = 'accept' )
610 {
611
612 $group_conditions = get_post_meta( $funnel_id, $condition_identifier, true );
613
614 if ($group_conditions) {
615 // Loop through group condition.
616 foreach ($group_conditions as $group) {
617 if (empty($group)) {
618 continue;
619 }
620
621 $match_group = true;
622 // Loop over rules and determine if all rules match.
623 foreach ($group as $rule) {
624 if (!self::match_rule( $funnel_id, $rule, $order, $current_page_id, $checker )) {
625 $match_group = false;
626 break;
627 }
628 }
629
630 // If this group matches, show the field group.
631 if ($match_group) {
632 return true;
633 }else{
634 return false;
635 }
636 }
637 }
638 if( $checker == 'accept' ){
639 return true;
640 }
641 // Return default.
642 return false;
643 }
644
645
646 /**
647 * Check if rule is matched
648 *
649 * @param $rule
650 * @param $order
651 * @param $current_page_id
652 * @param $checker
653 *
654 * @return mixed
655 *
656 * @since 2.0.2
657 */
658 public static function match_rule( $funnel_id, $rule, $order, $current_page_id, $checker )
659 {
660
661 if (isset( $rule['field'] ) && $rule['field'] == 'downsell') {
662 $rule['field'] = 'upsell';
663 }
664 $condition = $rule['field'];
665 if ( strpos($rule['field'] , 'optin')){
666 $condition = 'optin';
667 }
668 $checker_function = $condition . '_condition_checker';
669 return self::$checker_function( $funnel_id, $rule, $order, $current_page_id, $checker );
670 }
671
672
673 /**
674 * Upsell condition checker for conditional step
675 *
676 * @param Integer $funnel_id
677 * @param Array $data
678 * @param Object $order
679 * @param Integer $current_page_id
680 * @param String $checker
681 *
682 * @return Boolean
683 *
684 * @since 2.5.7
685 */
686 public static function upsell_condition_checker( $funnel_id ,$data, $order, $current_page_id, $checker)
687 {
688
689 if ($data['value'] == 'yes') {
690 if ( $checker == 'accept' ) {
691 return true;
692 } else {
693 return false;
694 }
695
696 } else if ($data['value'] == 'no') {
697
698 if ($checker == 'reject') {
699 return true;
700 } else {
701 return false;
702 }
703 }
704 return false;
705 }
706
707
708 /**
709 * Optin condition checker for conditional step
710 *
711 * @param Integer $funnel_id
712 * @param Array $data
713 * @param Object $order
714 * @param Integer $current_page_id
715 * @param String $checker
716 *
717 * @return Boolean
718 *
719 * @since 2.5.7
720 */
721 public function optin_condition_checker( $funnel_id, $rule, $data, $current_page_id, $checker = 'accept' ){
722
723 if( isset($data['step_id']) ){
724 $step_id = str_replace('optin_','',$data['step_id'] );
725 $optin_steps = get_option('optin_data');
726 if( isset( $optin_steps['optin_data'] )){
727 $key = array_search($step_id, array_column($optin_steps['optin_data'], 'step_id'));
728 if( false !== $key ){
729 unset($optin_steps[$key]);
730 update_option('optin_data', $optin_steps );
731 return true;
732 }
733 }
734
735 }elseif(!empty($data['cta']) ){
736 return false;
737 }
738
739 if( isset($rule['field']) ){
740 $step_id = str_replace('optin_','',$rule['field'] );
741 $optin_steps = get_option('optin_data');
742 if( isset( $optin_steps['optin_data'] )){
743 $key = array_search($step_id, array_column($optin_steps['optin_data'], 'step_id'));
744 if( false !== $key ){
745 unset($optin_steps[$key]);
746 update_option('optin_data', $optin_steps );
747 return true;
748 }
749 }
750 }
751
752 return false;
753 }
754
755
756 /**
757 * Order bump condition checker
758 *
759 * @param $data
760 * @param $order
761 * @param $current_page_id
762 *
763 * @return bool
764 */
765 public static function orderbump_condition_checker( $funnel_id, $data, $order, $current_page_id, $checker = 'accept' )
766 {
767 $order_bump_accepted = '';
768 if ( Wpfnl_functions::is_wc_active() ) {
769 $order_bump_accepted = WC()->session->get('order_bump_accepted');
770 }
771 return $data['value'] == $order_bump_accepted;
772 }
773
774
775 /**
776 * Check cart total condition in conditional node
777 *
778 * @param $data
779 * @param $order
780 * @param $current_page_id
781 *
782 * @return bool
783 */
784 public static function carttotal_condition_checker($funnel_id, $data, $order, $current_page_id, $checker = 'accept' )
785 {
786 $cart_total = $order->get_total();
787
788 $checker = false;
789 if ($data['condition'] == 'greater') {
790 if ($cart_total > $data['value']) {
791 $checker = true;
792 }
793 } elseif ($data['condition'] == 'equal') {
794 if ($cart_total == $data['value']) {
795 $checker = true;
796 }
797 } elseif ($data['condition'] == 'less') {
798 if ($cart_total < $data['value']) {
799 $checker = true;
800 }
801 }
802 return $checker;
803 }
804
805
806 /**
807 * Billing country condition checker
808 *
809 * @param Array
810 * @param Object
811 * @param String
812 * @param String
813 *
814 * @return Bool
815 * @since 2.4.18
816 */
817 public static function billing_condition_checker($funnel_id, $data, $order, $current_page_id, $checker ){
818 if( $order ){
819 $billing_country = $order->get_billing_country();
820 if( isset($data['field']) && 'billing' === $data['field'] && isset($data['value']) && $billing_country === $data['value'] ){
821 return true;
822 }
823 }
824 return false;
825 }
826
827
828 /**
829 * Shipping country condition checker
830 *
831 * @param Array
832 * @param Object
833 * @param String
834 * @param String
835 *
836 * @return Bool
837 * @since 2.4.18
838 */
839 public static function shipping_condition_checker( $funnel_id, $data, $order, $current_page_id, $checker ){
840 if( $order ){
841 $shipping_country = $order->get_shipping_country();
842 if( isset($data['field']) && 'shipping' === $data['field'] && isset($data['value']) && $shipping_country === isset($data['value']) ){
843 return true;
844 }
845 }
846 return false;
847 }
848
849
850 /**
851 * Get next step of the
852 * funnel
853 *
854 * @param $funnel_id
855 * @param $step_id
856 * @param bool $condition
857 *
858 * @return Mix
859 *
860 * @since 1.0.0
861 */
862 public static function get_next_step( $funnel_id, $step_id, $condition = true )
863 {
864 if( $funnel_id && !$step_id ) {
865 return false;
866 }
867 $parent_step_id = get_post_meta( $step_id, '_parent_step_id', true );
868 if( $parent_step_id ){
869 $step_id = $parent_step_id;
870 }
871 $funnel_data = self::get_funnel_data($funnel_id);
872 if ( $funnel_data ) {
873 $node_id = self::get_node_id( $funnel_id, $step_id );
874
875 $node_data = $funnel_data['drawflow']['Home']['data'];
876 $step_type = get_post_meta( $step_id, '_step_type', true );
877 foreach ( $node_data as $node_key => $node_value ) {
878 if ( $node_value['id'] == $node_id ) {
879 $triggers = self::get_mint_triggers();
880 if( in_array( $step_type, $triggers ) ){
881 $next_node_id = isset($node_value['outputs']['output_1']['connections'][0]['node']) ? $node_value['outputs']['output_1']['connections'][0]['node'] : '';
882 }else{
883 if( $condition ) {
884 $next_node_id = isset($node_value['outputs']['output_1']['connections'][0]['node']) ? $node_value['outputs']['output_1']['connections'][0]['node'] : '';
885 } else {
886 $next_node_id = isset($node_value['outputs']['output_2']['connections'][0]['node']) ? $node_value['outputs']['output_2']['connections'][0]['node'] : '';
887 }
888 }
889
890 if( $next_node_id ){
891 $next_step_id = self::get_step_by_node( $funnel_id, $next_node_id );
892 $next_step_type = self::get_node_type( $node_data, $next_node_id );
893 if( in_array( $next_step_type, $triggers ) ){
894 $next_step = self::get_next_step( $funnel_id, $next_step_id );
895 return $next_step;
896 }
897
898 return apply_filters( 'wpfunnels/next_step_data', array(
899 'step_id' => $next_step_id,
900 'step_type' => $next_step_type,
901 ));
902
903 }else{
904 // if there is no thank you page
905 self::redirect_to_deafult_thankyou();
906 }
907 }
908 }
909 }
910 return false;
911 }
912
913
914 /**
915 * Redirect deafult thank you page
916 */
917 public static function redirect_to_deafult_thankyou(){
918
919 if( isset( $_POST[ 'order_id' ] ) && $_POST[ 'order_id' ] ) {
920 $url = home_url().'/checkout/order-received/'.$_POST[ 'order_id' ].'/?key='.$_POST[ 'order_key' ];
921 return $url;
922 }else{
923 add_action( 'template_redirect', function( $order_id ){
924 if( isset( $_GET[ 'order-received' ] ) && $_GET[ 'order-received' ] ) {
925 $url = '';
926 $url = add_query_arg( 'id', $_GET[ 'order-received' ], $url );
927 wp_safe_redirect( wp_sanitize_redirect( esc_url_raw( $url ) ) );
928 exit;
929 }elseif( isset( $_POST[ 'order_id' ] ) && $_POST[ 'order_id' ] ) {
930 $url = '';
931 $url = add_query_arg( 'id', $_POST[ 'order_id' ], $url );
932 wp_safe_redirect( wp_sanitize_redirect( esc_url_raw( $url ) ) );
933 exit;
934 }
935 });
936 }
937 }
938
939
940 /**
941 * Get previous step of the
942 * funnel
943 *
944 * @param $funnel_id
945 * @param $step_id
946 * @param bool $condition
947 *
948 * @return Mix
949 *
950 * @since 1.0.0
951 */
952 public static function get_prev_step( $funnel_id, $step_id, $condition = true )
953 {
954 if( $funnel_id && !$step_id ) {
955 return false;
956 }
957 $funnel_data = self::get_funnel_data($funnel_id);
958 if ( $funnel_data ) {
959 $node_id = self::get_node_id( $funnel_id, $step_id );
960 $node_data = $funnel_data['drawflow']['Home']['data'];
961
962 foreach ( $node_data as $node_key => $node_value ) {
963 if ( $node_value['id'] == $node_id ) {
964 if( $condition ) {
965 if(!empty($node_value['inputs'])){
966 $prev_node_id = $node_value['inputs']['input_1']['connections'][0]['node'];
967 }else{
968 $prev_node_id = '';
969 }
970
971 } else {
972 if(!empty($node_value['inputs'])){
973 $prev_node_id = $node_value['inputs']['input_2']['connections'][0]['node'];
974 }else{
975 $prev_node_id = '';
976 }
977
978 }
979 $prev_step_id = self::get_step_by_node( $funnel_id, $prev_node_id );
980 $prev_step_type = self::get_node_type( $node_data, $prev_node_id );
981 if($prev_step_type == 'conditional'){
982 return self::get_prev_step($funnel_id,$prev_step_id);
983
984 }else{
985
986 return array(
987 'step_id' => $prev_step_id,
988 'step_type' => $prev_step_type,
989 );
990 }
991 }
992 }
993
994 }
995 return false;
996 }
997
998 /**
999 * Get node type
1000 */
1001 public static function get_node_type($node_data, $node_id)
1002 {
1003 foreach ($node_data as $node_key => $node_value) {
1004 if ($node_value['id'] == $node_id) {
1005 return $node_value['data']['step_type'];
1006 }
1007 }
1008 }
1009
1010 /**
1011 * Get step by node
1012 */
1013 public static function get_step_by_node($funnel_id, $node_id)
1014 {
1015 $identifier_json = get_post_meta($funnel_id, 'funnel_identifier', true);
1016 $identifier_json = preg_replace('/\: *([0-9]+\.?[0-9e+\-]*)/', ':"\\1"', $identifier_json);
1017 if ($identifier_json) {
1018 $identifier = json_decode($identifier_json, true);
1019 foreach ($identifier as $identifier_key => $identifier_value) {
1020 if ($identifier_key == $node_id) {
1021 return $identifier_value;
1022 }
1023 }
1024 }
1025 return false;
1026 }
1027
1028
1029 /**
1030 * Get node by step
1031 *
1032 * @param $funnel_id
1033 * @param $step_id
1034 *
1035 * @return bool|int|string
1036 */
1037 public static function get_node_id( $funnel_id, $step_id )
1038 {
1039 $identifier_json = get_post_meta( $funnel_id, 'funnel_identifier', true );
1040 if ($identifier_json) {
1041 $identifier = json_decode( $identifier_json, true );
1042 foreach ( $identifier as $identifier_key => $identifier_value ) {
1043 if ($identifier_value == $step_id) {
1044 return $identifier_key;
1045 }
1046 }
1047 }
1048 return false;
1049 }
1050
1051
1052 /**
1053 * Get funnel data
1054 *
1055 * @param $funnel_id
1056 *
1057 * @return mixed
1058 *
1059 * @since 2.0.5
1060 */
1061 public static function get_funnel_data( $funnel_id ) {
1062 return get_post_meta( $funnel_id, 'funnel_data', true );
1063 }
1064
1065
1066 /**
1067 * Update settings option
1068 *
1069 * @param $key
1070 * @param $value
1071 * @param bool $network
1072 *
1073 * @since 1.0.0
1074 */
1075 public static function update_admin_settings($key, $value, $network = false)
1076 {
1077 if ( $network && is_multisite() ) {
1078 update_site_option($key, $value);
1079 } else {
1080 update_option($key, $value);
1081 }
1082 }
1083
1084
1085 /**
1086 * Get admin settings option
1087 * by key
1088 *
1089 * @param $key
1090 * @param bool $default
1091 * @param bool $network
1092 *
1093 * @return mixed|void
1094 * @since 1.0.0
1095 */
1096 public static function get_admin_settings($key, $default = false, $network = false)
1097 {
1098 if ($network && is_multisite()) {
1099 $value = get_site_option($key, $default);
1100 } else {
1101 $value = get_option($key, $default);
1102 }
1103 return $value;
1104 }
1105
1106
1107 /**
1108 * Get general settings data
1109 *
1110 * @return array
1111 * @since 1.0.0
1112 */
1113 public static function get_general_settings()
1114 {
1115 $default_settings = apply_filters(
1116 'wpfunnels_general_settings',
1117 [
1118 'builder' => 'elementor',
1119 'paypal_reference' => 'off',
1120 'order_bump' => 'off',
1121 'ab_testing' => 'off',
1122 'allow_funnels' => Array
1123 (
1124 'administrator' => 'true'
1125 ),
1126 'funnel_type' => 'lead',
1127 'create_child_order' => 'off',
1128 'disable_theme_style' => 'off',
1129 'enable_log_status' => 'off',
1130 ]
1131 );
1132 $saved_settings = self::get_admin_settings('_wpfunnels_general_settings', $default_settings);
1133 return wp_parse_args($saved_settings, $default_settings);
1134 }
1135
1136
1137 /**
1138 * Get permalink settings data
1139 *
1140 * @return array
1141 * @since 1.0.0
1142 */
1143 public static function get_permalink_settings()
1144 {
1145 $default_settings = apply_filters(
1146 'wpfunnels_permalink_settings',
1147 [
1148 'structure' => 'default',
1149 'step_base' => WPFNL_STEPS_POST_TYPE,
1150 'funnel_base' => WPFNL_FUNNELS_POST_TYPE,
1151 ]
1152 );
1153 $saved_settings = self::get_admin_settings('_wpfunnels_permalink_settings');
1154 return wp_parse_args($saved_settings, $default_settings);
1155 }
1156
1157
1158 /**
1159 * Get offer settings data
1160 *
1161 * @return array
1162 * @since 1.0.0
1163 */
1164 public static function get_offer_settings()
1165 {
1166 $default_settings = apply_filters( 'wpfunnels/get_offer_settings', array(
1167 'offer_orders' => 'main-order',
1168 'show_supported_payment_gateway' => 'off',
1169 'skip_offer_step' => 'off',
1170 'skip_offer_step_for_free' => 'off',
1171 )
1172 );
1173 $saved_settings = self::get_admin_settings('_wpfunnels_offer_settings');
1174 return wp_parse_args($saved_settings, $default_settings);
1175 }
1176
1177 /**
1178 * Get GTM events
1179 *
1180 * @return array
1181 */
1182 public static function get_gtm_events(){
1183 $default_gtm_events = array(
1184 'add_to_cart' => 'Add to cart',
1185 'begin_checkout' => 'Begin checkout',
1186 'add_payment_info' => 'Add Payment Info',
1187 'add_shipping_info' => 'Add Shipping Info',
1188 'purchase' => 'Purchase',
1189 'orderbump_accept' => 'Order Bump',
1190 'upsell' => 'Upsell',
1191 'downsell' => 'Downsell',
1192 );
1193 return $default_gtm_events;
1194 }
1195
1196 public static function get_gtm_settings(){
1197 $default_enable_settings = array(
1198 'gtm_enable' => 'off',
1199 'gtm_container_id' => '',
1200 'gtm_events' => array(
1201 'add_to_cart' => 'true',
1202 'begin_checkout' => 'true',
1203 'add_payment_info' => 'true',
1204 'add_shipping_info' => 'true',
1205 'purchase' => 'true',
1206 'orderbump_accept' => 'true',
1207 'upsell' => 'true',
1208 'downsell' => 'true',
1209 ),
1210 );
1211 $gtm_settings = self::get_admin_settings('_wpfunnels_gtm');
1212 return wp_parse_args($gtm_settings, $default_enable_settings);
1213 }
1214 /**
1215 * Get facebook pixel events
1216 *
1217 * @return array
1218 */
1219 public static function get_facebook_events(){
1220 $default_fb_events = array(
1221 'AddPaymentInfo' => 'Add payment info',
1222 'AddToCart' => 'Add to cart',
1223 'InitiateCheckout' => 'Initiate checkout',
1224 //'Lead' => 'Lead',
1225 'Purchase' => 'Purchase',
1226 'ViewContent' => 'View content',
1227 );
1228 return $default_fb_events;
1229 }
1230
1231 public static function get_facebook_pixel_settings(){
1232 $default_enable_settings = array(
1233 'enable_fb_pixel' => 'off',
1234 'facebook_pixel_id' => '',
1235 'facebook_tracking_events' => array(
1236 'AddPaymentInfo' => 'true',
1237 'AddToCart' => 'true',
1238 'InitiateCheckout' => 'true',
1239 'Lead' => 'true',
1240 'Purchase' => 'true',
1241 'ViewContent' => 'true',
1242 ),
1243 );
1244 $facebook_pixel_setting = self::get_admin_settings('_wpfunnels_facebook_pixel');
1245 return wp_parse_args($facebook_pixel_setting, $default_enable_settings);
1246 }
1247
1248
1249 public static function get_recaptcha_settings(){
1250 $default_enable_settings = array(
1251 'enable_recaptcha' => 'no',
1252 'recaptcha_site_key' => '',
1253 'recaptcha_site_secret' => '',
1254 );
1255 $recaptcha_setting = self::get_admin_settings('_wpfunnels_recaptcha_setting');
1256 return wp_parse_args($recaptcha_setting, $default_enable_settings);
1257 }
1258
1259
1260 /**
1261 * Get advanced settings
1262 */
1263 public static function get_advanced_settings(){
1264 $default_enable_settings = array(
1265 'show_supported_payment_gateway' => 'off',
1266 );
1267
1268 $advanced_settings = self::get_admin_settings('_wpfunnels_advanced_settings');
1269 return wp_parse_args($advanced_settings, $default_enable_settings);
1270 }
1271
1272 /**
1273 * Get UTM Parameters
1274 *
1275 * @return array
1276 */
1277 public static function get_utm_params(){
1278 $default_utm_params = array(
1279 'utm_source' => 'UTM Source',
1280 'utm_medium' => 'UTM Medium',
1281 'utm_campaign' => 'UTM Campaign',
1282 'utm_content' => 'UTM Content',
1283 );
1284 return $default_utm_params;
1285 }
1286
1287 public static function get_utm_settings(){
1288 $default_enable_settings = array(
1289 'utm_enable' => 'off',
1290 'utm_source' => '',
1291 'utm_medium' => '',
1292 'utm_campaign' => '',
1293 'utm_content' => '',
1294 );
1295 $utm_settings = self::get_admin_settings('_wpfunnels_utm_params');
1296 return wp_parse_args($utm_settings, $default_enable_settings);
1297 }
1298
1299 /**
1300 * Get user roles
1301 *
1302 * @return array
1303 * @since 2.1.7
1304 */
1305 public static function get_user_roles(){
1306 global $wp_roles;
1307 $all_roles = $wp_roles->roles;
1308 return array_keys($all_roles);
1309 }
1310
1311
1312 /**
1313 * Get the saved builder type
1314 *
1315 * @return mixed|void
1316 * @since 1.0.0
1317 */
1318 public static function get_builder_type()
1319 {
1320 $general_settings = self::get_general_settings();
1321 return $general_settings['builder'];
1322 }
1323
1324
1325 /**
1326 * Check if wc is installed
1327 *
1328 * @return bool
1329 * @since 1.0.0
1330 */
1331 public static function is_wc_active()
1332 {
1333 if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) {
1334 return true;
1335 }elseif( function_exists('is_plugin_active') ){
1336 if( is_plugin_active( 'woocommerce/woocommerce.php' )){
1337 return true;
1338 }
1339 }
1340 return false;
1341 }
1342
1343
1344 /**
1345 * Check if elementor is installed
1346 *
1347 * @return bool
1348 * @since 1.0.0
1349 */
1350 public static function is_elementor_active()
1351 {
1352 if (in_array('elementor/elementor.php', apply_filters('active_plugins', get_option('active_plugins')))) {
1353 return true;
1354 }elseif( function_exists('is_plugin_active') ){
1355 if( is_plugin_active( 'elementor/elementor.php' )){
1356 return true;
1357 }
1358 }
1359 return false;
1360 }
1361
1362
1363 /**
1364 * Check if saved builder is activated
1365 * or not
1366 *
1367 * @param $builder
1368 *
1369 * @return bool
1370 * @since 1.0.0
1371 */
1372 public static function is_builder_active($builder)
1373 {
1374 switch ($builder) {
1375 case 'elementor':
1376 return self::is_elementor_active();
1377 break;
1378 default:
1379 return false;
1380 break;
1381 }
1382 }
1383
1384
1385 /**
1386 * Check if the global funnel addon is activated or not
1387 *
1388 * @return bool
1389 * @since 2.0.4
1390 */
1391 public static function is_global_funnel_activated() {
1392 return apply_filters('wpfunnels/is_global_funnel_activated', false);
1393 }
1394
1395
1396 /**
1397 * Check if the funnel is global funnel
1398 *
1399 * @param $funnel_id
1400 *
1401 * @return bool
1402 */
1403 public static function is_global_funnel( $funnel_id ) {
1404 if(!$funnel_id) {
1405 return false;
1406 }
1407 return apply_filters( 'wpfunnels/is_global_funnel', false, $funnel_id );
1408 }
1409
1410
1411 /**
1412 * Check if pro is activated/deactivated
1413 *
1414 * @return bool
1415 * @since 1.0.0
1416 */
1417 public static function is_wpfnl_pro_activated()
1418 {
1419 return apply_filters('wpfunnels/is_wpfnl_pro_active', false) || apply_filters('is_wpfnl_pro_active', false);
1420 }
1421
1422
1423 /**
1424 * Check if pro is activated/deactivated
1425 *
1426 * @return bool
1427 * @since 1.0.0
1428 */
1429 public static function is_pro_license_activated()
1430 {
1431 return apply_filters('wpfunnels/is_pro_license_activated', false);
1432 }
1433
1434
1435 /**
1436 * Check if the module is pro or
1437 * not
1438 *
1439 * @param $module
1440 *
1441 * @return bool
1442 * @since 1.0.0
1443 */
1444 public static function is_pro_module($module)
1445 {
1446 $pro_modules = apply_filters('wpfnl_pro_modules', []);
1447 return in_array($module, $pro_modules);
1448 }
1449
1450
1451 /**
1452 * Check if the module is exists or not
1453 *
1454 * @param $module_name
1455 * @param string $type
1456 * @param bool $step
1457 * @param bool $pro
1458 *
1459 * @return bool
1460 * @since 1.0.0
1461 */
1462 public static function is_module_registered($module_name, $type = 'admin', $step = false, $pro = false)
1463 {
1464 $class_name = str_replace('-', ' ', $module_name);
1465 $class_name = str_replace(' ', '', ucwords($class_name));
1466 if ($pro) {
1467 if ($type === 'steps') {
1468 $class_name = 'WPFunnelsPro\\Admin\\Modules\\Steps\\' . $class_name . '\Module';
1469 }
1470 } else {
1471 if ($type === 'admin') {
1472 $class_name = 'WPFunnels\\Admin\\Modules\\' . $class_name . '\Module';
1473 } elseif ($type === 'steps') {
1474 $class_name = 'WPFunnels\\Admin\\Modules\\Steps\\' . $class_name . '\Module';
1475 } else {
1476 $class_name = 'WPFunnels\\Modules\\Frontend\\' . $class_name . '\Module';
1477 }
1478 }
1479 return class_exists($class_name);
1480 }
1481
1482
1483 /**
1484 * Check manager permissions on REST API.
1485 *
1486 * @param string $object Object.
1487 * @param string $context Request context.
1488 *
1489 * @return bool
1490 * @since 2.6.0
1491 */
1492 public static function wpfnl_rest_check_manager_permissions($object, $context = 'read')
1493 {
1494
1495 $objects = [
1496 'settings' => 'manage_options',
1497 'templates' => 'manage_options',
1498 'steps' => 'manage_options',
1499 'products' => 'manage_options',
1500 ];
1501 return current_user_can( $objects[$object] );
1502 }
1503
1504
1505 /**
1506 * Check if the provided plugin ($path) is installed or not
1507 *
1508 * @param $path
1509 *
1510 * @return bool
1511 * @since 2.0.0
1512 */
1513 public static function is_plugin_installed( $path )
1514 {
1515 $plugins = get_plugins();
1516 return isset($plugins[$path]);
1517 }
1518
1519
1520
1521 /**
1522 * Check if the provided plugin ($path) is installed or not
1523 *
1524 * @param $path
1525 *
1526 * @return bool
1527 * @since 2.0.0
1528 */
1529 public static function is_plugin_activated( $path )
1530 {
1531 include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
1532 if(is_plugin_active( $path)) {
1533 return true;
1534 }
1535 return false;
1536 }
1537
1538
1539
1540 /**
1541 * Check plugin status by path
1542 *
1543 * @param $path
1544 * @param $slug
1545 *
1546 * @return string
1547 *
1548 * @since 2.0.1
1549 */
1550 public static function get_plugin_action($path, $slug)
1551 {
1552 if( 'divi-builder' === $slug ){
1553 $is_divi_theme_active = self::wpfnl_is_theme_active( 'Divi' );
1554 if( $is_divi_theme_active ){
1555 return 'nothing';
1556 }
1557 }
1558
1559 if (null == self::$installed_plugins) {
1560 self::$installed_plugins = get_plugins();
1561 }
1562
1563 if (!isset(self::$installed_plugins[$path])) {
1564 return 'install';
1565 } elseif (!is_plugin_active($path)) {
1566 return 'activate';
1567 } else {
1568 return 'nothing';
1569 }
1570 }
1571
1572 /**
1573 * Check theme is active or not
1574 *
1575 * @param $theme_name
1576 *
1577 * @return Bool
1578 */
1579 public static function wpfnl_is_theme_active( $theme_name ){
1580 $theme = wp_get_theme(); // gets the current theme
1581 if ( $theme_name == $theme->name || $theme_name == $theme->parent_theme ) {
1582 return true;
1583 }
1584 return false;
1585 }
1586
1587
1588 /**
1589 * Check plugin is installed or not
1590 *
1591 * @param $plugin_slug
1592 *
1593 * @return Bolean
1594 */
1595 public static function wpfnl_check_is_plugin_installed( $plugin ){
1596 $installed_plugins = get_plugins();
1597 return array_key_exists( $plugin, $installed_plugins ) || in_array( $plugin, $installed_plugins, true );
1598 }
1599
1600
1601 /**
1602 * Get depenedency plugins status
1603 *
1604 * @return mixed|void
1605 *
1606 * @since 2.0.1
1607 */
1608 public static function get_dependency_plugins_status()
1609 {
1610 return apply_filters('wpfunnels/dependency_plugin_list', array(
1611 'elementor' => array(
1612 'name' => 'Elementor',
1613 'plugin_file' => 'elementor/elementor.php',
1614 'slug' => 'elementor',
1615 'action' => self::get_plugin_action('elementor/elementor.php', 'elementor')
1616 ),
1617 'gutenberg' => array(
1618 'name' => 'Qubely',
1619 'plugin_file' => 'qubely/qubely.php',
1620 'slug' => 'qubely',
1621 'action' => self::get_plugin_action('qubely/qubely.php', 'qubely')
1622 ),
1623 'divi-builder' => array(
1624 'name' => 'Divi',
1625 'plugin_file' => 'divi-builder/divi-builder.php',
1626 'slug' => 'divi-builder',
1627 'action' => self::get_plugin_action('divi-builder/divi-builder.php', 'divi-builder')
1628 ),
1629 'oxygen' => array(
1630 'name' => 'Oxygen',
1631 'plugin_file' => 'oxygen/functions.php',
1632 'slug' => 'oxygen',
1633 'action' => self::get_plugin_action('oxygen/functions.php', 'oxygen')
1634 )
1635 ));
1636 }
1637
1638
1639 /**
1640 * Is there any missing plugin for wpfunnels
1641 *
1642 * @return string
1643 *
1644 * @since 2.0.1
1645 */
1646 public static function is_any_plugin_missing()
1647 {
1648 if (null == self::$installed_plugins) {
1649 self::$installed_plugins = get_plugins();
1650 }
1651 $builder = self::get_builder_type();
1652 $dependency_plugins = self::get_dependency_plugins_status();
1653 $is_missing = 'no';
1654
1655 if (isset($dependency_plugins[$builder])) {
1656
1657 $plugin_data = $dependency_plugins[$builder];
1658 if ($plugin_data['action'] === 'activate' || $plugin_data['action'] === 'install') {
1659 $is_missing = 'yes';
1660 }
1661 }
1662 return $is_missing;
1663 }
1664
1665
1666 /**
1667 * Recursively traverses a multidimensional array in search of a specific value and returns the
1668 * array containing the value, or an
1669 * null on failure.
1670 *
1671 * @param $search_value
1672 * @param $array
1673 *
1674 * @return array
1675 * @since 2.0.0
1676 */
1677 public static function recursive_multidimensional_ob_array_search_by_value($search_value, $array, $keys = array())
1678 {
1679 if (is_array($array) && count($array) > 0) {
1680 foreach ($array as $key => $value) {
1681 $temp_keys = $keys;
1682
1683 // Adding current key to search path
1684 array_push($temp_keys, $key);
1685
1686 // Check if this value is an array
1687 // with atleast one element
1688 if (is_array($value) && count($value) > 0) {
1689 $widget_type = isset($value['widgetType']) ? $value['widgetType'] : false;
1690 if ($widget_type) {
1691 if ($widget_type === $search_value) {
1692 $value['path'] = $temp_keys;
1693 return $value;
1694 } else {
1695 $res_path = self::recursive_multidimensional_ob_array_search_by_value(
1696 $search_value, $value['elements'], $temp_keys);
1697 }
1698 if ($res_path != null) {
1699 return $res_path;
1700 }
1701 } else {
1702 $res_path = self::recursive_multidimensional_ob_array_search_by_value(
1703 $search_value, $value['elements'], $temp_keys);
1704 }
1705 if ($res_path != null) {
1706 return $res_path;
1707 }
1708 }
1709 }
1710 }
1711
1712 return null;
1713 }
1714
1715
1716 /**
1717 * Check if checkout ajax or not
1718 *
1719 * @return bool
1720 */
1721 public static function is_checkout_ajax() {
1722 if ( wp_doing_ajax() || isset( $_GET['wc-ajax'] ) ) {
1723 if ( isset( $_GET['wc-ajax'] ) && //phpcs:ignore
1724 isset( $_POST['_wcf_checkout_id'] ) //phpcs:ignore
1725 ) {
1726 return true;
1727 }
1728 }
1729
1730 return false;
1731 }
1732
1733
1734 /**
1735 * Calculate discount price
1736 *
1737 * @param $discount_type
1738 * @param $discount_value
1739 * @param $product_price
1740 *
1741 * @deprecated deprecated since 2.7.6
1742 *
1743 * @return string
1744 */
1745 public static function calculate_discount_price( $discount_type, $discount_value, $product_price ) {
1746
1747 $custom_price = $product_price;
1748 if (!empty($discount_type)) {
1749 if ('discount-percentage' === $discount_type) {
1750 if ( $discount_value > 0 && $discount_value <= 100) {
1751 $custom_price = $product_price - (($product_price * $discount_value) / 100);
1752 $custom_price = number_format((float)$custom_price,2, '.', '');
1753 }
1754 } elseif ('discount-price' === $discount_type) {
1755 if ($discount_value > 0) {
1756 $custom_price = $product_price - $discount_value;
1757 }
1758 }
1759 }
1760 return $custom_price;
1761 }
1762
1763
1764 /**
1765 * Calculate discount price
1766 *
1767 * @param $discount_type
1768 * @param $discount_value
1769 * @param $product_price
1770 *
1771 * @return string
1772 */
1773 public static function calculate_discount_amount( $discount_type, $discount_value, $product_price ) {
1774
1775 if ( $discount_type !== 'original' && !empty($discount_type) ) {
1776 $discount = '';
1777 if ('discount-percentage' === $discount_type) {
1778 if ( $discount_value > 0 && $discount_value <= 100) {
1779 $discount = (($product_price * $discount_value) / 100);
1780 }
1781 } elseif ('discount-price' === $discount_type) {
1782 if ($discount_value > 0) {
1783 $discount = $discount_value;
1784
1785 }
1786 }
1787 return number_format($discount, 2);
1788 }
1789
1790 return false;
1791 }
1792
1793
1794 /**
1795 * Get attributes for wpfunnels body wrapper
1796 *
1797 * @param string $template
1798 *
1799 * @return string
1800 */
1801 public static function get_template_container_atts( $template = '' ) {
1802 $attributes = apply_filters( 'wpfunnels/page_container_atts', array() );
1803 $atts_string = '';
1804 foreach ( $attributes as $key => $value ) {
1805 if ( ! $value ) {
1806 continue;
1807 }
1808 if ( true === $value ) {
1809 $atts_string .= esc_html( $key ) . ' ';
1810 } else {
1811 $atts_string .= sprintf( '%s="%s" ', esc_html( $key ), esc_attr( $value ) );
1812 }
1813 }
1814 return $atts_string;
1815 }
1816
1817
1818 /**
1819 * Get funnel link
1820 *
1821 * @param $funnel_id
1822 *
1823 * @return Mix
1824 */
1825 public static function get_funnel_link( $funnel_id ) {
1826 if(!$funnel_id) {
1827 return;
1828 }
1829 $steps = self::get_steps($funnel_id);
1830 if( $steps && is_array($steps) ) {
1831 $first_step = reset($steps);
1832 $first_step_id = $first_step['id'];
1833 return get_the_permalink($first_step_id);
1834 }
1835 return home_url();
1836 }
1837
1838
1839 /**
1840 * Get wc fragment
1841 *
1842 * @param array $data
1843 *
1844 * @return array
1845 */
1846 public static function get_wc_fragments( $data = array() ) {
1847 ob_start();
1848 woocommerce_order_review();
1849 $woocommerce_order_review = ob_get_clean();
1850
1851 ob_start();
1852 woocommerce_checkout_payment();
1853 $woocommerce_checkout_payment = ob_get_clean();
1854
1855 $response = array(
1856 'cart_total' => WC()->cart->total,
1857 'wc_custom_fragments' => 'yes',
1858 'fragments' => apply_filters(
1859 'woocommerce_update_order_review_fragments',
1860 array(
1861 '.woocommerce-checkout-review-order-table' => $woocommerce_order_review,
1862 /*'.woocommerce-checkout-payment' => $woocommerce_checkout_payment,*/
1863 )
1864 ),
1865 );
1866
1867 if( !empty( $data ) ) {
1868 $response[ 'wpfunnels_data' ] = $data;
1869 }
1870
1871 return $response;
1872 }
1873
1874
1875 /**
1876 * Get supported builders
1877 *
1878 * @return array
1879 */
1880 public static function get_supported_builders() {
1881 $builders = array(
1882 'elementor' => 'Elementor',
1883 'gutenberg' => 'Gutenberg',
1884 'divi-builder' => 'Divi builder',
1885 'oxygen' => 'Oxygen',
1886 );
1887 return apply_filters( 'wpfunnels/supported_builders', $builders );
1888 }
1889
1890 /**
1891 * Get custom url instead of deafult tahnkyou page
1892 *
1893 * @param mixed $step_id
1894 *
1895 * @return [type]
1896 */
1897 public static function custom_url_for_thankyou_page( $step_id ){
1898
1899 $isThankyou = self::check_if_this_is_step_type_by_id($step_id, 'thankyou');
1900 $isCustomUrl = get_post_meta( $step_id, '_wpfnl_thankyou_is_custom_redirect', true );
1901 $isDirect = get_post_meta( $step_id, '_wpfnl_thankyou_is_direct_redirect', true );
1902
1903 if( $isThankyou && $isCustomUrl === 'on' ){
1904 $url = get_post_meta( $step_id, '_wpfnl_thankyou_custom_redirect_url', true );
1905 if( $url ){
1906
1907 if( $isDirect === 'off' ){
1908 $redirectAfterSec = get_post_meta( $step_id, '_wpfnl_thankyou_set_time', true ) ? get_post_meta( $step_id, '_wpfnl_thankyou_set_time', true ) : 5;
1909 header( "refresh:".$redirectAfterSec.";url=".$url );
1910 }else{
1911 //unsell 'wpfunnels_automation_data' cookie and trigger 'wpfunnels/trigger_automation' hook
1912 self::unset_site_cookie( $step_id, 'wpfunnels_automation_data', 'wpfunnels/trigger_automation' );
1913 return $url;
1914 }
1915 }
1916 return false;
1917 }
1918 return false;
1919 }
1920
1921 /**
1922 * Check product has perfect variation or not
1923 *
1924 * @param $variation_id
1925 *
1926 * @return Boolean
1927 */
1928 public static function is_perfect_variations( $variation_id ){
1929
1930 $blank_attr = [];
1931 $response = array(
1932 'status' => true,
1933 'data' => [],
1934 );
1935 $product = wc_get_product( $variation_id );
1936 if( $product ){
1937 $parent_id = $product->get_parent_id();
1938 $_product = wc_get_product( $parent_id );
1939 if( $_product ){
1940 $attrs = self::get_product_attr( $_product );
1941 $attributes = $product->get_attributes();
1942 if( !empty( $attributes) ){
1943 foreach($attributes as $attribute_key=>$attribute_value){
1944
1945 if( !$attribute_value ){
1946 $blank_attr[$attribute_key] = $attrs[$attribute_key];
1947 $response['status'] = false;
1948 }
1949 }
1950 }
1951 }
1952
1953 }
1954 $response['data'] = $blank_attr;
1955 return $response;
1956 }
1957
1958
1959 /**
1960 * Get attributes of product
1961 *
1962 * @param Object $produt
1963 */
1964 public static function get_product_attr( $product ){
1965 $attributes = $product->get_attributes();
1966 $attr_array = [];
1967 foreach($attributes as $attribute_key=>$attribute_value){
1968
1969 $attribute_name = str_replace( 'attribute_', '', $attribute_key );
1970 $attr_value = $product->get_attribute( $attribute_name );
1971 $attr_value = strtolower($attr_value);
1972
1973 if (strpos($attr_value, '|')) {
1974 $attr_array[$attribute_key] = explode("|",$attr_value);
1975 }else{
1976 $attr_array[$attribute_key] = explode(",",$attr_value);
1977 }
1978 }
1979 return $attr_array;
1980
1981 }
1982
1983
1984
1985 /**
1986 * Remove site cookie
1987 *
1988 * @param $step_id, $cookie_name, $trigger_hook, $funnel_id
1989 */
1990 public static function unset_site_cookie( $step_id, $cookie_name, $trigger_hook = '', $funnel_id = '' ){
1991
1992 if( !$funnel_id ){
1993 $funnel_id = self::get_funnel_id_from_step( $step_id );
1994 }
1995
1996 if( !$funnel_id ){
1997 return false;
1998 }
1999
2000 $cookie = isset( $_COOKIE[$cookie_name] ) ? json_decode( wp_unslash( $_COOKIE[$cookie_name] ), true ) : array();
2001 if(!isset($cookie['funnel_id'])) {
2002 $cookie['funnel_id'] = $funnel_id;
2003 }
2004 $cookie['funnel_status'] = 'successful';
2005
2006 if(isset( $_COOKIE[$cookie_name] )){
2007 if( $trigger_hook ){
2008 do_action( $trigger_hook, $cookie );
2009 }
2010 }
2011 // unset cookie
2012 ob_start();
2013 if( isset( $_COOKIE[$cookie_name] ) ){
2014 setcookie( $cookie_name, null, strtotime( '-1 days' ), '/', COOKIE_DOMAIN );
2015 }
2016 ob_end_flush();
2017 }
2018
2019
2020 /**
2021 * Get formated product name
2022 *
2023 * @param Object $product
2024 *
2025 * @return String
2026 */
2027 public static function get_formated_product_name( $product, $formatted_attr = [] ){
2028 $_product = wc_get_product( $product );
2029 $each_child_attr = [];
2030 $_title = '';
2031 if( $_product ){
2032 if( !$formatted_attr ){
2033 if( 'variable' === $_product->get_type() || 'variation' === $_product->get_type() || 'subscription_variation' === $_product->get_type() || 'variable-subscription' === $_product->get_type() ){
2034 $attr_summary = $_product->get_attribute_summary();
2035 $attr_array = explode( ",", $attr_summary );
2036
2037 foreach ( $attr_array as $ata ) {
2038 $attr = strpbrk( $ata, ":" );
2039 $each_child_attr[] = $attr;
2040 }
2041 }
2042
2043 }else{
2044 foreach ( $formatted_attr as $attr ) {
2045 $each_child_attr[] = ucfirst($attr);
2046 }
2047 }
2048 if( $each_child_attr ){
2049 $each_child_attr_two = [];
2050 foreach ( $each_child_attr as $eca ) {
2051 $each_child_attr_two[] = str_replace( ": ", " ", $eca );
2052 }
2053 $_title = $_product->get_title() . " - ";
2054 $_title = $_title . implode( ', ', $each_child_attr_two );
2055 }else{
2056 $_title = $_product->get_title();
2057 }
2058 }
2059
2060 return $_title;
2061 }
2062
2063
2064 /**
2065 * Get page builder of a specific funnel by step Id from postmeta
2066 *
2067 * @param $funnel_id
2068 *
2069 * @return String $builder_name
2070 *
2071 * @since 2.0.5
2072 */
2073 public static function get_page_builder_by_step_id( $funnel_id ){
2074 $steps = self::get_steps( $funnel_id );
2075 $builder_name = '';
2076 if( isset($steps[0]) ){
2077 $first_step_id = $steps[0]['id'];
2078 // check builder is elementor or not
2079 $elementor_page = get_post_meta( $first_step_id, '_elementor_edit_mode', true );
2080
2081 // check builder is divi or not
2082 $divi_page = get_post_meta( $first_step_id, '_et_pb_use_builder', true );
2083
2084 //check Oxygen builder is not
2085 $oxygen_page = get_post_meta($first_step_id, 'ct_builder_shortcodes',true);
2086
2087 if( $elementor_page ) {
2088 $builder_name = 'elementor';
2089 } elseif( 'on' === $divi_page ){
2090 $builder_name = 'divi-builder';
2091 } elseif (!empty($oxygen_page)){
2092 $builder_name = 'oxygen';
2093 } else {
2094 $builder_name = 'gutenberg';
2095 }
2096 if( $builder_name ){
2097 return $builder_name;
2098 }
2099 }
2100 return $builder_name;
2101 }
2102
2103
2104 /**
2105 * Get checkout section heading settings
2106 */
2107 public static function get_checkout_section_heading_settings( $type = '' , $step_id = '' ){
2108
2109 if( self::is_pro_license_activated() ){
2110 if( $step_id ){
2111 $get_settings = get_post_meta( $step_id, '_wpfunnels_edit_field_additional_settings', true );
2112 if( !empty($get_settings) ){
2113 if( $type === 'billing' ){
2114
2115 $settings = array(
2116 'custom_heading' => $get_settings['custom_billing_heading'],
2117 );
2118 return $settings;
2119 }
2120 if( $type === 'shipping' ){
2121 $settings = array(
2122 'custom_heading' => $get_settings['custom_shipping_heading'],
2123 );
2124 return $settings;
2125 }
2126
2127 if( $type === 'order' ){
2128 $settings = array(
2129 'custom_heading' => $get_settings['custom_order_detail_heading'],
2130 );
2131 return $settings;
2132 }
2133 }
2134
2135 }
2136 }
2137 return false;
2138 }
2139
2140 /**
2141 * Check webhook addon activated or not
2142 *
2143 * @return Boolean
2144 */
2145 public static function is_webhook_activated(){
2146 if( is_plugin_active( 'wpfunnels-pro-webhook/wpfunnels-pro-webhook.php' )){
2147 return true;
2148 }
2149 return false;
2150 }
2151
2152
2153 /**
2154 * Check webhook addon license activated or not
2155 *
2156 * @return Boolean
2157 */
2158 public static function is_webhook_license_activated(){
2159
2160 if( is_plugin_active( 'wpfunnels-pro/wpfnl-pro.php' )){
2161 return true;
2162 }
2163 return false;
2164 }
2165
2166
2167 /**
2168 * Get gbf supported addons
2169 */
2170 public static function get_supported_addons(){
2171
2172 $addons = array(
2173 'global_funnel' => array(
2174 'features' => array(
2175 'trigger_options' => array(
2176 '' => __('Please select type..', 'wpfnl'),
2177 'category' => __('Product category is ..', 'wpfnl'),
2178 'product' => __('Product is ..', 'wpfnl'),
2179 )
2180 )
2181 ),
2182 );
2183
2184 if( defined( 'WPFNL_PRO_GB_VERSION') && version_compare( WPFNL_PRO_GB_VERSION, '1.0.7', '>=') ){
2185 $addons['global_funnel']['features']['trigger_options']['all_product'] = __('Any product is selected', 'wpfnl');
2186 }
2187 return apply_filters( 'wpfunnels/supported-addons', $addons );
2188 }
2189
2190 /**
2191 * Get supported GBF offer condition
2192 */
2193 public static function get_supported_gbf_offer_condition(){
2194 $conditions = [
2195 'specificProduct' => 'Specific Product'
2196 ];
2197 return apply_filters( 'wpfunnels/supported-gbf-offer-condition', $conditions );
2198 }
2199
2200
2201 /**
2202 * Get product categories for GBF offer condition
2203 */
2204 public static function get_categories_gbf_offer_condition(){
2205 $categories = array();
2206 if( self::is_wc_active() ){
2207 $orderby = 'name';
2208 $order = 'asc';
2209 $hide_empty = false ;
2210 $cat_args = array(
2211 'orderby' => $orderby,
2212 'order' => $order,
2213 'hide_empty' => $hide_empty,
2214 );
2215 $product_categories = get_terms( 'product_cat', $cat_args );
2216 if( !empty($product_categories) ){
2217 foreach($product_categories as $category){
2218 $categories[$category->slug] = $category->name;
2219 }
2220 }
2221 }
2222 return $categories;
2223 }
2224
2225
2226 public static function oxygen_builder_version_capability(){
2227 if (defined("CT_VERSION") && version_compare(CT_VERSION,'3.2','>=')){
2228 return true;
2229 }
2230 return false;
2231 }
2232
2233 public static function get_funnel_utm_settings( $funnel_id = null ){
2234 if( $funnel_id ){
2235 $default_enable_settings = array(
2236 'utm_enable' => 'off',
2237 'utm_source' => '',
2238 'utm_medium' => '',
2239 'utm_campaign' => '',
2240 'utm_content' => '',
2241 );
2242
2243 $utm_settings = get_post_meta( $funnel_id, '_wpfunnels_utm_params', true );
2244 return wp_parse_args($utm_settings, $default_enable_settings);
2245 }
2246 return false;
2247 }
2248
2249 public static function get_funnel_settings( $funnel_id = null ){
2250
2251 if( $funnel_id ){
2252
2253 $utm_settings = self::get_funnel_utm_settings( $funnel_id );
2254 $is_fb_pixel = get_post_meta( $funnel_id, '_wpfunnels_disabled_fb_pixel', true ) ? get_post_meta( $funnel_id, '_wpfunnels_disabled_fb_pixel', true ) : 'no';
2255 $is_gtm = get_post_meta( $funnel_id, '_wpfunnels_disabled_gtm', true ) ? get_post_meta( $funnel_id, '_wpfunnels_disabled_gtm', true ) : 'no';
2256
2257 return [
2258 'utm_settings' => $utm_settings,
2259 'is_fb_pixel' => $is_fb_pixel,
2260 'is_gtm' => $is_gtm,
2261 ];
2262 }
2263 return false;
2264
2265 }
2266
2267
2268 /**
2269 * Check discount is applicable or not in checkout page
2270 */
2271 public static function discount_on_checkout( $step_id = null ){
2272 if( $step_id ){
2273 $discount = get_post_meta( $step_id, '_wpfnl_checkout_discount_main_product', true );
2274 if( $discount ){
2275 return $discount;
2276 }
2277 }
2278 return false;
2279 }
2280
2281
2282 /**
2283 * Calculate main product total amount in checkout page
2284 *
2285 * @param Array $checkout_product
2286 * @param Object $cart_content
2287 * @param String $step_id
2288 *
2289 * @return Mix
2290 */
2291 public static function calculate_main_product_total( $checkout_product = null , $cart_content = null, $step_id = '' ){
2292
2293 if( $checkout_product && $cart_content ){
2294 $total = 0;
2295
2296 foreach( $cart_content as $key=>$content ){
2297 if( isset($content['wpfnl_order_bump']) && $content['wpfnl_order_bump'] ){
2298 continue;
2299 }
2300 $product_id = '';
2301 if( !empty($content['variation_id']) ){
2302 $product_id = $content['variation_id'];
2303 }
2304
2305 if( !$product_id ){
2306 $product_id = isset($content['product_id']) ? $content['product_id'] : '';
2307 }
2308
2309 $checkout_product = maybe_unserialize( $checkout_product );
2310 $key = array_search($product_id, array_column($checkout_product, 'id'));
2311 if( $key !== false ){
2312 if (wc_tax_enabled()) {
2313 if ( !wc_prices_include_tax() ) {
2314 $content['line_total'] = number_format($content['line_total'], 2);
2315 $content['line_total'] = filter_var($content['line_total'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
2316 $total = $total + $content['line_total'];
2317 }else{
2318
2319 $content['line_total'] = number_format($content['line_total'], 2);
2320 $content['line_total'] = filter_var($content['line_total'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
2321 $total = $total + $content['line_total'] + $content['line_tax'];
2322
2323 }
2324 }else{
2325 $content['line_total'] = number_format($content['line_total'], 2);
2326 $content['line_total'] = filter_var($content['line_total'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
2327 $total = $total + $content['line_total'] + $content['line_tax'];
2328 }
2329 }
2330 }
2331
2332 $total = number_format($total, 2);
2333 $total = filter_var($total, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
2334 return $total;
2335 }
2336 return false;
2337 }
2338
2339
2340
2341 /**
2342 * Calculate cart total amount in checkout page
2343 *
2344 * @param Array $checkout_product
2345 * @param Object $cart_content
2346 * @param String $step_id
2347 *
2348 * @return bool|int|float
2349 */
2350 public static function calculate_cart_total( $checkout_product = null , $cart_content = null, $step_id = '' ){
2351
2352 if( $checkout_product && $cart_content ){
2353 $total = 0;
2354
2355 foreach( $cart_content as $key=>$content ){
2356 $product_id = $content['variation_id'] ? $content['variation_id'] : $content['product_id'];
2357
2358 if (wc_tax_enabled()) {
2359 if ( !wc_prices_include_tax() ) {
2360 $content['line_total'] = number_format($content['line_total'], 2);
2361 $content['line_total'] = filter_var($content['line_total'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
2362 $total = $total + $content['line_total'];
2363 }else{
2364 $content['line_total'] = number_format($content['line_total'], 2);
2365 $content['line_total'] = filter_var($content['line_total'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
2366 $total = $total + $content['line_total'] + $content['line_tax'];
2367
2368 }
2369 }else{
2370 $content['line_total'] = number_format($content['line_total'], 2);
2371 $content['line_total'] = filter_var($content['line_total'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
2372 $total = $total + $content['line_total'] + $content['line_tax'];
2373
2374 }
2375 }
2376 $total = number_format($total, 2);
2377 $total = filter_var($total, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
2378 return $total;
2379 }
2380 return false;
2381 }
2382
2383
2384
2385 /**
2386 * Check array type ( multi-dimentional or one dimentional )
2387 *
2388 * @param Array
2389 *
2390 * @return Bool
2391 */
2392 public static function check_array_is_multidimentional( $multi_array = null ){
2393
2394 if( $multi_array ){
2395 foreach($multi_array as $array){
2396 if(is_array($array)){
2397 return true;
2398 }else{
2399 return false;
2400 }
2401 }
2402 return true;
2403 }
2404 return false;
2405 }
2406
2407
2408 /**
2409 * Migrate old Order bump settings with multiple order bump
2410 */
2411 public static function migrate_order_bump( $prev_settings = null, $step_id = null ){
2412 if( $prev_settings && $step_id ){
2413 $multi_settings = array();
2414 if( !self::check_array_is_multidimentional( $prev_settings ) ){
2415 $multi_settings = array(
2416 $prev_settings
2417 );
2418 update_post_meta( $step_id, 'order-bump-settings', $multi_settings);
2419 return $multi_settings;
2420 }
2421 }
2422 return false;
2423 }
2424
2425
2426 /**
2427 * N:B test case should be implemented
2428 * Get order bump settings by step id
2429 */
2430 public static function get_ob_settings( $step_id ){
2431
2432 $all_settings = get_post_meta($step_id, 'order-bump-settings', true) ? get_post_meta($step_id, 'order-bump-settings', true) : array();
2433 $is_multiple = self::check_array_is_multidimentional( $all_settings );
2434
2435 if( !$is_multiple && $all_settings ){
2436 $all_settings['name'] = 'Order bump';
2437 $all_settings = self::migrate_order_bump( $all_settings , $step_id );
2438 }
2439
2440 if( is_array( $all_settings ) && count($all_settings) > 0 ) {
2441 foreach( $all_settings as $key=>$settings ){
2442 if( !isset($all_settings[$key]['discountOption']) && 'original' !== $all_settings[$key]['discountOption'] ) {
2443 $product = wc_get_product( $all_settings[$key]['product'] );
2444 if( $product ){
2445 if( $product->is_on_sale() ) {
2446 $price = wc_format_sale_price( $product->get_regular_price() * $all_settings[$key]['quantity'], $product->get_sale_price() ? $product->get_sale_price() * $all_settings[$key]['quantity'] : $product->get_regular_price() * $all_settings[$key]['quantity']);
2447 } else {
2448 $price = $product->get_regular_price();
2449 if( is_plugin_active( 'woocommerce-subscriptions/woocommerce-subscriptions.php' ) ){
2450 $signUpFee = \WC_Subscriptions_Product::get_sign_up_fee( $product );
2451 $price = $price + $signUpFee;
2452 }
2453 $price = wc_price( $price * $all_settings[$key]['quantity'] );
2454 }
2455 $all_settings[$key]['htmlPrice'] = $price ? $price : $all_settings[$key]['htmlPrice'];
2456 }
2457 }
2458 }
2459 return $all_settings;
2460 }
2461
2462 return [];
2463 }
2464
2465
2466 /**
2467 * Check if funnel canvas or not
2468 *
2469 * @return bool
2470 * @since 2.3.8
2471 */
2472 public static function is_funnel_canvas_window() {
2473 if( is_admin() && isset( $_GET['page'] ) && 'edit_funnel' === $_GET['page'] ) {
2474 return true;
2475 }
2476 return false;
2477 }
2478
2479
2480 /**
2481 * Get all funnel from post
2482 *
2483 * @return $funnels
2484 * @since 2.4.4
2485 */
2486 public static function get_all_funnels( $status = 'publish' ){
2487
2488 if( 'all' == $status ){
2489 $arg = [
2490 'post_type' => WPFNL_FUNNELS_POST_TYPE,
2491 'fields' => 'ID',
2492 "orderby" => "date",
2493 "order" => 'ASC',
2494 'numberposts' => -1
2495 ];
2496 }else{
2497 $arg = [
2498 'post_type' => WPFNL_FUNNELS_POST_TYPE,
2499 'post_status' => $status,
2500 'fields' => 'ID',
2501 "orderby" => "date",
2502 "order" => 'ASC',
2503 'numberposts' => -1
2504 ];
2505 }
2506
2507 $funnels = get_posts( $arg );
2508 return $funnels;
2509 }
2510
2511
2512 /**
2513 * Get all funnel from post
2514 *
2515 * @return $funnels
2516 * @since 2.4.4
2517 */
2518 public static function get_all_steps(){
2519
2520 $steps = get_posts(
2521 array(
2522 'post_type' => 'wpfunnel_steps',
2523 'post_status' => 'publish',
2524 'fields' => 'ID',
2525 "orderby" => "date",
2526 "order" => 'ASC',
2527 )
2528 );
2529 return $steps;
2530 }
2531
2532
2533 /**
2534 * Add type meta for each funnel
2535 *
2536 * @since 2.4.4
2537 */
2538 public static function add_type_meta(){
2539
2540 $is_added = get_option( '_wpfnl_added_type_meta' );
2541 if( !$is_added ){
2542 update_option( '_wpfnl_added_type_meta', 'yes' );
2543 $funnels = self::get_all_funnels();
2544 foreach($funnels as $funnel){
2545 $type = get_post_meta( $funnel->ID, '_wpfnl_funnel_type', true );
2546 if( !$type ){
2547 update_post_meta( $funnel->ID, '_wpfnl_funnel_type', 'wc' );
2548 }
2549 }
2550 }
2551
2552 }
2553
2554
2555 /**
2556 * Enable lms settings
2557 *
2558 * @return Bool
2559 * @since 2.4.5
2560 */
2561 public static function is_enable_lms_settings(){
2562 $status = get_option( 'wpfunnels_pro_lms_license_status' );
2563 if( $status === 'active' ){
2564 return apply_filters('wpfunnels/is_enable_lms_settings', false);
2565 }
2566 return false;
2567 }
2568
2569 /**
2570 * Check if lms addon activated or not
2571 *
2572 * @return Bool
2573 * @since 2.4.5
2574 */
2575 public static function is_lms_addon_active(){
2576
2577 if (in_array('wpfunnels-pro-lms/wpfunnels-pro-lms.php', apply_filters('active_plugins', get_option('active_plugins')))) {
2578 return true;
2579 }elseif( function_exists('is_plugin_active') ){
2580 if( is_plugin_active( 'wpfunnels-pro-lms/wpfunnels-pro-lms.php' ) ){
2581 return true;
2582 }
2583 }
2584 return false;
2585 }
2586
2587
2588 /**
2589 * Get checkout tabs column name
2590 *
2591 * @return Array
2592 * @since 2.4.5
2593 */
2594 public static function get_checkout_columns( $step_id ){
2595
2596 $funnel_id = get_post_meta( $step_id, '_funnel_id', true );
2597 $columns = [
2598 'product-name' => 'Product',
2599 'product-price' => 'Unit Price',
2600 'calculate-operator' => '',
2601 'product-quantity' => 'Quantity',
2602 'total-price' => 'Total Price',
2603 'product-action' => 'Actions',
2604 ];
2605
2606 return apply_filters('wpfunnels/checkout_columns', $columns, $funnel_id);
2607 }
2608
2609
2610 /**
2611 * Supported order bump position
2612 *
2613 * @return Array
2614 * @since 2.4.5
2615 */
2616 public static function supported_orderbump_position( $step_id ){
2617 $funnel_id = get_post_meta( $step_id, '_funnel_id', true );
2618
2619 $positions = [
2620 [
2621 'name' => 'Before Order Details',
2622 'value' => 'before-order',
2623 ],
2624 [
2625 'name' => 'After Order Details',
2626 'value' => 'after-order',
2627 ],
2628 [
2629 'name' => 'Before Checkout Details',
2630 'value' => 'before-checkout',
2631 ],
2632 [
2633 'name' => 'After Customer Details',
2634 'value' => 'after-customer-details',
2635 ],
2636 [
2637 'name' => 'Before Payment Options',
2638 'value' => 'before-payment',
2639 ],
2640 [
2641 'name' => 'After Payment Options',
2642 'value' => 'after-payment',
2643 ],
2644 [
2645 'name' => 'Pop-up offer',
2646 'value' => 'popup',
2647 ],
2648 ];
2649 if( $funnel_id ){
2650 return apply_filters('wpfunnels/ob_positions', $positions, $funnel_id);
2651 }
2652
2653 return $positions;
2654
2655 }
2656
2657 /**
2658 * Get time zone in string
2659 *
2660 * @return String
2661 * @since 2.4.6
2662 */
2663 public static function wpfnl_timezone_string() {
2664
2665 // If site timezone string exists, return it.
2666 $timezone = get_option( 'timezone_string' );
2667 if ( $timezone ) {
2668 return $timezone;
2669 }
2670
2671 // Get UTC offset, if it isn't set then return UTC.
2672 $utc_offset = floatval( get_option( 'gmt_offset', 0 ) );
2673 if ( ! is_numeric( $utc_offset ) || 0.0 === $utc_offset ) {
2674 return 'UTC';
2675 }
2676
2677 // Adjust UTC offset from hours to seconds.
2678 $utc_offset = (int) ( $utc_offset * 3600 );
2679
2680 // Attempt to guess the timezone string from the UTC offset.
2681 $timezone = timezone_name_from_abbr( '', $utc_offset );
2682 if ( $timezone ) {
2683 return $timezone;
2684 }
2685
2686 // Last try, guess timezone string manually.
2687 foreach ( timezone_abbreviations_list() as $abbr ) {
2688 foreach ( $abbr as $city ) {
2689 // WordPress restrict the use of date(), since it's affected by timezone settings, but in this case is just what we need to guess the correct timezone.
2690 if ( (bool) date( 'I' ) === (bool) $city['dst'] && $city['timezone_id'] && intval( $city['offset'] ) === $utc_offset ) { // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
2691 return $city['timezone_id'];
2692 }
2693 }
2694 }
2695
2696 // Fallback to UTC.
2697 return 'UTC';
2698 }
2699
2700
2701
2702 /**
2703 * Get timezone offset in seconds.
2704 *
2705 * @since 2.4.6
2706 * @return float
2707 */
2708 public static function wpfnl_timezone_offset() {
2709 $timezone = get_option( 'timezone_string' );
2710 if ( $timezone ) {
2711 $timezone_object = new DateTimeZone( $timezone );
2712 return $timezone_object->getOffset( new DateTime( 'now' ) );
2713 } else {
2714 return floatval( get_option( 'gmt_offset', 0 ) ) * HOUR_IN_SECONDS;
2715 }
2716 }
2717
2718
2719 /**
2720 * Check if integrations addon activated or not
2721 *
2722 * @return Bool
2723 * @since 2.4.7
2724 */
2725 public static function is_integrations_addon_active(){
2726 if (in_array('wpfunnels-pro-integrations/wpfunnels-pro-integrations.php', apply_filters('active_plugins', get_option('active_plugins')))) {
2727 return true;
2728 }elseif( function_exists('is_plugin_active') ){
2729 if( is_plugin_active( 'wpfunnels-pro-integrations/wpfunnels-pro-integrations.php' ) ){
2730 return true;
2731 }
2732 }
2733 return false;
2734 }
2735
2736
2737 /**
2738 * Get template types
2739 *
2740 * @return array
2741 * @since 2.4.11
2742 */
2743 public static function get_template_types() {
2744 $general_settings = Wpfnl_functions::get_general_settings();
2745 if( self::is_wc_active() ){
2746 $types = array(
2747 array(
2748 'slug' => 'wc',
2749 'label' => 'Woo Templates',
2750 ),
2751 array(
2752 'slug' => 'lead',
2753 'label' => 'Lead Gen Templates',
2754 )
2755 );
2756 }else{
2757 $types = array(
2758 array(
2759 'slug' => 'lead',
2760 'label' => 'Lead Gen Templates',
2761 )
2762 );
2763 }
2764
2765 if( isset($general_settings['funnel_type']) && 'lead' === $general_settings['funnel_type'] ) {
2766 $types = array(
2767 array(
2768 'slug' => 'lead',
2769 'label' => 'Lead Gen Templates',
2770 )
2771 );
2772 }
2773 return apply_filters( 'wpfunnels/modify_template_type', $types );
2774
2775 }
2776
2777
2778 /**
2779 * Get global funnel type
2780 *
2781 * @return Mix
2782 */
2783 public static function get_global_funnel_type(){
2784 $general_settings = self::get_general_settings();
2785 if( isset($general_settings['funnel_type']) ){
2786 return $general_settings['funnel_type'];
2787 }
2788 return false;
2789 }
2790
2791
2792 /**
2793 * May be allow to create sales funnel
2794 *
2795 * @return Bool
2796 */
2797 public static function maybe_allow_sales_funnel(){
2798 if( self::is_wc_active() || self::is_lms_addon_active() ){
2799 return true;
2800 }
2801 return false;
2802 }
2803
2804 /**
2805 * Retrieve all user role
2806 *
2807 * @return Array
2808 */
2809
2810 public static function get_all_user_roles(){
2811 global $wp_roles;
2812
2813 $all_roles = isset($wp_roles->roles) ? $wp_roles->roles : [];
2814 $editable_roles = apply_filters('editable_roles', $all_roles);
2815
2816 return $editable_roles;
2817 }
2818
2819
2820 /**
2821 * Retrive all the product tags
2822 *
2823 * @return array
2824 * @since 2.4.11
2825 */
2826 public static function get_all_tags(){
2827 $term_array = array();
2828 if( self::is_wc_active() ){
2829 $terms = get_terms( 'product_tag' );
2830 if ( ! empty( $terms ) && ! is_wp_error( $terms ) ){
2831 foreach ( $terms as $term ) {
2832
2833 $term_array[] = [
2834 'id' => isset($term->term_id) ? $term->term_id : "",
2835 'name' => isset($term->name) ? $term->name : "",
2836 ];
2837 }
2838 }
2839 }
2840 return $term_array;
2841 }
2842
2843 /**
2844 * Get all shiiping classes
2845 *
2846 * @return array
2847 * @since 2.4.10
2848 */
2849 public static function get_shipping_classes(){
2850
2851 if( self::is_wc_active() ){
2852 $shipping_classes = WC()->shipping()->get_shipping_classes();
2853 if( $shipping_classes ){
2854 return $shipping_classes;
2855 }
2856 }
2857 return [];
2858 }
2859
2860
2861 /**
2862 * Maybe global funnel
2863 *
2864 * @param String
2865 *
2866 * @return String
2867 *
2868 * @since 2.4.14
2869 */
2870 public static function maybe_global_funnel( $step_id = '' ){
2871 if( $step_id ){
2872 $funnel_id = get_post_meta($step_id, '_funnel_id', true);
2873 $is_gbf = get_post_meta( $funnel_id, 'is_global_funnel', true);
2874 if( $is_gbf ){
2875 return $is_gbf;
2876 }
2877 }
2878 return 'no';
2879 }
2880
2881
2882 /**
2883 * Get Woocommerce billing/shipping countries
2884 *
2885 * @return array
2886 * @since 2.4.18
2887 */
2888 public static function get_countries(){
2889 if( self::is_wc_active() ){
2890 $wc_countries = new \WC_Countries();
2891 $countries = $wc_countries->get_countries();
2892 if( $countries ){
2893 return $countries;
2894 }
2895 }
2896 return [];
2897 }
2898
2899
2900 /**
2901 * Check the checkout layout is express or not
2902 *
2903 * @return Bool
2904 * @since 2.4.18
2905 */
2906 public static function maybe_express_checkout( $checkout_id = ''){
2907 if( !$checkout_id ){
2908 global $post;
2909 if( !$post ){
2910 return false;
2911 }
2912 if ( wp_doing_ajax() || isset( $_GET['wc-ajax'] ) ) {
2913 $checkout_id =self::get_checkout_id_from_post($_POST);
2914 }else {
2915 $checkout_id = $post->ID;
2916 }
2917 if( !$checkout_id ){
2918 $checkout_id = get_the_ID();
2919 }
2920 }
2921
2922 $layout = get_post_meta( $checkout_id, '_wpfnl_checkout_layout' , true);
2923
2924 return 'wpfnl-express-checkout' === $layout;
2925 }
2926
2927
2928
2929 /**
2930 * Sanitize request data
2931 *
2932 * @param $data
2933 *
2934 * @return Mix
2935 */
2936 public static function get_sanitized_get_post( $data = [] )
2937 {
2938 if ( is_array( $data ) && !empty( $data ) ) {
2939 return filter_var_array( $data, FILTER_SANITIZE_FULL_SPECIAL_CHARS );
2940 }
2941 return array(
2942 'get' => filter_input_array(INPUT_GET, FILTER_SANITIZE_FULL_SPECIAL_CHARS),
2943 'post' => filter_input_array(INPUT_POST, FILTER_SANITIZE_FULL_SPECIAL_CHARS),
2944 'request' => filter_var_array( $_REQUEST, FILTER_SANITIZE_FULL_SPECIAL_CHARS),
2945 );
2946 }
2947
2948
2949
2950 /**
2951 * Update funnel type to lead
2952 *
2953 * @since 2.5.1
2954 */
2955 public static function update_funnel_type_to_lead(){
2956
2957 $saved_settings = self::get_admin_settings('_wpfunnels_general_settings');
2958 if( isset($saved_settings['funnel_type']) ){
2959 $saved_settings['funnel_type'] = 'lead';
2960 update_option( '_wpfunnels_general_settings', $saved_settings );
2961 }
2962 }
2963
2964
2965 /**
2966 * Delete template transients
2967 *
2968 * @since 2.5.1
2969 */
2970 public static function wpfnl_delete_transient(){
2971 delete_option(WPFNL_TEMPLATES_OPTION_KEY.'_wc');
2972 delete_option(WPFNL_TEMPLATES_OPTION_KEY.'_lms');
2973 delete_option(WPFNL_TEMPLATES_OPTION_KEY.'_lead');
2974
2975 delete_transient('wpfunnels_remote_template_data_wc_' . WPFNL_VERSION);
2976 delete_transient('wpfunnels_remote_template_data_lms_' . WPFNL_VERSION);
2977 delete_transient('wpfunnels_remote_template_data_lead_' . WPFNL_VERSION);
2978 }
2979
2980
2981 /**
2982 * Get all the published funnel lists
2983 *
2984 * @return Array $funnels
2985 * @since 2.5.6
2986 */
2987 public static function get_funnel_list(){
2988 $funnels = get_posts(
2989 array(
2990 'post_type' => WPFNL_FUNNELS_POST_TYPE,
2991 'post_status' => 'publish',
2992 'numberposts' => -1,
2993 'fields' => 'ID',
2994 "orderby" => "date",
2995 "order" => 'ASC',
2996 )
2997 );
2998 $formatted_funnel_data[' '] = __('Select funnel','wpfnl');
2999 if( is_array($funnels) ){
3000 foreach( $funnels as $funnel ){
3001 $is_gbf = get_post_meta( $funnel->ID, 'is_global_funnel', true );
3002 if( !$is_gbf || 'no' === $is_gbf ){
3003 $formatted_funnel_data[self::get_funnel_link( $funnel->ID )] = $funnel->post_title;
3004 }
3005 }
3006 }
3007 return $formatted_funnel_data;
3008 }
3009
3010 /**
3011 * Check the log status is enabled or not
3012 *
3013 * @return Bool
3014 * @since 2.5.9
3015 */
3016 public static function maybe_logger_enabled(){
3017 $general_settings = get_option( '_wpfunnels_general_settings' );
3018 if( $general_settings && isset($general_settings['enable_log_status']) ){
3019 return 'on' === $general_settings['enable_log_status'];
3020 }
3021 return false;
3022 }
3023
3024
3025 /**
3026 * Get supported step type
3027 * Landing, Checkout, Thankyou steps are supported for free
3028 *
3029 * @return Array $types
3030 * @since 2.5.7
3031 */
3032 public static function get_supported_step_type(){
3033 $types = [
3034 [
3035 'type' => 'landing',
3036 'name' => 'Landing',
3037 ],
3038 [
3039 'type' => 'checkout',
3040 'name' => 'Checkout',
3041 ],
3042 [
3043 'type' => 'thankyou',
3044 'name' => 'Thankyou',
3045 ],
3046 ];
3047
3048 return apply_filters( 'wpfunnels/supported_step_type', $types );
3049 }
3050
3051
3052 /**
3053 * Check user permission to allow WPFunnels
3054 *
3055 * @param Array $permitted_role
3056 *
3057 * @return String $role
3058 * @since 2.6.2
3059 */
3060 public static function role_permission_to_allow_wpfunnel( $permitted_role = [] ){
3061
3062 return 'manage_options';
3063 $user = wp_get_current_user();
3064 if( isset($user->roles) ){
3065 $roles = ( array ) $user->roles;
3066 foreach( $roles as $role ){
3067 if( isset($permitted_role['allow_funnels'][$role]) ){
3068 return $role;
3069 }
3070 }
3071 }
3072 return 'administrator';
3073 }
3074
3075
3076 /**
3077 * Check if mint crm is installed
3078 *
3079 * @return bool
3080 * @since 1.0.0
3081 */
3082 public static function is_mint_mrm_active()
3083 {
3084 return apply_filters( 'is_mail_mint_pro_active', false );
3085 }
3086
3087
3088 /**
3089 * Check if mint automation exist for a funnel by funnel id.
3090 *
3091 * @param int $funnel_id
3092 * @return bool
3093 * @since 1.0.0
3094 */
3095 public static function maybe_automation_exist_for_a_funnel( $funnel_id )
3096 {
3097 return apply_filters( 'wpfunnels/maybe_automation_exist_for_a_funnel', false, $funnel_id );
3098 }
3099
3100 /**
3101 * Supported steps for allow settings
3102 *
3103 * @return array
3104 * @since 2.6.6
3105 */
3106 public static function get_settings_steps(){
3107 $settings_steps =[
3108 'upsell',
3109 'downsell',
3110 'checkout',
3111 'thankyou',
3112 'delay',
3113 'sendMail',
3114 'createUser',
3115 'addTag',
3116 'addList',
3117 'removeTag',
3118 'removeList',
3119 'wpf_optin_submit',
3120 'wpf_order_placed',
3121 'wpf_cta_triggered',
3122 'wpf_order_bump_accepted',
3123 'wpf_offer_trigger',
3124 ];
3125
3126 return apply_filters( 'wpfunnels/supported_settings_steps', $settings_steps );
3127 }
3128
3129
3130 /**
3131 * Supported steps for allow only settings
3132 *
3133 * @return array
3134 * @since 2.6.6
3135 */
3136 public static function get_only_settings_steps(){
3137 $settings_steps =[
3138 'delay',
3139 'sendMail',
3140 'createUser',
3141 'addTag',
3142 'addList',
3143 'removeTag',
3144 'removeList',
3145 'wpf_optin_submit',
3146 'wpf_order_placed',
3147 'wpf_cta_triggered',
3148 'wpf_order_bump_accepted',
3149 'wpf_offer_trigger',
3150 ];
3151
3152 return apply_filters( 'wpfunnels/supported_only_settings_steps', $settings_steps );
3153 }
3154
3155
3156 /**
3157 *
3158 */
3159 public static function get_default_automation(){
3160 $automation_data = [
3161 'name' => 'automation-1',
3162 'status' => 'active',
3163 'author' => 1,
3164 'trigger_name' => 'wpf-offer-trigger',
3165 'steps' => [
3166 [
3167 'step_id' => 'mg3e1i',
3168 'key' => 'wp_user_login',
3169 'type' => 'trigger',
3170 'settings' => [
3171
3172 ],
3173 'next_step_id' => 'zytv4'
3174 ],
3175 [
3176 'step_id' => 'zytv4',
3177 'key' => 'createUser',
3178 'type' => 'action',
3179 'settings' => [
3180
3181 ],
3182 'next_step_id' => '9w8vjh'
3183 ],
3184 [
3185 'step_id' => '9w8vjh',
3186 'key' => 'addTag',
3187 'type' => 'action',
3188 'settings' => [
3189 'tag_settings' => [
3190 'tags' => [
3191 [
3192 'id' => 3,
3193 'title' => 'demo'
3194 ]
3195 ]
3196 ]
3197 ],
3198 'next_step_id' => ''
3199 ],
3200 ],
3201 'created_ago' => '3 seconds'
3202 ];
3203
3204 return $automation_data;
3205 }
3206
3207
3208 /**
3209 * Get mint triggers
3210 *
3211 * @return array
3212 */
3213 public static function get_mint_triggers(){
3214 $triggers = [
3215 'wpf_optin_submit',
3216 'wpf_order_placed',
3217 'wpf_cta_triggered',
3218 'wpf_order_bump_accepted',
3219 'wpf_offer_trigger',
3220 ];
3221
3222 return apply_filters( 'wpfunnels/mint_triggers', $triggers );
3223 }
3224
3225
3226 /**
3227 * Get mint actions
3228 *
3229 * @return array
3230 */
3231 public static function get_mint_actions(){
3232 $actions = [
3233 'delay',
3234 'sendMail',
3235 'createUser',
3236 'addTag',
3237 'addList',
3238 'removeTag',
3239 'removeList',
3240 ];
3241
3242 return apply_filters( 'wpfunnels/mint_actions', $actions );
3243 }
3244
3245
3246 /**
3247 * Get all tags/list from mint
3248 *
3249 * @return array
3250 */
3251 public static function get_mint_contact_groups( $type = 'tags' ){
3252 $class_name = "Mint\\MRM\\DataBase\\Models\\ContactGroupModel";
3253 if( class_exists($class_name) ){
3254
3255 $groups = $class_name::get_all_lists_or_tags($type);
3256 if( $groups && is_array($groups) ){
3257 $formatted_groups = [];
3258 $i=1;
3259 foreach( $groups as $group ){
3260 $data = [
3261 'index' => $i,
3262 'title' => $group['title'],
3263 'id' => $group['id'],
3264 'checked' => false,
3265 ];
3266 array_push( $formatted_groups, $data );
3267 $i++;
3268 }
3269
3270 return $formatted_groups;
3271 }
3272 }
3273 return [];
3274 }
3275
3276
3277 /**
3278 * Get selected steps
3279 *
3280 * @param string $type
3281 * @param int $funnel_id
3282 *
3283 * @return array
3284 */
3285 public static function get_selected_steps( $type, $funnel_id ){
3286 if( $funnel_id ){
3287 $steps = get_post_meta( $funnel_id, '_steps', true );
3288 if( $steps && is_array($steps) ){
3289 $i = 1;
3290 $formatted_steps = [];
3291 $step_types = [$type];
3292 if( 'landing' == $type ){
3293 $step_types = [ $type, 'custom' ];
3294 }
3295 foreach($steps as $step ){
3296 if( in_array($step['step_type'], $step_types) ){
3297 $data = [
3298 'id' => $i,
3299 'title' => $step['name'],
3300 'value' => $step['id'],
3301 ];
3302 array_push( $formatted_steps, $data );
3303 $i++;
3304 }
3305 }
3306
3307 return $formatted_steps;
3308 }
3309 }
3310 return [];
3311 }
3312
3313
3314 /**
3315 * Get all order bump of a funnel
3316 *
3317 * @param int $funnel_id
3318 *
3319 * @return array
3320 */
3321 public static function get_all_ob( $funnel_id ){
3322 if( $funnel_id ){
3323 $steps = self::get_steps( $funnel_id );
3324 if( $steps && is_array($steps) ){
3325 $key = array_search('checkout', array_column($steps, 'step_type'));
3326 if( false !== $key ){
3327 if( isset( $steps[$key]['id'] ) ){
3328 $checkout_step_id = $steps[$key]['id'];
3329 $order_bumps = get_post_meta( $checkout_step_id, 'order-bump-settings', true);
3330 if( $order_bumps && is_array($order_bumps) ){
3331 $i = 1;
3332 $formatted_obs = [];
3333 foreach($order_bumps as $index=>$ob ){
3334 $data = [
3335 'id' => $i,
3336 'title' => $ob['name'],
3337 'value' => $index,
3338 ];
3339 array_push( $formatted_obs, $data );
3340 $i++;
3341 }
3342 return $formatted_obs;
3343 }
3344 }
3345 }
3346 }
3347 }
3348 return [];
3349 }
3350
3351
3352 /**
3353 * Get sequences from campaign table
3354 *
3355 * @return array
3356 * @since 1.0.0
3357 */
3358 public static function get_sequences() {
3359 if( self::is_mint_mrm_active() && class_exists("Mint\\MRM\\DataBase\\Tables\\CampaignSchema") ){
3360
3361 global $wpdb;
3362 $class_name = "Mint\\MRM\\DataBase\\Tables\\CampaignSchema";
3363 $campaign_table = $wpdb->prefix . $class_name::$campaign_table;
3364 $results = $wpdb->get_results( $wpdb->prepare( "SELECT id as value, title as label FROM $campaign_table WHERE type = %s AND status = %s ", 'automation', 'created' ), ARRAY_A ); // phpcs:ignore.
3365 $default = array(
3366 array(
3367 'value' => '',
3368 'label' => 'Select Sequence',
3369 ),
3370 );
3371 if( !empty($results) ){
3372 return array_merge( $default, $results );
3373 }else{
3374 return $default;
3375 }
3376
3377 }
3378 return [];
3379 }
3380
3381
3382 /**
3383 * Get CFE deafult fields
3384 *
3385 * @return array
3386 * @since 2.7.0
3387 */
3388 public static function get_cfe_default_fields(){
3389 if( self::is_wc_active() ){
3390 $fields = [];
3391 $billing_default_field = WC()->countries->get_address_fields();
3392 foreach($billing_default_field as $key => $sf){
3393 $billing_default_field[$key]['enable'] = 1;
3394 $billing_default_field[$key]['show'] = 1;
3395 $billing_default_field[$key]['delete'] = 0;
3396 if(!(isset($sf['type']))){
3397 $billing_default_field[$key]['type'] = null;
3398 }
3399 if(!(isset($sf['placeholder']))){
3400 $billing_default_field[$key]['placeholder'] = null;
3401 }
3402 if(!(isset($sf['label']))){
3403 $billing_default_field[$key]['label'] = null;
3404 }
3405 if(!(isset($sf['validate']))){
3406 $billing_default_field[$key]['validate'] = null;
3407 }
3408 if(!(isset($sf['default']))){
3409 $billing_default_field[$key]['default'] = null;
3410 }
3411 }
3412
3413 $countries = new \WC_Countries();
3414 $shipping_default_fields = $countries->get_address_fields( $countries->get_base_country(),'shipping_');
3415 foreach($shipping_default_fields as $key => $sf){
3416 $shipping_default_fields[$key]['enable'] = 1;
3417 $shipping_default_fields[$key]['show'] = 1;
3418 $shipping_default_fields[$key]['delete'] = 0;
3419 if(!(isset($sf['type']))){
3420 $shipping_default_fields[$key]['type'] = null;
3421 }
3422 if(!(isset($sf['placeholder']))){
3423 $shipping_default_fields[$key]['placeholder'] = null;
3424 }
3425 if(!(isset($sf['label']))){
3426 $shipping_default_fields[$key]['label'] = null;
3427 }
3428 if(!(isset($sf['validate']))){
3429 $shipping_default_fields[$key]['validate'] = null;
3430 }
3431 if(!(isset($sf['default']))){
3432 $shipping_default_fields[$key]['default'] = null;
3433 }
3434 }
3435
3436 $order_comment = array(
3437 'type' => 'textarea',
3438 'class' => array( 'notes' ),
3439 'label' => __( 'Order notes', 'woocommerce' ),
3440 'placeholder' => esc_attr__(
3441 'Notes about your order, e.g. special notes for delivery.',
3442 'woocommerce'),
3443 'name' => 'order_comments',
3444 'required' => false,
3445 'enable' => 1,
3446 'show' => 1,
3447 'default' => null,
3448 'validate' => null,
3449 'delete' => 0,
3450 );
3451
3452 $additional_default_fields = array(
3453 'order_comments' => $order_comment
3454 );
3455
3456 $fields = [
3457 'billing' => $billing_default_field,
3458 'shipping' => $shipping_default_fields,
3459 'additional' => $additional_default_fields
3460 ];
3461 return $fields;
3462 }
3463 }
3464
3465 /**
3466 * Generates and updates the first step id of the funnel
3467 *
3468 * @param int|string $funnel_id Funnel id.
3469 * @since 2.8.0
3470 */
3471 public static function generate_first_step( $funnel_id, $steps = [] ) {
3472 if( $funnel_id ) {
3473 $steps = !empty( $steps ) ? $steps : get_post_meta( $funnel_id, '_steps', true ); // Get step order
3474
3475 $priority_order = [ 'landing', 'custom', 'upsell', 'downsell', 'checkout', 'thankyou' ];
3476 $first_step = [ 'id' => null, 'step_type' => '' ];
3477
3478 if( is_array( $steps ) && !empty( $steps ) ) {
3479 foreach( $steps as $step ) {
3480 if(
3481 isset( $step[ 'step_type' ], $step[ 'id' ] )
3482 && ( !$first_step[ 'id' ] || ( array_search( $step[ 'step_type' ], $priority_order ) < array_search( $first_step[ 'step_type' ], $priority_order ) ) )
3483 ) {
3484 $first_step[ 'id' ] = $step[ 'id' ];
3485 $first_step[ 'step_type' ] = $step[ 'step_type' ];
3486 }
3487 }
3488 self::update_funnel_first_step( $funnel_id, $first_step[ 'id' ] );
3489 }
3490 }
3491 }
3492
3493 /**
3494 * Get the first step of a funnel
3495 *
3496 * @param int|string $funnel_id Funnel id.
3497 * @return string|int
3498 * @since 2.8.0
3499 */
3500 public static function get_first_step( $funnel_id ) {
3501 return get_post_meta( $funnel_id, '_first_step', true );
3502 }
3503
3504 /**
3505 * Updates the first step id of the funnel
3506 *
3507 * @param int|string $funnel_id Funnel id.
3508 * @param int|string $first_step_id First step id of the funnel.
3509 * @return void
3510 */
3511 public static function update_funnel_first_step( $funnel_id, $first_step_id ) {
3512 update_post_meta( $funnel_id, '_first_step', $first_step_id );
3513 }
3514
3515
3516 /**
3517 * Mail mint email
3518 *
3519 * @return mix
3520 */
3521 public static function get_mailmint_email(){
3522 if( self::is_mint_mrm_active() ){
3523 $email_settings = get_option( '_mrm_email_settings' );
3524 if( isset( $email_settings['from_email'] ) ){
3525 return $email_settings['from_email'];
3526 }
3527 }
3528 return false;
3529 }
3530
3531
3532 /**
3533 * Maybe duplicate step
3534 *
3535 * @param $step_id Step ID
3536 *
3537 * @since 2.7.7
3538 * @return bool
3539 */
3540 public static function maybe_duplicate_step( $step_id ){
3541
3542 if( $step_id ){
3543 $is_duplicate = get_post_meta( $step_id, '_is_duplicate', true );
3544 if( 'yes' === $is_duplicate ){
3545 return true;
3546 }
3547 }
3548 return false;
3549 }
3550
3551
3552 /**
3553 * Retrieves all created coupons from WooCommerce.
3554 * This function fetches all coupon posts of the 'shop_coupon' post type that are currently published in WooCommerce.
3555 *
3556 * @since 2.7.9
3557 * @return array An array of coupon codes and their corresponding names.
3558 */
3559 public static function get_all_coupons(){
3560 global $wpdb;
3561 $table_name = $wpdb->prefix . 'posts';
3562 $coupon_type = 'shop_coupon';
3563 $post_status = 'publish';
3564 $query = $wpdb->prepare(
3565 "SELECT post_title FROM $table_name WHERE post_type = %s AND post_status = %s ORDER BY post_name ASC LIMIT 100",
3566 $coupon_type,
3567 $post_status
3568 );
3569 $coupon_codes = [];
3570 $coupons = $wpdb->get_col($query);
3571 if( is_array( $coupons ) ){
3572 foreach ( $coupons as $coupon ) {
3573 $coupon_codes[] = [
3574 'name' => $coupon,
3575 ];
3576 }
3577 }
3578 return $coupon_codes;
3579 }
3580
3581
3582 /**
3583 * Retrieves the applied coupon for a given step ID.
3584 * This function checks if a step ID is provided and retrieves the applied coupon associated with that step.
3585 * If no step ID is provided or the applied coupon is not found, it returns false.
3586 *
3587 * @param int $step_id The ID of the step for which to retrieve the applied coupon.
3588 *
3589 * @since 2.7.9
3590 * @return string|false The selected coupon code if found and auto-coupon feature is
3591 */
3592 public static function get_applied_coupon( $step_id ){
3593 if( !$step_id ){
3594 return false;
3595 }
3596 $auto_coupon = get_post_meta($step_id, '_wpfnl_checkout_auto_coupon', true);
3597 if( isset( $auto_coupon['enableAutoCoupon'], $auto_coupon['selectedCoupon'] ) && 'yes' === $auto_coupon['enableAutoCoupon'] && $auto_coupon['selectedCoupon'] ){
3598 return $auto_coupon['selectedCoupon'];
3599 }
3600 return false;
3601 }
3602
3603 /**
3604 * Get step IDs for a given funnel.
3605 *
3606 * Retrieves an array of step IDs associated with a specific funnel, including A/B testing variations.
3607 *
3608 * @param int $funnel_id The ID of the funnel.
3609 * @return array An array of step IDs.
3610 * @since 2.7.10
3611 */
3612 public static function get_step_ids( $funnel_id ){
3613 $steps = self::get_steps( $funnel_id );
3614
3615 $all_steps_including_ab = array();
3616 $all_steps_including_ab_ids = array();
3617 if ( is_array($steps) ){
3618 foreach ( $steps as $step ) {
3619 if ( isset( $step['id'] ) ){
3620 $all_steps_including_ab = get_post_meta( $step['id'], '_wpfnl_ab_testing_start_settings' ,true );
3621 $ids = array_column($all_steps_including_ab['variations'], 'id');
3622 $all_steps_including_ab_ids = array_merge($all_steps_including_ab_ids, $ids);
3623 }
3624 }
3625 }
3626
3627 return $all_steps_including_ab_ids;
3628 }
3629
3630 /**
3631 * Validates the order owner's authorization.
3632 *
3633 *
3634 * @param WC_Order $order The order object to validate.
3635 * @return bool
3636 * @since 2.7.13
3637 */
3638 public static function is_valid_order_owner( $order ){
3639
3640 if (!self::is_wc_active() || false === is_a( $order, 'WC_Order' )){
3641 return false;
3642 }
3643
3644 // If it's not a guest order, current user can pay but only if it's their own order,
3645 // or they are an admin or shop manager or they are in a same session(for guest).
3646
3647 $order_has_customer = ! empty( $order->get_customer_id() );
3648 $is_authorized_owner = false;
3649
3650 $has_owner = !empty ( WC()->session->get('wpfnl_order_owner') );
3651
3652 if ( $order_has_customer ) {
3653 $is_order_owned_by_current_user = $order->get_customer_id() === get_current_user_id();
3654
3655 $is_authorized_owner = $is_order_owned_by_current_user || current_user_can( 'manage_woocommerce' );
3656 }
3657
3658 if (!$is_authorized_owner && !$has_owner){
3659 return false;
3660 }
3661 return true;
3662 }
3663
3664 /**
3665 * Check if the current page is using the Gutenberg editor.
3666 *
3667 * This function checks whether the current page in the WordPress admin area is using the Gutenberg editor. It does so by checking the availability of a specific function associated with Gutenberg. If this function exists, it is likely that the Gutenberg editor is in use.
3668 *
3669 * @return bool True if the current page is using the Gutenberg editor, false otherwise.
3670 * @since 2.8.12
3671 */
3672 private static function is_gutenberg_edit_page() {
3673 if ( function_exists( 'wp_enqueue_script' ) && function_exists( 'wp_enqueue_style' ) ) {
3674 // Check if Gutenberg scripts and styles are enqueued
3675 return wp_script_is( 'wp-blocks' ) && wp_script_is( 'wp-element' ) && wp_style_is( 'wp-edit-blocks' );
3676 }
3677 return false;
3678 }
3679
3680 /**
3681 * Check if the current page is an Elementor edit page.
3682 *
3683 * This function checks whether the current page in the WordPress admin area is an edit page created with the Elementor page builder plugin. It does so by inspecting the 'action' query parameter in the URL. If the 'action' is set to 'elementor', it is likely an edit page created with Elementor.
3684 *
3685 * @return bool True if the current page is an Elementor edit page, false otherwise.
3686 * @since 2.8.12
3687 */
3688 private static function is_elementor_edit_page() {
3689 // Check if the 'action' query parameter is set to 'elementor'.
3690 return 'elementor' === filter_input( INPUT_GET, 'action', FILTER_SANITIZE_STRING ) || filter_input( INPUT_GET, 'elementor-preview', FILTER_SANITIZE_STRING );
3691 }
3692
3693 /**
3694 * Check if the current page is an edit page created with the Divi Builder.
3695 *
3696 * This function checks whether the current page in the WordPress admin area is an edit page created with the Divi Builder plugin. It does so by checking the availability of specific functions associated with Divi Builder. If these functions exist, it is likely an edit page created with Divi Builder.
3697 *
3698 * @return bool True if the current page is an edit page created with Divi Builder, false otherwise.
3699 * @since 2.8.12
3700 */
3701 private static function is_divi_edit_page() {
3702 // Check if the Divi Builder's assets are enqueued by verifying the presence of specific functions.
3703 return is_callable( 'et_pb_enqueue_main_scripts' ) && is_callable( 'et_theme_builder_overrides' );
3704 }
3705
3706 /**
3707 * Check if the current page is an Oxygen Builder edit page.
3708 *
3709 * This function checks whether the current page in the WordPress admin area is an Oxygen Builder edit page. It does so by verifying if specific Oxygen assets (scripts and styles) are enqueued. If the assets are enqueued, it is likely that the current page is an Oxygen edit page.
3710 *
3711 * @return bool True if the current page is an Oxygen edit page, false otherwise.
3712 * @since 2.8.12
3713 */
3714 private static function is_oxygen_edit_page() {
3715 // Check if Oxygen's assets are enqueued
3716 return wp_script_is( 'ct-automation' ) || wp_style_is( 'ct-select2' ) || 'ct_render_shortcode' === filter_input( INPUT_GET, 'action', FILTER_SANITIZE_STRING ) || filter_input( INPUT_GET, 'ct_builder', FILTER_SANITIZE_STRING ) || filter_input( INPUT_GET, 'ct_inner', FILTER_SANITIZE_STRING );
3717 }
3718
3719 /**
3720 * Check if the current page is being edited using a specific page builder or any builder if not specified.
3721 *
3722 * This function checks whether the current page in the WordPress admin area is being edited using a specific page builder, such as Elementor, Divi, Oxygen, or Gutenberg. If no specific builder is provided, it checks for any of the supported page builders.
3723 *
3724 * @param string|null $builder (Optional) The name of the page builder to check (e.g., 'elementor', 'divi', 'oxygen', 'gutenberg'). If not specified, checks for any supported page builder.
3725 * @return bool True if the current page is being edited with the specified page builder or any supported builder, false otherwise.
3726 * @since 2.8.12
3727 */
3728 public static function is_builder_edit_page( $builder = null ) {
3729 switch( $builder ) {
3730 case 'elementor':
3731 return self::is_elementor_edit_page();
3732 case 'divi':
3733 return self::is_divi_edit_page();
3734 case 'oxygen':
3735 return self::is_oxygen_edit_page();
3736 case 'gutenberg':
3737 return self::is_gutenberg_edit_page();
3738 default:
3739 // Check for any supported page builder.
3740 return self::is_elementor_edit_page() || self::is_gutenberg_edit_page() || self::is_divi_edit_page() || self::is_oxygen_edit_page() || 'edit' === filter_input( INPUT_GET, 'action', FILTER_SANITIZE_STRING );
3741 }
3742 }
3743 }
3744