PluginProbe
FunnelKit – Funnel Builder for WooCommerce Checkout / 3.16.0.2
FunnelKit – Funnel Builder for WooCommerce Checkout v3.16.0.2
3.16.0.5 3.16.0.4 3.16.0.3 3.16.0.2 3.16.0 3.16.0.1 3.15.0.9 3.15.0.8 3.0.0.1 3.0.1.1 3.0.2.1 3.1.0.1 3.1.1.1 3.1.2.1 3.10.0.1 3.10.1.1 3.10.2.1 3.11.0.0.1 3.11.0.1.1 3.11.0.2.1 3.11.1.1 3.12.0.0.1 3.12.0.1.1 3.13.0.0.1 3.13.1.0.1 All 219 releases
funnel-builder / funnel-builder.php

funnel-builder.php in FunnelKit – Funnel Builder for WooCommerce Checkout 3.16.0.2, at funnel-builder.php

585 lines 19.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: FunnelKit Funnel Builder
4 * Plugin URI: https://funnelkit.com/wordpress-funnel-builder/
5 * Description: Create high-converting sales funnels on WordPress that look professional by following a well-guided step-by-step process.
6 * Version: 3.16.0.2
7 * Author: FunnelKit
8 * Author URI: https://funnelkit.com
9 * License: GPLv3 or later
10 * License URI: http://www.gnu.org/licenses/gpl-3.0.html
11 * Text Domain: funnel-builder
12 *
13 * Requires at least: 6.2
14 * Tested up to: 7.0
15 * Requires PHP: 7.4
16 * WooFunnels: true
17 *
18 * Funnel Builder is free software.
19 * You can redistribute it and/or modify it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation, either version 3 of the License, or
21 * any later version.
22 *
23 * Funnel Builder is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with Funnel Builder. If not, see <http://www.gnu.org/licenses/>.
30 */
31
32 defined( 'ABSPATH' ) || exit; // Exit if accessed directly
33
34 if ( ! class_exists( 'WFFN_Core' ) ) {
35
36 /**
37 * Class WFFN_Core
38 */
39 #[AllowDynamicProperties]
40 class WFFN_Core {
41
42 /**
43 * @var null
44 */
45 public static $_instance = null;
46
47 /**
48 * @var array
49 */
50 private static $_registered_entity = array(
51 'active' => array(),
52 'inactive' => array(),
53 );
54
55 /**
56 * @var WFFN_Admin
57 */
58 public $admin;
59
60 public $assets;
61
62 /**
63 * @var WFFN_Steps
64 */
65 public $steps;
66
67 /**
68 * @var WFFN_Substeps
69 */
70 public $substeps;
71 /**
72 * @var WFFN_Data
73 */
74 public $data;
75
76 /**
77 * @var WFFN_Logger
78 */
79 public $logger;
80
81 /**
82 * @var WFFN_Importer
83 */
84 public $import;
85
86 /**
87 * @var WFFN_Remote_Template_Importer
88 */
89 public $remote_importer;
90
91 /**
92 * @var WFFN_Page_Builder_Manager
93 */
94 public $page_builders;
95
96 /**
97 * @var WFFN_Landing_Pages
98 */
99 public $landing_pages;
100
101 /**
102 * @var WFFN_Funnel_Contacts
103 */
104 public $wffn_contacts;
105
106 /**
107 * @var WFFN_Thank_You_WC_Pages
108 */
109 public $thank_you_pages;
110
111 /** @var WFFN_Funnels_DB */
112 public $funnels_db = null;
113
114 /** @var WFFN_Template_Importer */
115 public $importer = null;
116
117 /** @var WFFN_Public */
118 public $public = null;
119
120 /** @var WFFN_WP_User_AutoLogin */
121 public $autologin = null;
122
123 /** @var WFFN_Role_Capability */
124 public $role = null;
125
126 /** @var WFFN_Admin_Notifications */
127 public $admin_notifications = null;
128
129 /**
130 * WFFN_Core constructor.
131 */
132 public function __construct() {
133
134 /**
135 * Load important variables and constants
136 */
137 $this->define_plugin_properties();
138 require_once __DIR__ . '/start.php';
139 require __DIR__ . '/includes/wffn-functions.php';
140 /**
141 * Wire Funnel Builder's own framework classes (subcore/) into the core kernel.
142 * subcore/load.php only registers them onto the kernel's bwf_kernel_* filters --
143 * the core kernel does the actual loading, and only when FB's own dismantled core
144 * is the copy that wins arbitration (a full core carries these classes itself).
145 * subcore/ sits at the FB plugin root, NOT inside the shared woofunnels core:
146 * nothing plugin-specific remains in woofunnels/, and no other FunnelKit plugin
147 * references this folder. Its files are all __DIR__-relative, so it can live
148 * anywhere FB ships it.
149 */
150 require_once __DIR__ . '/subcore/load.php';
151 /**
152 * Transition arbitration: withdraw our dismantled core if an un-dismantled
153 * full core is present, so it wins include_core() below. See
154 * WooFunnel_WFFN::maybe_yield_to_full_core().
155 *
156 * MUST run before the FIRST include_core() of the request. include_core is
157 * triggered by many sibling plugins at assorted plugins_loaded priorities
158 * (some as early as -99, e.g. via a Pro/checkout module), not just our own
159 * -1 below -- and whoever fires it first locks WooFunnel_Loader::$loaded, so
160 * a late withdrawal is a no-op. No sibling calls include_core at file-load
161 * (all are inside plugins_loaded callbacks), so PHP_INT_MIN guarantees we
162 * withdraw first. (Cannot live in register()/file-load: sibling full cores
163 * that register at file-load load AFTER us, so the pool is not yet complete
164 * there; and the automation registers even later, on plugins_loaded:1 -- the
165 * hook force-registers those via file-probe.)
166 */
167 add_action( 'plugins_loaded', array( 'WooFunnel_WFFN', 'maybe_yield_to_full_core' ), PHP_INT_MIN );
168 add_action( 'plugins_loaded', array( 'WooFunnel_Loader', 'include_core' ), - 1 );
169
170 /**
171 * Loads hooks
172 */
173 $this->load_hooks();
174 }
175
176 /**
177 * Defining constants
178 */
179 public function define_plugin_properties() {
180
181 define( 'WFFN_VERSION', '3.16.0.2' );
182 define( 'WFFN_BWF_VERSION', '1.10.12.84' );
183
184 define( 'WFFN_MIN_WC_VERSION', '3.5.0' );
185 define( 'WFFN_MIN_WP_VERSION', '5.4.0' );
186 /**
187 * Lowest Funnel Builder Pro build that pairs with this release. Older Pro
188 * builds keep loading, but features whose code moved out of this plugin
189 * stop working, so an admin notice asks for a Pro update.
190 * Bump on every release that moves or removes code Pro depends on.
191 */
192 define( 'WFFN_MIN_PRO_VERSION', '3.16.0' );
193 define( 'WFFN_DB_VERSION', '4.0.0' );
194 define( 'WFFN_REVIEW_RATING_COUNT', 897 );
195 define( 'WFFN_SLUG', 'wffn' );
196 define( 'WFFN_PLUGIN_FILE', __FILE__ );
197 define( 'WFFN_PLUGIN_DIR', __DIR__ );
198 define( 'WFFN_PLUGIN_URL', untrailingslashit( plugin_dir_url( WFFN_PLUGIN_FILE ) ) );
199 define( 'WFFN_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
200 define( 'WFFN_TEMPLATE_UPLOAD_DIR', $this->get_content_dir() . '/wffn_templates/' );
201 ( defined( 'WFFN_IS_DEV' ) && true === WFFN_IS_DEV ) ? define( 'WFFN_VERSION_DEV', time() ) : define( 'WFFN_VERSION_DEV', WFFN_VERSION );
202 ( ! defined( 'WFFN_REACT_ENVIRONMENT' ) ) ? define( 'WFFN_REACT_ENVIRONMENT', 1 ) : '';
203 }
204
205 public function get_content_dir() {
206 return wp_upload_dir()['basedir'];
207 }
208
209 /**
210 * Load classes on plugins_loaded hook
211 */
212 public function load_hooks() {
213 add_action( 'plugins_loaded', array( $this, 'load_classes' ), 1 );
214 add_action( 'plugins_loaded', array( $this, 'register_classes' ), 1 );
215
216 register_activation_hook( __FILE__, array( $this, 'plugin_activation_hook' ) );
217
218 add_action( 'activated_plugin', array( $this, 'on_activated_plugin' ) );
219
220 if ( ! class_exists( 'WFACP_Core' ) ) {
221
222 require __DIR__ . '/modules/checkouts/woofunnels-aero-checkout-lite.php';
223 }
224 if ( ! class_exists( 'WFOPP_Core' ) ) {
225 require __DIR__ . '/modules/optins/woofunnels-optins.php';
226 }
227 add_action( 'plugins_loaded', array( $this, 'init_oxygen' ), 10 );
228 add_action( 'wp_loaded', array( $this, 'load_divi_importer' ), 150 );
229 add_action( 'activated_plugin', array( $this, 'check_activation' ) );
230
231 // Define a constant for the plugin file, if not already defined.
232 define( 'FUNNELKIT_BRICKS_INTEGRATION_FILE', __DIR__ . '/includes/bricks-builder/' );
233 // Require the class file for Funnelkit Bricks Integration.
234 require_once __DIR__ . '/includes/bricks-builder/includes/class-bricks-integration.php';
235 }
236
237 /**
238 *
239 */
240 public function load_classes() {
241
242 try {
243 /**
244 * Loads all the admin
245 */
246 $this->load_autoloader();
247 $this->load_admin();
248 $this->load_includes();
249 $this->load_modules();
250 $this->load_steps();
251 $this->load_commons();
252 $this->load_analytics();
253
254 /**
255 * Deferred activation hook: fires only after all classes are
256 * loaded, unlike activated_plugin.
257 */
258 $activated_plugin = get_transient( 'wffn_activated_plugin' );
259 if ( $activated_plugin ) {
260 delete_transient( 'wffn_activated_plugin' );
261 do_action( 'wffn_activated_plugin', $activated_plugin );
262 }
263 } catch ( Exception |Error $e ) {
264 // do nothing here
265 }
266 }
267
268 /**
269 * Loads the admin
270 */
271 public function load_admin() {
272 include_once __DIR__ . '/admin/class-wffn-admin.php';
273 include_once __DIR__ . '/admin/class-wffn-pro-update-required.php';
274 include_once __DIR__ . '/admin/class-bwf-admin-breadcrumbs.php';
275 include_once __DIR__ . '/admin/class-bwf-admin-settings.php';
276 include_once __DIR__ . '/admin/class-wffn-page-builder-manager.php';
277 include_once __DIR__ . '/admin/class-wffn-admin-notifications.php';
278 include_once __DIR__ . '/admin/rest-api/class-wffn-rest-funnels.php';
279 include_once __DIR__ . '/admin/rest-api/class-wffn-rest-steps.php';
280 include_once __DIR__ . '/admin/rest-api/class-wffn-rest-substeps.php';
281 include_once __DIR__ . '/admin/rest-api/class-wffn-rest-funnel-settings.php';
282 include_once __DIR__ . '/admin/rest-api/class-wffn-api-update-user-preference.php';
283 include_once __DIR__ . '/admin/rest-api/class-wffn-rest-tools.php';
284 include_once __DIR__ . '/admin/rest-api/class-wffn-rest-funnel-canvas.php';
285 include_once __DIR__ . '/admin/rest-api/class-wffn-rest-user-preferences.php';
286 include_once __DIR__ . '/admin/rest-api/class-wffn-rest-notifications.php';
287 include_once __DIR__ . '/admin/rest-api/class-wffn-rest-get-recipes.php';
288 include_once __DIR__ . '/admin/rest-api/class-wffn-rest-setup.php';
289 include_once __DIR__ . '/admin/rest-api/class-wffn-rest-store-checkout.php';
290 include_once __DIR__ . '/admin/rest-api/class-wffn-rest-funnel-modules.php';
291 include_once __DIR__ . '/admin/rest-api-helpers/class-wffn-rest-api-helpers.php';
292 include_once __DIR__ . '/admin/rest-api/class-wffn-rest-optin-api-endpoint.php';
293 include_once __DIR__ . '/admin/rest-api/class-wffn-rest-checkout-api-endpoint.php';
294 include_once __DIR__ . '/admin/rest-api/class-wffn-rest-wizard.php';
295 include_once __DIR__ . '/admin/rest-api/class-wffn-funnel-contacts.php';
296 include_once __DIR__ . '/admin/rest-api/class-wffn-funnel-orders.php';
297 include_once __DIR__ . '/admin/rest-api/class-wffn-rest-api-dashboard-endpoint.php';
298 require_once __DIR__ . '/admin/rest-api/class-wffn-api-send-test-notification.php';
299
300 /*
301 * Order Bump Preview
302 */
303
304 include_once __DIR__ . '/admin/rest-api/class-wfob-bump-rest-api.php';
305
306 /***Global settings*/
307
308 include_once __DIR__ . '/admin/rest-api/class-wffn-rest-global-settings.php';
309
310 /**Global Header */
311 include_once __DIR__ . '/admin/includes/class-wffn-header.php';
312
313 /** JS translations chunk combiner */
314 include_once __DIR__ . '/admin/class-wffn-translations.php';
315 WFFN_Translations::get_instance();
316 }
317
318 /**
319 * Load includes folder
320 */
321 public function load_includes() {
322
323 require __DIR__ . '/includes/class-wffn-logger.php';
324 require __DIR__ . '/includes/class-wffn-session-handler.php';
325 require __DIR__ . '/includes/class-wffn-data.php';
326 require __DIR__ . '/includes/class-wffn-funnels-db.php';
327 require __DIR__ . '/includes/class-wffn-public.php';
328 require __DIR__ . '/includes/class-wffn-funnel.php';
329 require __DIR__ . '/includes/class-wffn-woofunnels-support.php';
330 require __DIR__ . '/merge-tags/class-bwf-contact-tags.php';
331 }
332
333 /**
334 * Include Modules (Landing & thankyou)
335 */
336 public function load_modules() {
337 require __DIR__ . '/includes/class-wffn-module-common.php';
338 require __DIR__ . '/modules/landing-pages/class-wffn-landing-pages.php';
339 require __DIR__ . '/modules/thankyou-pages/class-wffn-thank-you-wc-pages.php';
340 do_action( 'wffn_core_modules_loaded' );
341 }
342
343 /**
344 * Include steps and substeps
345 */
346 public function load_steps() {
347 require __DIR__ . '/includes/class-wffn-step-base.php';
348 require __DIR__ . '/includes/class-wffn-step.php';
349 require __DIR__ . '/includes/class-wffn-steps.php';
350 require __DIR__ . '/includes/class-wffn-substep.php';
351 require __DIR__ . '/includes/class-wffn-substeps.php';
352 }
353
354 /**
355 * Includes common functions.
356 */
357 public function load_commons() {
358
359 require __DIR__ . '/includes/class-wffn-common.php';
360
361 require __DIR__ . '/importer/interface-import-export.php';
362 require __DIR__ . '/importer/class-wffn-template-importer.php';
363 require __DIR__ . '/importer/class-wffn-background-importer.php';
364 require __DIR__ . '/admin/db/wffn-updater-functions.php';
365
366 include_once __DIR__ . '/admin/class-wffn-importer.php';
367
368 $response = WFFN_Common::check_builder_status( 'elementor' );
369 if ( true === $response['found'] && empty( $response['error'] ) ) {
370 require __DIR__ . '/importer/class-wffn-elementor-importer.php';
371 }
372
373 require __DIR__ . '/importer/class-wffn-wp-editor-importer.php';
374 require __DIR__ . '/compatibilities/class-wffn-plugin-compatibilities.php';
375 require __DIR__ . '/includes/class-wffn-conversion-tracking-migrator.php';
376 WFFN_Common::init();
377 }
378
379
380 public function load_divi_importer() {
381
382 try {
383 $response = WFFN_Common::check_builder_status( 'divi' );
384 if ( true === $response['found'] && empty( $response['error'] ) ) {
385 require __DIR__ . '/importer/class-wffn-divi-importer.php';
386 require __DIR__ . '/importer/class-wffn-divi5-importer.php';
387 }
388 $response = WFFN_Common::check_builder_status( 'oxy' );
389 if ( true === $response['found'] && empty( $response['error'] ) ) {
390 require __DIR__ . '/importer/class-wffn-oxygen-importer.php';
391 }
392 require __DIR__ . '/importer/class-wffn-gutenberg-importer.php';
393 } catch ( Exception $e ) {
394 // do nothing here
395 }
396 }
397
398 public function load_analytics() {
399 if ( class_exists( 'WFACP_Core' ) && wffn_is_wc_active() && ! class_exists( 'WFACP_Contacts_Analytics' ) ) {
400 require_once __DIR__ . '/contact-analytics/class-wfacp-contacts-analytics.php';
401 }
402 if ( class_exists( 'WFOPP_Core' ) && ! class_exists( 'WFFN_Optin_Contacts_Analytics' ) ) {
403 require_once __DIR__ . '/contact-analytics/class-wffn-optin-contacts-analytics.php';
404 }
405
406 // Tracking system will be lazy-loaded on demand via autoloader
407 // No need to load classes here - they'll be loaded when tracking data is collected
408 }
409
410 /**
411 * @return WFFN_Core|null
412 */
413 public static function get_instance() {
414 if ( null === self::$_instance ) {
415 self::$_instance = new self();
416 }
417
418 return self::$_instance;
419 }
420
421
422 /**
423 * Register classes
424 */
425 public function register_classes() {
426
427 try {
428 $load_classes = self::get_registered_class();
429 if ( is_array( $load_classes ) && count( $load_classes ) > 0 ) {
430 foreach ( $load_classes as $access_key => $class ) {
431
432 $this->$access_key = $class::get_instance();
433 }
434 do_action( 'wffn_loaded' );
435 }
436 } catch ( Exception $e ) {
437 // do nothing here
438 }
439 }
440
441 /**
442 * @return mixed
443 */
444 public static function get_registered_class() {
445 return self::$_registered_entity['active'];
446 }
447
448 public static function register( $short_name, $class ) { //phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedParameter
449
450 self::$_registered_entity['active'][ $short_name ] = $class;
451 }
452
453 /**
454 * @return WFFN_Funnels_DB
455 */
456 public function get_dB() {
457 if ( empty( $this->funnels_db ) ) {
458 $class = apply_filters( 'wffn_funnels_db_class', 'WFFN_Funnels_DB' );
459 $this->funnels_db = new $class();
460 }
461
462 return $this->funnels_db;
463 }
464
465 public function plugin_activation_hook() {
466 update_option( 'bwf_needs_rewrite', 'yes', true );
467
468 /** Save the plugin first version when the plugin was activated, if not already present */
469 $first_version = get_option( 'wffn_first_v', '' );
470 if ( empty( $first_version ) ) {
471 update_option( 'wffn_first_v', WFFN_VERSION, false );
472
473 }
474 }
475
476 public function get_plugin_url() {
477 return untrailingslashit( plugin_dir_url( WFFN_PLUGIN_FILE ) );
478 }
479
480 public function load_autoloader() {
481 spl_autoload_register( array( $this, 'autoload' ) );
482 /**
483 * The license classes live in the premium plugin now; the free plugin only
484 * carries inert fallbacks so premium builds released before the relocation
485 * don't fatal. Their autoloader registers once every plugin has finished
486 * booting, so it sits BEHIND every premium loader in the spl queue: the
487 * premium copy always gets the first chance to supply the real classes,
488 * and the fallback fires only when nothing else has defined them.
489 */
490 add_action( 'plugins_loaded', array( $this, 'load_license_fallback_autoloader' ), 9999 );
491 }
492
493 public function load_license_fallback_autoloader() {
494 spl_autoload_register( array( $this, 'autoload_license_fallbacks' ) );
495 }
496
497 public function autoload_license_fallbacks( $class_name ) {
498 $license_classes = array( 'woofunnels_licenses', 'woofunnels_license_check', 'woofunnels_license_controller' );
499 if ( in_array( strtolower( $class_name ), $license_classes, true ) ) {
500 require_once WFFN_PLUGIN_DIR . '/includes/class-woofunnels-licenses.php'; // phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingCustomConstant
501 }
502 }
503
504 public function autoload( $class_name ) {
505 if ( false !== strpos( $class_name, 'WFFN_' ) ) {
506 $filename = basename( 'class-' . $this->slugify_classname( $class_name ) . '.php' );
507 $file_path = WFFN_PLUGIN_DIR . '/includes/' . $filename;
508
509 if ( file_exists( $file_path ) ) {
510 $real_path = realpath( $file_path );
511 $real_includes = realpath( WFFN_PLUGIN_DIR . '/includes/' );
512
513 if ( false !== $real_path && false !== $real_includes && 0 === strpos( $real_path, $real_includes ) ) {
514 require_once $real_path; // phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingCustomConstant
515 }
516 }
517 }
518 }
519
520 /**
521 * Stores a transient on activation so wffn_activated_plugin can fire
522 * later in plugins_loaded, once classes exist.
523 *
524 * @param string $filename Activated plugin filename.
525 */
526 public function on_activated_plugin( $filename ) {
527 if ( '/funnel-builder.php' === substr( $filename, -19 ) ) {
528 set_transient( 'wffn_activated_plugin', $filename );
529 }
530 }
531
532 public function slugify_classname( $class_name ) {
533 $classname = $this->custom_sanitize_title( $class_name );
534 $classname = str_replace( '_', '-', $classname );
535
536 return $classname;
537 }
538
539 private function custom_sanitize_title( $title ) {
540 $title = remove_accents( $title );
541 $title = sanitize_title_with_dashes( $title );
542
543 return $title;
544 }
545
546 public function init_oxygen() {
547 if ( class_exists( 'OxygenElement' ) ) {
548 require_once __DIR__ . '/includes/class-abstract-wffn-oxygen-fields.php';
549 }
550 }
551
552 /**
553 * Added redirection on plugin activation
554 *
555 * @param $plugin
556 */
557 public function check_activation( $plugin ) {
558 if ( $plugin === plugin_basename( WFFN_PLUGIN_FILE ) ) {
559 $pro_first_active = get_option( 'fk_fb_active_date', array() );
560 if ( empty( $pro_first_active ) || ! isset( $pro_first_active['lite'] ) ) {
561 $pro_first_active['lite'] = current_time( 'timestamp' );
562 update_option( 'fk_fb_active_date', $pro_first_active, false );
563 }
564 }
565 if ( ( defined( 'WFFN_PRO_FILE' ) && $plugin === plugin_basename( WFFN_PRO_FILE ) ) || ( defined( 'WFFN_BASIC_FILE' ) && $plugin === plugin_basename( WFFN_BASIC_FILE ) ) ) {
566 $pro_first_active = get_option( 'fk_fb_active_date', array() );
567 if ( empty( $pro_first_active ) || ! isset( $pro_first_active['pro'] ) ) {
568 $pro_first_active['pro'] = current_time( 'timestamp' );
569 update_option( 'fk_fb_active_date', $pro_first_active, false );
570 }
571 }
572 }
573 }
574 }
575 if ( ! function_exists( 'WFFN_Core' ) ) {
576 /**
577 * @return WFFN_Core|null
578 */
579 function WFFN_Core() { //@codingStandardsIgnoreLine
580 return WFFN_Core::get_instance();
581 }
582 }
583
584 $GLOBALS['WFFN_Core'] = WFFN_Core();
585