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

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

784 lines 21.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Funnel module
4 *
5 * @package
6 */
7 namespace WPFunnels\Modules\Admin\Funnel;
8
9 use WPFunnels\Admin\Module\Wpfnl_Admin_Module;
10 use WPFunnels\Admin\Wpfnl_Admin;
11 use WPFunnels\Traits\SingletonTrait;
12 use WPFunnels\Wpfnl;
13 use WPFunnels\Wpfnl_functions;
14 use WPFunnelsPro\Wpfnl_Pro;
15 use WC_Countries;
16 class Module extends Wpfnl_Admin_Module
17 {
18
19 use SingletonTrait;
20
21 private $id;
22
23 protected $funnel;
24
25 protected $step_module = null;
26
27 protected $step_type;
28
29
30 public function init($id)
31 {
32 $this->id = $id;
33 $this->funnel = Wpfnl::$instance->funnel_store;
34 $this->funnel->set_id($id);
35 }
36
37
38
39 public function init_ajax()
40 {
41 wp_ajax_helper()->handle('save-steps-order')
42 ->with_callback([ $this, 'save_steps_order' ])
43 ->with_validation($this->get_validation_data());
44
45 wp_ajax_helper()->handle('clone-funnel')
46 ->with_callback([ $this, 'clone_funnel' ])
47 ->with_validation($this->get_validation_data());
48
49 wp_ajax_helper()->handle('trash-funnel')
50 ->with_callback([ $this, 'trash_funnel' ])
51 ->with_validation($this->get_validation_data());
52
53 wp_ajax_helper()->handle('restore-funnel')
54 ->with_callback([ $this, 'restore_funnel' ])
55 ->with_validation($this->get_validation_data());
56
57 wp_ajax_helper()->handle('delete-funnel')
58 ->with_callback([ $this, 'delete_funnel' ])
59 ->with_validation($this->get_validation_data());
60
61 wp_ajax_helper()->handle('update-funnel-status')
62 ->with_callback([ $this, 'update_funnel_status' ])
63 ->with_validation($this->get_validation_data());
64
65 wp_ajax_helper()->handle('funnel-drag-order')
66 ->with_callback([ $this, 'funnel_drag_order' ])
67 ->with_validation($this->get_validation_data());
68
69 wp_ajax_helper()->handle('wpfnl-update-funnel-settings')
70 ->with_callback([ $this, 'wpfnl_update_funnel_settings' ])
71 ->with_validation($this->get_validation_data());
72
73 wp_ajax_helper()->handle('wpfnl-guided-tour')
74 ->with_callback([ $this, 'wpfnl_guided_tour' ])
75 ->with_validation($this->get_validation_data());
76 }
77
78
79 /**
80 * Return funnel object
81 *
82 * @return Wpfnl_Funnel_Store_Data
83 * @since 1.0.0
84 */
85 public function get_funnel()
86 {
87 return $this->funnel;
88 }
89
90
91 /**
92 * Show funnel window if the following conditions met
93 * a. if funnel exits
94 * show steps if -
95 * a. step_id exits in url
96 * b. step exits
97 * c. this funnel contains the step
98 * otherwise show 404 page
99 *
100 * @throws \Exception
101 * @since 1.0.0
102 */
103 public function get_view()
104 {
105 if (Wpfnl_functions::check_if_module_exists($this->funnel->get_id())) {
106 $step_id = filter_input(INPUT_GET, 'step_id', FILTER_SANITIZE_SPECIAL_CHARS);
107 $this->funnel->read($this->id);
108 $funnel = $this->get_funnel();
109
110 if (
111 $step_id
112 && Wpfnl_functions::check_if_module_exists($step_id)
113 && $this->funnel->check_if_step_in_funnel($step_id)
114 ) {
115 $this->step_type = 'landing';
116 } else {
117 $step_id = $funnel->get_first_step_id();
118 $this->step_type = $funnel->get_first_step_type();
119 }
120 $is_pro_activated = Wpfnl_functions::is_wpfnl_pro_activated();
121 $is_pro_module = Wpfnl_functions::is_pro_module($this->step_type);
122
123 $is_module_registered = Wpfnl_functions::is_module_registered($this->step_type, 'steps', true, $is_pro_module);
124
125 if ($this->step_type) {
126 if ($is_pro_activated && $is_module_registered && $is_pro_module) {
127 $this->step_module = Wpfnl_Pro::$instance->module_manager->get_admin_modules($this->step_type);
128 $this->step_module->init($step_id);
129 } elseif ($is_module_registered) {
130 $this->step_module = Wpfnl::$instance->module_manager->get_admin_modules($this->step_type);
131 $this->step_module->init($step_id);
132 }
133 }
134 require_once WPFNL_DIR . '/admin/modules/funnel/views/view.php';
135 } else {
136 require_once WPFNL_DIR . '/admin/partials/404.php';
137 }
138 }
139
140
141 /**
142 * Save steps order
143 *
144 * @param $payload
145 *
146 * @return array
147 *
148 * @since 2.0.5
149 */
150 public function save_steps_order( $payload ) {
151 $funnel_id = isset( $payload['funnelID'] ) ? $payload['funnelID'] : 0;
152 $input_node = $payload['inputNode'];
153 $output_node = $payload['outputNode'];
154 if( $funnel_id ) {
155 $funnel_data = get_post_meta( $funnel_id, '_funnel_data', true );
156 }
157 return array(
158 'success' => true
159 );
160 }
161
162 /**
163 * Funnel drag order
164 *
165 * @param Array $payload
166 *
167 * @return Array
168 * @since 2.0.4
169 */
170 public function funnel_drag_order($payload)
171 {
172 $funnel_id = $payload['funnel_id'];
173 $orders = $payload['order'];
174 $existing_order = get_post_meta($funnel_id, '_steps_order', true);
175 $step_names = apply_filters('wpfunnels_steps', [
176 'landing' => __('Landing', 'wpfnl'),
177 'thankyou' => __('Thank You', 'wpfnl'),
178 'checkout' => __('Checkout', 'wpfnl'),
179 'upsell' => __('Upsell', 'wpfnl'),
180 'downsell' => __('Downsell', 'wpfnl'),
181 ]);
182 $modified_order = [];
183 foreach ($orders as $order) {
184 $order = str_replace('setp-list-', '', $order);
185 $step_type = get_post_meta($order, '_step_type', true);
186 $step_array = [
187 'id' => $order,
188 'step_type' => $step_type,
189 'name' => $step_names[$step_type],
190 ];
191 $modified_order[] = $step_array;
192 }
193 $modified_order = array_values(array_filter($modified_order));
194 update_post_meta($funnel_id, '_steps_order', $modified_order);
195 return [
196 'success' => true,
197 ];
198 }
199
200
201 /**
202 * Trash funnel and all the
203 * data
204 *
205 * @param $payload
206 *
207 * @return array
208 * @since 1.0.0
209 */
210 public function trash_funnel($payload)
211 {
212 $funnel_id = sanitize_text_field($payload['funnel_id']);
213
214 $funnel = Wpfnl::$instance->funnel_store;
215 $funnel->read($funnel_id);
216
217 $funnel_type = get_post_meta($funnel_id, '_wpfnl_funnel_type', true);
218 $is_store_checkout = 'store_checkout' === $funnel_type;
219
220 if ($funnel->get_step_ids()) {
221 foreach ($funnel->get_step_ids() as $step_id) {
222 if ( $is_store_checkout ) {
223 wp_delete_post( $step_id, true );
224 } else {
225 $post_data = array(
226 'ID' => $step_id,
227 'post_status' => 'trash',
228 );
229 wp_update_post($post_data);
230 }
231 }
232 }
233 do_action('wpfunnels/before_trash_funnel', $funnel_id );
234
235 if ( $is_store_checkout ) {
236 wp_delete_post( $funnel_id, true );
237 } else {
238 $post_data = array(
239 'ID' => $funnel_id,
240 'post_status' => 'trash',
241 );
242 wp_update_post($post_data);
243 }
244
245 $page_slug = $is_store_checkout ? WPFNL_STORE_CHECKOUT_SLUG : WPFNL_FUNNEL_PAGE_SLUG;
246
247 $redirect_link = add_query_arg(
248 [
249 'page' => $page_slug,
250 ],
251 admin_url('admin.php')
252 );
253 return [
254 'success' => true,
255 'redirectUrl' => $redirect_link,
256 ];
257 }
258
259
260 /**
261 * Restore funnel and all the
262 * data
263 *
264 * @param $payload
265 *
266 * @return array
267 * @since 1.0.0
268 */
269 public function restore_funnel($payload)
270 {
271 if( !$this->maybe_restore_allowed() ){
272 $redirect_link = add_query_arg(
273 [
274 'page' => WPFNL_TRASH_FUNNEL_SLUG,
275 ],
276 admin_url('admin.php')
277 );
278
279 return [
280 'success' => true,
281 'redirectUrl' => $redirect_link,
282 ];
283 }
284
285 $funnel_id = sanitize_text_field($payload['funnel_id']);
286 $funnel_id = sanitize_text_field($payload['funnel_id']);
287
288 do_action('wpfunnels/before_restore_funnel', $funnel_id );
289
290 $post_data = array(
291 'ID' => $funnel_id,
292 'post_status' => 'publish',
293 );
294
295 wp_update_post($post_data);
296
297
298 $funnel = Wpfnl::$instance->funnel_store;
299 $funnel->read($funnel_id);
300
301 if ($funnel->get_step_ids()) {
302 foreach ($funnel->get_step_ids() as $step_id) {
303 $post_data = array(
304 'ID' => $step_id,
305 'post_status' => 'publish',
306 );
307 wp_update_post($post_data);
308 }
309 }
310
311 $redirect_link = add_query_arg(
312 [
313 'page' => WPFNL_TRASH_FUNNEL_SLUG,
314 ],
315 admin_url('admin.php')
316 );
317
318 return [
319 'success' => true,
320 'redirectUrl' => $redirect_link,
321 ];
322 }
323
324 /**
325 * Check if the user can restore the funnel
326 * If the user has pro license then he can restore any time
327 * If the user has free license then he can restore only 3 funnels
328 * If the user has more than 3 funnels then he can't restore
329 * @return bool
330 * @since 3.4.14
331 */
332 private function maybe_restore_allowed(){
333 if( !Wpfnl_functions::is_pro_license_activated() ){
334 $total_funnels = Wpfnl_functions::count_non_store_checkout_funnels( array( 'publish', 'draft' ) );
335 if( (int)$total_funnels < 3 ){
336 return true;
337 }
338 return false;
339 }
340 return true;
341 }
342
343
344 /**
345 * Delete funnel and all the
346 * data
347 *
348 * @param $payload
349 *
350 * @return array
351 * @since 1.0.0
352 */
353 public function delete_funnel($payload)
354 {
355 $funnel_id = sanitize_text_field($payload['funnel_id']);
356 $funnel = Wpfnl::$instance->funnel_store;
357 $funnel->read($funnel_id);
358
359 if ($funnel->get_step_ids()) {
360 foreach ($funnel->get_step_ids() as $step_id) {
361 $step = Wpfnl::$instance->step_store;
362 $step->delete($step_id);
363 }
364 }
365 do_action('wpfunnels/before_delete_funnel', $funnel_id );
366 $response = $funnel->delete($funnel_id);
367 if ($response) {
368 $redirect_link = add_query_arg(
369 [
370 'page' => WPFNL_TRASH_FUNNEL_SLUG,
371 ],
372 admin_url('admin.php')
373 );
374 return [
375 'success' => true,
376 'redirectUrl' => $redirect_link,
377 ];
378 }
379 }
380
381 /**
382 * Update funnel status
383 *
384 * @param Array $payload
385 *
386 * @return Array
387 */
388 public function update_funnel_status( $payload ) {
389
390 if ( ! isset( $payload['funnel_id'] ) ) {
391 return array(
392 'message' => __( 'No funnel id found', 'wpfnl' )
393 );
394 }
395
396 $funnel_id = sanitize_text_field($payload['funnel_id']);
397 $status = sanitize_text_field($payload['status']);
398 $steps = get_post_meta( $funnel_id, '_steps_order', true );
399 if( $steps ) {
400 foreach ($steps as $step) {
401 $step_data = array(
402 'ID' => $step['id'],
403 'post_status' => $status
404 );
405 wp_update_post($step_data);
406 }
407 }
408
409 $funnel_data = array(
410 'ID' => $funnel_id,
411 'post_status' => $status
412 );
413 wp_update_post($funnel_data);
414
415 return array(
416 'success' => true,
417 'status' => $status,
418 'funnel_id' => $funnel_id,
419 'message' => __('Funnel status has been updated.', 'wpfnl'),
420 'redirect_url' => admin_url('admin.php?page=wp_funnels')
421 );
422 }
423
424
425 /**
426 * Clone funnel and all the steps
427 * data
428 *
429 * @param $payload
430 * @since 1.0.0
431 * @return array
432 */
433 public function clone_funnel($payload)
434 {
435 $funnel_id = sanitize_text_field($payload['funnel_id']);
436 $funnel = Wpfnl::$instance->funnel_store;
437 $funnel->read($funnel_id);
438 $response = $funnel->clone_funnel();
439
440 if ($response && ! is_wp_error($response)) {
441 $link = add_query_arg(
442 [
443 'page' => 'wp_funnels',
444 'id' => $response,
445 ],
446 admin_url('admin.php')
447 );
448
449 return [
450 'success' => true,
451 'redirectUrl' => $link,
452 ];
453 } else {
454 return [
455 'success' => false,
456 'message' => $response->get_error_message(),
457 ];
458 }
459 }
460
461 /**
462 * Get module name
463 *
464 * @return String
465 */
466 public function get_name()
467 {
468 return __('funnel','wpfnl');
469 }
470
471 /**
472 * Delete marked funnel
473 *
474 * @param $payload
475 *
476 * @return array|bool
477 * @since 1.0.0
478 */
479 public function delete_marked_funnels( $payload ) {
480 $response = [];
481 if (isset($payload['ids'])) {
482 $data_array = $payload['ids'];
483 foreach ($data_array as $data_key => $data_value) {
484 $funnel_id = sanitize_text_field($data_value);
485 $funnel = Wpfnl::$instance->funnel_store;
486 $funnel->read($funnel_id);
487
488 if ($funnel->get_step_ids()) {
489 foreach ($funnel->get_step_ids() as $step_id) {
490 $step = Wpfnl::$instance->step_store;
491 Wpfnl_functions::maybe_delete_screenshot_by_step_id( $step_id );
492 $step->delete($step_id);
493 }
494 }
495 /**
496 * Fires before deleting a funnel to delete Mail Mint automation
497 *
498 * @param int funnel_id Funnel id
499 * @since 2.7.18
500 */
501 do_action('wpfunnels/before_delete_funnel', $funnel_id );
502 $response = $funnel->delete($funnel_id);
503
504 }
505 }
506 if ($response) {
507 $redirect_link = add_query_arg(
508 [
509 'page' => WPFNL_TRASH_FUNNEL_SLUG,
510 ],
511 admin_url('admin.php')
512 );
513 return [
514 'success' => true,
515 'redirectUrl' => $redirect_link,
516 ];
517 }
518 return false;
519 }
520
521
522 /**
523 * Restore marked funnel
524 *
525 * @param $payload
526 *
527 * @return array|bool
528 * @since 1.0.0
529 */
530 public function restore_marked_funnels( $payload ) {
531 $response = [];
532 if (isset($payload['ids'])) {
533 $data_array = $payload['ids'];
534 foreach ($data_array as $data_key => $data_value) {
535
536 if( !$this->maybe_restore_allowed() ){
537 $redirect_link = add_query_arg(
538 [
539 'page' => WPFNL_TRASH_FUNNEL_SLUG,
540 ],
541 admin_url('admin.php')
542 );
543
544 return [
545 'success' => true,
546 'redirectUrl' => $redirect_link,
547 ];
548 }
549
550 $funnel_id = sanitize_text_field($data_value);
551 $funnel = Wpfnl::$instance->funnel_store;
552 $funnel->read($funnel_id);
553
554 if ($funnel->get_step_ids()) {
555 foreach ($funnel->get_step_ids() as $step_id) {
556 $post_data = array(
557 'ID' => $step_id,
558 'post_status' => 'publish',
559 );
560 wp_update_post($post_data);
561 }
562 }
563 /**
564 * Fires before deleting a funnel to delete Mail Mint automation
565 *
566 * @param int funnel_id Funnel id
567 * @since 2.7.18
568 */
569 do_action('wpfunnels/before_restore_funnel', $funnel_id );
570 $post_data = array(
571 'ID' => $funnel_id,
572 'post_status' => 'publish',
573 );
574 $response = wp_update_post($post_data);
575
576 }
577 }
578 if ($response) {
579 $redirect_link = add_query_arg(
580 [
581 'page' => WPFNL_TRASH_FUNNEL_SLUG,
582 ],
583 admin_url('admin.php')
584 );
585 return [
586 'success' => true,
587 'redirectUrl' => $redirect_link,
588 ];
589 }
590 return false;
591 }
592
593 /**
594 * Trash marked funnel
595 *
596 * @param $payload
597 *
598 * @return array|bool
599 * @since 1.0.0
600 */
601 public function trash_marked_funnels( $payload ) {
602 $response = [];
603 if (isset($payload['ids'])) {
604 $data_array = $payload['ids'];
605 foreach ($data_array as $data_key => $data_value) {
606 $funnel_id = sanitize_text_field($data_value);
607 $funnel = Wpfnl::$instance->funnel_store;
608 $funnel->read($funnel_id);
609
610 if ($funnel->get_step_ids()) {
611 foreach ($funnel->get_step_ids() as $step_id) {
612 $post_data = array(
613 'ID' => $step_id,
614 'post_status' => 'trash',
615 );
616 wp_update_post($post_data);
617 }
618 }
619 /**
620 * Fires before deleting a funnel to delete Mail Mint automation
621 *
622 * @param int funnel_id Funnel id
623 * @since 2.7.18
624 */
625 do_action('wpfunnels/before_trash_funnel', $funnel_id );
626 $post_data = array(
627 'ID' => $funnel_id,
628 'post_status' => 'trash',
629 );
630 $response = wp_update_post($post_data);
631
632 }
633 }
634 if ($response) {
635 $redirect_link = add_query_arg(
636 [
637 'page' => WPFNL_FUNNEL_PAGE_SLUG,
638 ],
639 admin_url('admin.php')
640 );
641 return [
642 'success' => true,
643 'redirectUrl' => $redirect_link,
644 ];
645 }
646 return false;
647 }
648
649
650 /**
651 * Update funnel settings by funnel id to postmeta
652 */
653 public function wpfnl_update_funnel_settings( $payload ){
654
655 $response = [
656 'success' => false,
657 ];
658
659 if( isset($payload['funnel_id']) ){
660 if( isset($payload['utm_settings']) ){
661 $payload['utm_settings']['utm_enable'] = $payload['utm_settings']['utm_enable'] == 'true' ? 'on' : 'off';
662 update_post_meta( $payload['funnel_id'] , '_wpfunnels_utm_params', $payload['utm_settings'] );
663 }
664
665 if( isset($payload['is_fb_pixel']) ){
666
667 $payload['is_fb_pixel'] = $payload['is_fb_pixel'] == 'true' ? 'yes' : 'no';
668 update_post_meta( $payload['funnel_id'] , '_wpfunnels_disabled_fb_pixel', $payload['is_fb_pixel'] );
669 }
670
671 if( isset($payload['is_gtm']) ){
672 $payload['is_gtm'] = $payload['is_gtm'] == 'true' ? 'yes' : 'no';
673 update_post_meta( $payload['funnel_id'] , '_wpfunnels_disabled_gtm', $payload['is_gtm'] );
674 }
675
676 if( isset($payload['skip_offer']) && isset($payload['skip_if_quantity']) ){
677 $skip_offer = [
678 'skip_offer' => $payload['skip_offer'] == 'true' ? 'yes' : 'no',
679 'skip_if_quantity' => $payload['skip_if_quantity'] == 'true' ? 'yes' : 'no',
680 ];
681 update_post_meta( $payload['funnel_id'] , '_wpfunnels_skip_offer', $skip_offer );
682 }
683
684 if( !empty($payload['skip_recurring_offer_within_days']) ){
685 update_post_meta( $payload['funnel_id'] , '_wpfunnels_skip_recurring_offer_within_days', sanitize_text_field($payload['skip_recurring_offer_within_days']) );
686 }
687
688 if( !empty($payload['skip_recurring_offer']) ){
689 update_post_meta( $payload['funnel_id'] , '_wpfunnels_skip_recurring_offer', $payload['skip_recurring_offer'] );
690 }
691
692
693 $response = [
694 'success' => true,
695 'data' => 'Save successfull',
696 ];
697
698 }
699
700 return $response;
701 }
702
703 /**
704 * Handle guided tour
705 *
706 * @param $payload
707 *
708 * @return array
709 * @since 3.4.16
710 */
711 public function wpfnl_guided_tour($payload)
712 {
713 if(isset($payload['security']) && !wp_verify_nonce($payload['security'], 'wpfnl-admin')) {
714 return [
715 'success' => false,
716 'data' => 'You do not have permission to perform this action.',
717 ];
718 }
719
720 if (empty($payload)) {
721 return [
722 'success' => false,
723 'data' => 'Required value is missing.',
724 ];
725 }
726
727 $tour_name = !empty($payload['tourName']) ? $payload['tourName'] : '';
728 $tour_type = !empty($payload['tourType']) ? $payload['tourType'] : '';
729
730 if ('skip' === $tour_type) {
731 return $this->handle_skip_tour();
732 }
733
734 if ('finish' === $tour_type) {
735 return $this->handle_finish_tour($tour_name);
736 }
737
738 return [
739 'success' => false,
740 'data' => 'Invalid tour type',
741 ];
742 }
743
744 /**
745 * Handle skip tour
746 *
747 * @return array
748 * @since 3.4.16
749 */
750 public function handle_skip_tour()
751 {
752 update_option('wpfnl_guided_tour', []);
753 return [
754 'success' => true,
755 'data' => 'Tour skipped successfully',
756 'tour' => [],
757 ];
758 }
759
760 /**
761 * Handle finish tour
762 * @param $tour_name
763 * @return array
764 * @since 3.4.16
765 */
766 public function handle_finish_tour($tour_name)
767 {
768 $guided_tour = Wpfnl_functions::get_guided_tour();
769
770 if (($key = array_search($tour_name, $guided_tour)) !== false) {
771 unset($guided_tour[$key]);
772 }
773
774 update_option('wpfnl_guided_tour', array_values($guided_tour));
775 return [
776 'success' => true,
777 'data' => 'Tour finished successfully',
778 'tour' => $guided_tour,
779 ];
780 }
781
782
783 }
784