PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / 3.12.8
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell v3.12.8
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 / class-wpfnl.php

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

757 lines 21.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * The core plugin class.
4 *
5 * This is used to define internationalization, admin-specific hooks, and
6 * public-facing site hooks.
7 *
8 * Also maintains the unique identifier of this plugin as well as the current
9 * version of the plugin.
10 *
11 * @since 1.0.0
12 * @package Wpfnl
13 * @subpackage Wpfnl/includes
14 * @author RexTheme <[email protected]>
15 */
16 namespace WPFunnels;
17
18 use Wpfnl_Activator;
19 use Wpfnl_i18n;
20 use Wpfnl_Loader;
21 use Wpfnl_Logger;
22 use WPFunnels\Admin\OptinField\OptinField;
23 use WPFunnels\Admin\SetupWizard;
24 use WPFunnels\Admin\Wpfnl_Admin as Admin;
25 use WPFunnels\Admin\Notices\Notice;
26 use WPFunnels\Admin\Banner\SpecialOccasionBanner;
27 use WPFunnels\Admin\Banner\SetupReminderBanner;
28 use WPFunnels\Ajax_Handler\Ajax_Handler;
29 use WPFunnels\Classes\OrderBumpActions\Wpfnl_Order_Bump_Action;
30 use WPFunnels\Classes\TestimonialActions\Wpfnl_Testimonial_Action;
31 use WPFunnels\Compatibility\CartLift\Wpfnl_Cart_Lift_Compatibility;
32 use WPFunnels\Compatibility\SlimSeo\Wpfnl_Slim_Seo_Compatibility;
33 use WPFunnels\Frontend\Wpfnl_Public;
34 use WPFunnels\Frontend\Wpfnl_Public as Frontend;
35 use WPFunnels\CPT\Wpfnl_CPT as CPT;
36 use WPFunnels\Data_Store\Wpfnl_Funnel_Store_Data as Funnel_Store;
37 use WPFunnels\Data_Store\Wpfnl_Steps_Store_Data as Step_Store;
38 use WPFunnels\Menu\Wpfnl_Menus as Menu;
39 use WPFunnels\Modules\Wpfnl_Modules_Manager as Module_Manager;
40 use WPFunnels\Report\OptinRecorder;
41 use WPFunnels\Report\StatHookHandler;
42 use WPFunnels\Rest\Server;
43 // use WPFunnels\Shortcodes\Wpfnl_Shortcode;
44 use WPFunnels\Shortcodes\Wpfnl_Shortcodes;
45 use WPFunnels\Widgets\Wpfnl_Widgets_Manager as Widget_Manager;
46 use WPFunnels\Batch\Elementor\Wpfnl_Batch;
47 use WPFunnels\Meta\Wpfnl_Default_Meta;
48 use WPFunnels\Compatibility\Wpfnl_Compatibility;
49 use WPFunnels\Export\Wpfnl_Export;
50 use WPFunnels\Import\Wpfnl_Import;
51 use WPFunnels\Report\Reporting;
52 /**
53 * The file that defines the core plugin class
54 *
55 * A class definition that includes attributes and functions used across both the
56 * public-facing side of the site and the admin area.
57 *
58 * @link https://rextheme.com
59 * @since 1.0.0
60 *
61 * @package Wpfnl
62 * @subpackage Wpfnl/includes
63 */
64
65 class Wpfnl
66 {
67
68 /**
69 * Instance.
70 *
71 * Holds the plugin instance.
72 *
73 * @since 1.0.0
74 * @access public
75 * @static
76 *
77 * @var Wpfnl
78 */
79 public static $instance = null;
80
81 public $module_manager;
82
83 public $admin;
84
85 public $plugin_public;
86
87 public $template_manager;
88
89 public $menu;
90
91 public $cpt;
92
93 public $funnel_store;
94
95 public $step_store;
96
97 public $batch;
98
99 public $helper;
100
101 public $widget_manager;
102
103 public $page_templates;
104
105
106 public $order_bump_actions;
107
108 public $testimonial_actions;
109
110 public $meta;
111
112 public $frontend;
113
114 public $log;
115
116 public $shortcodes;
117 public $shortcode;
118
119
120 public $export_funnel;
121
122 public $import_funnel;
123
124 /**
125 * Admin notice object
126 *
127 * @var string $admin_notice
128 */
129 protected $admin_notice;
130
131
132 /**
133 * Admin banner object
134 *
135 * @var string $admin_banner
136 */
137 protected $admin_banner;
138
139 /**
140 * Setup reminder banner object
141 *
142 * @var SetupReminderBanner $setup_reminder_banner
143 * @since 3.6.0
144 */
145 protected $setup_reminder_banner;
146
147 protected $optin_field;
148
149 /**
150 * Reporting object
151 *
152 * @var $reporting
153 *
154 * @since 3.2.0
155 */
156 protected $reporting;
157
158 /**
159 * The loader that's responsible for maintaining and registering all hooks that power
160 * the plugin.
161 *
162 * @since 1.0.0
163 * @access protected
164 * @var Wpfnl_Loader $loader Maintains and registers all hooks for the plugin.
165 */
166 protected $loader;
167
168 /**
169 * The unique identifier of this plugin.
170 *
171 * @since 1.0.0
172 * @access protected
173 * @var string $plugin_name The string used to uniquely identify this plugin.
174 */
175 protected $plugin_name;
176
177
178 /**
179 * Object variable for Compatibility class
180 *
181 * @since
182 * @access protected
183 * @var $compatibility
184 */
185 protected $compatibility;
186
187 /**
188 * The current version of the plugin.
189 *
190 * @since 1.0.0
191 * @access protected
192 * @var string $version The current version of the plugin.
193 */
194 protected $version;
195
196
197 /**
198 * Ajax handler
199 *
200 * @var $ajax_handler
201 */
202 protected $ajax_handler;
203
204
205 /**
206 * Object variable for Cart_Lift_Compatibility class
207 *
208 * @since
209 * @access protected
210 * @var $cart_lift
211 */
212 protected $cart_lift;
213
214
215 /**
216 * Object variable for Slim_Seo_Compatibility class
217 *
218 * @since
219 * @access protected
220 * @var $slim_seo
221 */
222 protected $slim_seo;
223
224
225 /**
226 * StatHookHandler Object
227 *
228 * @var $stat_hooks_handler
229 * @type StatHookHandler
230 * @since 3.2.0
231 */
232 protected $stat_hooks_handler;
233
234
235 /**
236 * OptinRecorder Object
237 *
238 * @var $optin_recorder
239 * @type OptinRecorder
240 * @since 3.2.0
241 */
242 protected $optin_recorder;
243
244 /**
245 * Instance.
246 *
247 * Ensures only one instance of the plugin class is loaded or can be loaded.
248 *
249 * @since 1.0.0
250 * @access public
251 * @static
252 *
253 * @return Wpfnl An instance of the class.
254 */
255 public static function get_instance()
256 {
257 if (is_null(self::$instance)) {
258 self::$instance = new self();
259 do_action('wpfunnels/loaded');
260 }
261 return self::$instance;
262 }
263
264
265 /**
266 * Define the core functionality of the plugin.
267 *
268 * Set the plugin name and the plugin version that can be used throughout the plugin.
269 * Load the dependencies, define the locale, and set the hooks for the admin area and
270 * the public-facing side of the site.
271 *
272 * @since 1.0.0
273 */
274 public function __construct()
275 {
276 if (defined('WPFNL_VERSION')) {
277 $this->version = WPFNL_VERSION;
278 } else {
279 $this->version = '1.0.0';
280 }
281
282 $this->plugin_name = 'wpfunnels';
283 $this->load_dependencies();
284 $this->init_rest_api();
285 $this->init_setup_wizard();
286
287
288 /*if( !Wpfnl_functions::is_plugin_activated('woocommerce/woocommerce.php') ) {
289 add_action( 'admin_enqueue_scripts', [$this, 'enqueue_scripts'] );
290 add_action( 'wp_ajax_plugin_install_success', array($this, 'plugin_install_success') );
291 add_action( 'admin_notices', array('WPFunnels\Admin\Notices\Notice', 'woocommerce_dependency_notice') );
292 return;
293 }*/
294
295 // load core modules
296 add_action( 'admin_footer', array($this, 'admin_footer_style') );
297 add_action( 'wpfunnels/pro_init', array( $this, 'after_pro_plugin_init' ) );
298 add_action( 'plugins_loaded', array($this, 'load_plugin'), 9 );
299
300 $this->set_locale();
301 $this->init_hooks();
302 }
303
304
305 /**
306 * update funnel data response
307 *
308 * @param Array $response
309 *
310 * @since 1.7.8
311 * @return Array $response
312 */
313 public function update_mint_funnel_data_response( $response ){
314
315 $automation_steps = [];
316 if( is_array($response) && !empty($response['funnel_data']['drawflow']['Home']['data']) ){
317 $steps_order = $response['funnel_data']['drawflow']['Home']['data'];
318 if( is_array($steps_order) ){
319 foreach( $steps_order as $key=>$step ){
320 if( isset( $step['data']['step_id'] ) ){
321 $step_id = $step['data']['step_id'];
322 if( Wpfnl_functions::is_mint_mrm_active() ){
323 $automation_steps['step_'.$step_id]['data'] = [];
324 }
325 }
326 }
327 }
328 }
329 $response['automationSteps'] = $automation_steps;
330 return $response;
331 }
332
333
334 /**
335 * Enqueue funnel admin common scripts
336 */
337 public function enqueue_scripts() {
338 wp_enqueue_script($this->plugin_name . '-common', WPFNL_DIR_URL . 'admin/assets/js/wpfnl-admin-common.js', [ 'jquery', 'wp-i18n', 'wp-util', 'updates' ], $this->version, true);
339 wp_localize_script( $this->plugin_name. '-common', 'wpfnl_common_vars', array(
340 'ajaxurl' => admin_url( 'admin-ajax.php' ),
341 'wpfnl_activate_plugin_nonce' => wp_create_nonce('wpfnl_activate_plugin_nonce')
342 ));
343
344 $post_id = get_the_ID();
345 $custom_css = get_post_meta( $post_id, 'rex_gutenberg_css', true );
346
347 if ( $custom_css ) {
348 wp_register_style( 'rex-gutenberg-css', false );
349 wp_enqueue_style( 'rex-gutenberg-css' );
350 wp_add_inline_style( 'rex-gutenberg-css', $custom_css );
351 }
352 }
353
354
355 /**
356 * Plugin activation ajax
357 */
358 public function plugin_install_success() {
359
360 if ( ! current_user_can( 'manage_options' ) ) {
361 wp_send_json_error( array(
362 'message' => __('You are not authorize to activate plugins.', 'wpfnl')
363 ) );
364 }
365
366 if ( ! check_ajax_referer( 'wpfnl_activate_plugin_nonce', 'security', false ) ) {
367 $response_data = array( 'message' => __('Nonce verification failed', 'wpfnl') );
368 wp_send_json_error( $response_data );
369 }
370
371 \wp_clean_plugins_cache();
372 $plugin_init = ( isset( $_POST['plugin_init'] ) ) ? esc_attr( $_POST['plugin_init'] ) : '';
373 $activate = \activate_plugin( $plugin_init, '', false, true );
374
375 if ( is_wp_error( $activate ) ) {
376 wp_send_json_error(
377 array(
378 'success' => false,
379 'message' => $activate->get_error_message(),
380 )
381 );
382 }
383
384 wp_send_json_success(
385 array(
386 'message' => __('Plugin activated successfully.', 'wpfnl'),
387 )
388 );
389 }
390
391
392 public function init_hooks() {
393 $this->loader->add_action( 'init', $this, 'load_admin_modules' );
394 $shortcode = new Wpfnl_Shortcodes();
395 add_action( 'init', array( $shortcode, 'init') );
396 }
397
398 public function init_rest_api() {
399 $this->loader->add_action( 'init', $this, 'load_rest_api' );
400 }
401
402 public function load_admin_modules() {
403 $this->module_manager = new Module_Manager();
404 }
405
406 public function load_rest_api() {
407 Server::instance()->init();
408 }
409
410
411 /**
412 * Load plugin classes
413 */
414 public function load_plugin() {
415 $this->batch = new Wpfnl_Batch();
416 $this->init();
417
418 do_action( 'wpfunnels/init' );
419 }
420
421 public function init() {
422 $this->admin = new Admin( $this->get_plugin_name(), $this->get_version() );
423 $this->frontend = Wpfnl_Public::getInstance();
424 $this->cpt = new CPT();
425 $this->menu = new Menu();
426 $this->funnel_store = new Funnel_Store();
427 $this->step_store = new Step_Store();
428 $this->template_manager = new TemplateLibrary\Manager();
429
430 $this->widget_manager = Widget_Manager::getInstance()->init();
431 $this->page_templates = new PageTemplates\Manager();
432 $this->admin_notice = new Notice();
433 $this->admin_banner = new SpecialOccasionBanner('4thjuly', '2026-07-02 00:00:01', '2026-07-07 23:59:59', 'https://getwpfunnels.com/pricing/?utm_source=plugin&utm_medium=dashboard-banner-wpf&utm_campaign=4THJULY2026');
434 $this->setup_reminder_banner = new SetupReminderBanner();
435 $this->order_bump_actions = new Wpfnl_Order_Bump_Action();
436 $this->testimonial_actions = new Wpfnl_Testimonial_Action();
437 $this->meta = new Wpfnl_Default_Meta();
438 $this->shortcodes = Wpfnl_Shortcodes::getInstance()->init();
439 $this->ajax_handler = new Ajax_Handler();
440 $this->optin_field = new OptinField();
441 $this->log = Wpfnl_Logger::getInstance()->initialize_logging();
442 $this->compatibility = new Wpfnl_Compatibility();
443
444 $this->stat_hooks_handler = new StatHookHandler();
445 $this->optin_recorder = new OptinRecorder();
446
447 // Initialize Payment Gateway Factory
448 if ( Wpfnl_functions::is_wc_active() ) {
449 Gateway\Payment_Gateways_Factory::getInstance();
450
451 // Initialize Offer Module (upsell/downsell) only if Pro is not active
452 // When Pro is active, it handles offer functionality
453 if ( ! Wpfnl_functions::is_wpfnl_pro_activated() ) {
454 new Offer\Wpfnl_Offer();
455 }
456
457 // Store Checkout: override the WooCommerce default checkout with the
458 // WPFunnels Store Checkout step (only when a step is configured).
459 require_once WPFNL_DIR . 'includes/core/woocommerce/class-wpfnl-store-checkout-override.php';
460 \WPFunnels\WooCommerce\Wpfnl_Store_Checkout_Override::getInstance();
461 }
462
463 $this->export_funnel = Wpfnl_Export::getInstance()->init_ajax();
464 $this->import_funnel = new Wpfnl_Import();
465
466 $this->reporting = Reporting::get_instance();
467 $this->reporting->init();
468
469 Wpfnl_Activator::init();
470 }
471
472
473
474 /**
475 * Load the required dependencies for this plugin.
476 *
477 * Include the following files that make up the plugin:
478 *
479 * - Wpfnl_Loader. Orchestrates the hooks of the plugin.
480 * - Wpfnl_i18n. Defines internationalization functionality.
481 * - Wpfnl_Admin. Defines all hooks for the admin area.
482 * - Wpfnl_Public. Defines all hooks for the public side of the site.
483 *
484 * Create an instance of the loader which will be used to register the hooks
485 * with WordPress.
486 *
487 * @since 1.0.0
488 * @access private
489 */
490 private function load_dependencies()
491 {
492
493 /**
494 * Require the action scheduler
495 */
496 require_once plugin_dir_path(dirname(__FILE__)) . 'vendor/woocommerce/action-scheduler/action-scheduler.php';
497
498 /**
499 * The class responsible for auto loading all files of the
500 * core plugin.
501 */
502 require_once plugin_dir_path(dirname(__FILE__)) . 'vendor/autoload.php';
503
504 /**
505 * The class responsible for orchestrating the actions and filters of the
506 * core plugin.
507 */
508 require_once plugin_dir_path(dirname(__FILE__)) . 'includes/utils/class-wpfnl-loader.php';
509
510 /**
511 * The class responsible for defining internationalization functionality
512 * of the plugin.
513 */
514 require_once plugin_dir_path(dirname(__FILE__)) . 'includes/utils/class-wpfnl-i18n.php';
515
516 /**
517 * The class responsible for defining all actions that occur in the admin area.
518 */
519 require_once plugin_dir_path(dirname(__FILE__)) . 'admin/class-wpfnl-admin.php';
520
521 /**
522 * The class responsible for defining all actions that occur in the public-facing
523 * side of the site.
524 */
525 require_once plugin_dir_path(dirname(__FILE__)) . 'public/class-wpfnl-public.php';
526
527 /**
528 * Require action scheduler for crm
529 */
530 //require_once plugin_dir_path(dirname(__FILE__)) . 'packages/action-scheduler/action-scheduler.php';
531
532 $this->loader = new Wpfnl_Loader();
533 }
534
535
536 /**
537 * After pro plugin init action
538 */
539 public function after_pro_plugin_init() {
540
541 if ( ! is_admin() ) {
542 return;
543 }
544
545 if ( version_compare( WPFNL_PRO_VERSION, WPFNL_PRO_REQUIRED_VERSION, '<' ) ) {
546 add_action( 'admin_notices', array( $this, 'required_wpf_pro_notice' ) );
547 add_action( 'after_plugin_row_'. WPFNL_BASE, 'wpfnl_pro_update_notice_after_plugin_row' );
548 }
549 }
550
551
552 /**
553 * Required pro plugin notice
554 */
555 public function required_wpf_pro_notice() {
556 $class = 'notice notice-error';
557 $message = sprintf(__("It appears you have an older version of <strong>WPFunnels Pro</strong>. This may cause some issues with the plugin's functionality. Please update <strong>WPFunnels Pro</strong> to v%s and above.","wpfnl"), WPFNL_PRO_REQUIRED_VERSION); // phpcs:ignore
558 printf( '<div class="%1$s"><p>%2$s</p></div>', $class, $message );
559 }
560
561
562 /**
563 * Show pro dependency notice
564 * after plugin row
565 */
566 public function wpfnl_pro_update_notice_after_plugin_row() {
567 $message = sprintf(__("It appears you have an older version of <strong>WPFunnels Pro</strong>. This may cause some issues with the plugin's functionality. Please update <strong>WPFunnels Pro</strong> to v%s and above.",'wpfnl'), WPFNL_PRO_REQUIRED_VERSION ); // phpcs:ignore
568 printf( '</tr><tr class="plugin-update-tr"><td colspan="5" class="plugin-update"><div class="update-message" style="background-color: #ffebe8;">%s</div></td>', $message );
569 }
570
571
572 /**
573 * Define the locale for this plugin for internationalization.
574 *
575 * Uses the Wpfnl_i18n class in order to set the domain and to register the hook
576 * with WordPress.
577 *
578 * @since 1.0.0
579 * @access private
580 */
581 private function set_locale()
582 {
583 $plugin_i18n = new Wpfnl_i18n();
584
585 $this->loader->add_action('init', $plugin_i18n, 'load_plugin_textdomain');
586
587 }
588
589
590 /**
591 * Run the loader to execute all of the hooks with WordPress.
592 *
593 * @since 1.0.0
594 */
595 public function run()
596 {
597 $this->loader->run();
598 }
599
600
601 /**
602 * The name of the plugin used to uniquely identify it within the context of
603 * WordPress and to define internationalization functionality.
604 *
605 * @since 1.0.0
606 * @return string The name of the plugin.
607 */
608 public function get_plugin_name()
609 {
610 return $this->plugin_name;
611 }
612
613
614 /**
615 * The reference to the class that orchestrates the hooks with the plugin.
616 *
617 * @since 1.0.0
618 * @return Wpfnl_Loader Orchestrates the hooks of the plugin.
619 */
620 public function get_loader()
621 {
622 return $this->loader;
623 }
624
625
626 /**
627 * Retrieve the version number of the plugin.
628 *
629 * @since 1.0.0
630 * @return string The version number of the plugin.
631 */
632 public function get_version()
633 {
634 return $this->version;
635 }
636
637
638 /**
639 * Render admin footer styles
640 */
641 public function admin_footer_style() {
642 echo '<style>
643 .wpfnl-notice {
644 border-left-color: #dba617;
645 }
646 .wpfnl-notice .wpfnl-notice__content {
647 padding: 10px 0;
648 }
649
650 .wpfnl-notice .notice-dismiss {
651 top: 11px;
652 }
653
654 .wpfnl-notice .wpfnl-notice__content > p {
655 font-weight: 600;
656 margin: 0;
657 }
658 .wpfnl-notice .wpfnl-notice__actions {
659 margin-top: 8px;
660 }
661
662 .wpfnl-notice .wpfnl-notice__content .wpfnl-notice-button {
663 height: 36px;
664 line-height: 36px;
665 border-radius: 6px;
666 color: #fff;
667 font-weight: 500;
668 padding: 0 20px;
669 background: #6e42d3;
670 display: inline-block;
671 text-decoration: none;
672 letter-spacing: 0.5px;
673 transition: all 0.3s ease;
674 }
675
676 .wpfnl-notice .wpfnl-notice__content .wpfnl-notice-button:hover {
677 background: #4C25A5;
678 }
679 .wpfnl-notice .wpfnl-notice__content .wpfnl-notice-button .notice-loader {
680 border: 2px solid #8265c5;
681 border-radius: 50%;
682 border-top: 2px solid #fff;
683 width: 10px;
684 height: 10px;
685 animation: spin 0.7s linear infinite;
686 display: none;
687 position: relative;
688 top: 3px;
689 margin-left: 9px;
690 }
691 @-webkit-keyframes spin {
692 0% { -webkit-transform: rotate(0deg); }
693 100% { -webkit-transform: rotate(360deg); }
694 }
695
696 @keyframes spin {
697 0% { transform: rotate(0deg); }
698 100% { transform: rotate(360deg); }
699 }
700 </style>';
701 }
702
703
704 /**
705 * Init setup wizard options
706 */
707 public function init_setup_wizard() {
708 add_action('init', array( $this, 'register_setup_wizard_page' ));
709 add_action('admin_init', array($this, 'admin_redirects'));
710
711 // Register AJAX handlers for setup wizard (needs to be available even when not on wizard page)
712 \WPFunnels\Admin\SetupWizard::register_ajax_handlers();
713 }
714
715
716 /**
717 * Register setup wizard
718 */
719 public function register_setup_wizard_page() {
720 if (!empty($_GET['page']) && 'wpfunnels-setup' == sanitize_text_field( $_GET['page'] )) {
721 add_action('admin_menu', function () {
722 add_dashboard_page('WPFunnels Setup', 'WPFunnels Setup', 'manage_options', 'wpfunnels-setup', function () {
723 return '';
724 });
725 });
726 add_action('current_screen', function () {
727 new SetupWizard();
728 }, 999);
729 }
730 }
731
732
733 /**
734 * Handle redirects to setup/welcome page after install and updates.
735 *
736 * For setup wizard, transient must be present, the user must have access rights, and we must ignore the network/bulk plugin updaters.
737 */
738 public function admin_redirects()
739 {
740 // Setup wizard redirect.
741 if (get_transient('_wpfunnels_activation_redirect')) {
742 $do_redirect = true;
743 // On these pages, or during these events, postpone the redirect.
744 if (wp_doing_ajax() || is_network_admin() || !current_user_can('manage_options')) {
745 $do_redirect = false;
746 }
747
748 if ( $do_redirect ) {
749 delete_transient('_wpfunnels_activation_redirect');
750 $url = admin_url('admin.php?page=wpfunnels-setup');
751 wp_safe_redirect( wp_sanitize_redirect( esc_url_raw( $url ) ) );
752 exit;
753 }
754 }
755 }
756 }
757