PluginProbe
CartFlows – Funnel Builder & Checkout Plugin for WooCommerce / 3.3.0
CartFlows – Funnel Builder & Checkout Plugin for WooCommerce v3.3.0
3.3.0 3.2.1 3.2.0 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.1 trunk 1.0.4 1.1.0 1.1.0.1 1.1.1 1.1.10 1.1.11 1.1.12 1.1.13 1.1.14 1.1.15 1.1.16 1.1.17 1.1.18 1.1.19 1.1.2 All 162 releases
← All changes | classes/class-cartflows-loader.php +767 -436 1.1.14 → 3.3.0 View file →
@@ -1,436 +1,767 @@
1 -<?php
2 -/**
3 - * CartFlows Loader.
4 - *
5 - * @package CartFlows
6 - */
7 -
8 -if ( ! class_exists( 'Cartflows_Loader' ) ) {
9 -
10 - /**
11 - * Class Cartflows_Loader.
12 - */
13 - final class Cartflows_Loader {
14 -
15 - /**
16 - * Member Variable
17 - *
18 - * @var instance
19 - */
20 - private static $instance = null;
21 -
22 - /**
23 - * Member Variable
24 - *
25 - * @var utils
26 - */
27 - public $utils = null;
28 -
29 - /**
30 - * Member Variable
31 - *
32 - * @var logger
33 - */
34 - public $logger = null;
35 -
36 - /**
37 - * Member Variable
38 - *
39 - * @var session
40 - */
41 - public $session = null;
42 -
43 -
44 - /**
45 - * Member Variable
46 - *
47 - * @var options
48 - */
49 - public $options = null;
50 -
51 - /**
52 - * Member Variable
53 - *
54 - * @var meta
55 - */
56 - public $meta = null;
57 -
58 - /**
59 - * Member Variable
60 - *
61 - * @var flow
62 - */
63 - public $flow = null;
64 -
65 - /**
66 - * Member Variable
67 - *
68 - * @var assets_vars
69 - */
70 - public $assets_vars = null;
71 -
72 - /**
73 - * Initiator
74 - */
75 - public static function get_instance() {
76 -
77 - if ( is_null( self::$instance ) ) {
78 -
79 - self::$instance = new self;
80 -
81 - /**
82 - * CartFlows loaded.
83 - *
84 - * Fires when Cartflows was fully loaded and instantiated.
85 - *
86 - * @since 1.0.0
87 - */
88 - do_action( 'cartflows_loaded' );
89 - }
90 -
91 - return self::$instance;
92 - }
93 -
94 - /**
95 - * Constructor
96 - */
97 - public function __construct() {
98 -
99 - $this->define_constants();
100 -
101 - // Activation hook.
102 - register_activation_hook( CARTFLOWS_FILE, array( $this, 'activation_reset' ) );
103 -
104 - // deActivation hook.
105 - register_deactivation_hook( CARTFLOWS_FILE, array( $this, 'deactivation_reset' ) );
106 -
107 - add_action( 'plugins_loaded', array( $this, 'load_plugin' ), 99 );
108 - add_action( 'plugins_loaded', array( $this, 'load_cf_textdomain' ) );
109 - add_action( 'wp_loaded', array( $this, 'initialize' ) );
110 -
111 - // Update compatibility.
112 - require_once CARTFLOWS_DIR . 'classes/class-cartflows-update.php';
113 - }
114 -
115 - /**
116 - * Defines all constants
117 - *
118 - * @since 1.0.0
119 - */
120 - public function define_constants() {
121 -
122 - define( 'CARTFLOWS_BASE', plugin_basename( CARTFLOWS_FILE ) );
123 - define( 'CARTFLOWS_DIR', plugin_dir_path( CARTFLOWS_FILE ) );
124 - define( 'CARTFLOWS_URL', plugins_url( '/', CARTFLOWS_FILE ) );
125 - define( 'CARTFLOWS_VER', '1.1.14' );
126 - define( 'CARTFLOWS_SLUG', 'cartflows' );
127 - define( 'CARTFLOWS_SETTINGS', 'cartflows_settings' );
128 -
129 - define( 'CARTFLOWS_FLOW_POST_TYPE', 'cartflows_flow' );
130 - define( 'CARTFLOWS_STEP_POST_TYPE', 'cartflows_step' );
131 -
132 - if ( ! defined( 'CARTFLOWS_SERVER_URL' ) ) {
133 - define( 'CARTFLOWS_SERVER_URL', 'https://my.cartflows.com/' );
134 - }
135 - define( 'CARTFLOWS_DOMAIN_URL', 'https://cartflows.com/' );
136 - define( 'CARTFLOWS_TEMPLATES_URL', 'https://templates.cartflows.com/' );
137 - define( 'CARTFLOWS_TAXONOMY_STEP_TYPE', 'cartflows_step_type' );
138 - define( 'CARTFLOWS_TAXONOMY_STEP_FLOW', 'cartflows_step_flow' );
139 -
140 - if ( ! defined( 'CARTFLOWS_TAXONOMY_STEP_PAGE_BUILDER' ) ) {
141 - define( 'CARTFLOWS_TAXONOMY_STEP_PAGE_BUILDER', 'cartflows_step_page_builder' );
142 - }
143 - if ( ! defined( 'CARTFLOWS_TAXONOMY_FLOW_PAGE_BUILDER' ) ) {
144 - define( 'CARTFLOWS_TAXONOMY_FLOW_PAGE_BUILDER', 'cartflows_flow_page_builder' );
145 - }
146 - if ( ! defined( 'CARTFLOWS_TAXONOMY_FLOW_CATEGORY' ) ) {
147 - define( 'CARTFLOWS_TAXONOMY_FLOW_CATEGORY', 'cartflows_flow_category' );
148 - }
149 - }
150 -
151 - /**
152 - * Loads plugin files.
153 - *
154 - * @since 1.0.0
155 - *
156 - * @return void
157 - */
158 - function load_plugin() {
159 -
160 - if ( ! function_exists( 'WC' ) ) {
161 - add_action( 'admin_notices', array( $this, 'fails_to_load' ) );
162 - return;
163 - }
164 -
165 - $this->load_helper_files_components();
166 - $this->load_core_files();
167 - $this->load_core_components();
168 -
169 - /**
170 - * CartFlows Init.
171 - *
172 - * Fires when Cartflows is instantiated.
173 - *
174 - * @since 1.0.0
175 - */
176 - do_action( 'cartflows_init' );
177 - }
178 -
179 - /**
180 - * Load Helper Files and Components.
181 - *
182 - * @since 1.0.0
183 - *
184 - * @return void
185 - */
186 - function load_helper_files_components() {
187 -
188 - /* Public Utils */
189 - include_once CARTFLOWS_DIR . 'classes/class-cartflows-utils.php';
190 -
191 - /* Public Session */
192 - include_once CARTFLOWS_DIR . 'classes/class-cartflows-session.php';
193 -
194 - /* Public Global namespace functions */
195 - include_once CARTFLOWS_DIR . 'classes/class-cartflows-functions.php';
196 -
197 - /* Admin Helper */
198 - include_once CARTFLOWS_DIR . 'classes/class-cartflows-helper.php';
199 -
200 - /* Meta Default Values */
201 - include_once CARTFLOWS_DIR . 'classes/class-cartflows-default-meta.php';
202 -
203 - $this->utils = Cartflows_Utils::get_instance();
204 - $this->session = Cartflows_Session::get_instance();
205 - $this->options = Cartflows_Default_Meta::get_instance();
206 - }
207 -
208 - /**
209 - * Init hooked function.
210 - *
211 - * @since 1.0.0
212 - *
213 - * @return void
214 - */
215 - function initialize() {
216 - $this->assets_vars = $this->utils->get_assets_path();
217 - }
218 -
219 - /**
220 - * Load Core Files.
221 - *
222 - * @since 1.0.0
223 - *
224 - * @return void
225 - */
226 - function load_core_files() {
227 -
228 - /* Page builder compatibilty class */
229 - include_once CARTFLOWS_DIR . 'classes/class-cartflows-compatibility.php';
230 -
231 - /* Admin Meta Fields*/
232 - include_once CARTFLOWS_DIR . 'classes/fields/typography/class-cartflows-font-families.php';
233 - include_once CARTFLOWS_DIR . 'classes/class-cartflows-meta-fields.php';
234 - include_once CARTFLOWS_DIR . 'classes/class-cartflows-meta.php';
235 -
236 - /* Cloning */
237 - include_once CARTFLOWS_DIR . 'classes/class-cartflows-cloning.php';
238 -
239 - /* Admin Settings */
240 - include_once CARTFLOWS_DIR . 'classes/class-cartflows-admin.php';
241 -
242 - /* Core Modules */
243 - include_once CARTFLOWS_DIR . 'classes/class-cartflows-logger.php';
244 -
245 - /* Frontend Global */
246 - include_once CARTFLOWS_DIR . 'classes/class-cartflows-frontend.php';
247 - require_once CARTFLOWS_DIR . 'classes/class-cartflows-flow-frontend.php';
248 -
249 - /* Modules */
250 - include_once CARTFLOWS_DIR . 'modules/flow/class-cartflows-flow.php';
251 - include_once CARTFLOWS_DIR . 'modules/landing/class-cartflows-landing.php';
252 - include_once CARTFLOWS_DIR . 'modules/checkout/class-cartflows-checkout.php';
253 - include_once CARTFLOWS_DIR . 'modules/thankyou/class-cartflows-thankyou.php';
254 -
255 - include_once CARTFLOWS_DIR . 'classes/class-cartflows-api.php';
256 - include_once CARTFLOWS_DIR . 'classes/class-cartflows-importer-core.php';
257 -
258 - include_once CARTFLOWS_DIR . 'classes/batch-process/class-cartflows-batch-process.php';
259 - include_once CARTFLOWS_DIR . 'classes/class-cartflows-importer.php';
260 - }
261 -
262 - /**
263 - * Load Core Components.
264 - *
265 - * @since 1.0.0
266 - *
267 - * @return void
268 - */
269 - function load_core_components() {
270 -
271 - $this->meta = Cartflows_Meta_Fields::get_instance();
272 - $this->logger = Cartflows_Logger::get_instance();
273 - $this->flow = Cartflows_Flow_Frontend::get_instance();
274 - }
275 -
276 - /**
277 - * Load CartFlows Pro Text Domain.
278 - * This will load the translation textdomain depending on the file priorities.
279 - * 1. Global Languages /wp-content/languages/cartflows/ folder
280 - * 2. Local dorectory /wp-content/plugins/cartflows/languages/ folder
281 - *
282 - * @since 1.0.3
283 - * @return void
284 - */
285 - public function load_cf_textdomain() {
286 -
287 - // Default languages directory for CartFlows Pro.
288 - $lang_dir = CARTFLOWS_DIR . 'languages/';
289 -
290 - /**
291 - * Filters the languages directory path to use for CartFlows Pro.
292 - *
293 - * @param string $lang_dir The languages directory path.
294 - */
295 - $lang_dir = apply_filters( 'cartflows_languages_directory', $lang_dir );
296 -
297 - // Traditional WordPress plugin locale filter.
298 - global $wp_version;
299 -
300 - $get_locale = get_locale();
301 -
302 - if ( $wp_version >= 4.7 ) {
303 - $get_locale = get_user_locale();
304 - }
305 -
306 - /**
307 - * Language Locale for CartFlows Pro
308 - *
309 - * @var $get_locale The locale to use.
310 - * Uses get_user_locale()` in WordPress 4.7 or greater,
311 - * otherwise uses `get_locale()`.
312 - */
313 - $locale = apply_filters( 'plugin_locale', $get_locale, 'cartflows' );
314 - $mofile = sprintf( '%1$s-%2$s.mo', 'cartflows', $locale );
315 -
316 - // Setup paths to current locale file.
317 - $mofile_local = $lang_dir . $mofile;
318 - $mofile_global = WP_LANG_DIR . '/plugins/' . $mofile;
319 -
320 - if ( file_exists( $mofile_global ) ) {
321 - // Look in global /wp-content/languages/cartflows/ folder.
322 - load_textdomain( 'cartflows', $mofile_global );
323 - } elseif ( file_exists( $mofile_local ) ) {
324 - // Look in local /wp-content/plugins/cartflows/languages/ folder.
325 - load_textdomain( 'cartflows', $mofile_local );
326 - } else {
327 - // Load the default language files.
328 - load_plugin_textdomain( 'cartflows', false, $lang_dir );
329 - }
330 - }
331 -
332 - /**
333 - * Fires admin notice when Elementor is not installed and activated.
334 - *
335 - * @since 1.0.0
336 - *
337 - * @return void
338 - */
339 - public function fails_to_load() {
340 -
341 - $screen = get_current_screen();
342 -
343 - if ( isset( $screen->parent_file ) && 'plugins.php' === $screen->parent_file && 'update' === $screen->id ) {
344 - return;
345 - }
346 -
347 - $class = 'notice notice-error';
348 - /* translators: %s: html tags */
349 - $message = sprintf( __( 'The %1$sCartFlows%2$s plugin requires %1$sWooCommerce%2$s plugin installed & activated.', 'cartflows' ), '<strong>', '</strong>' );
350 -
351 - $plugin = 'woocommerce/woocommerce.php';
352 -
353 - if ( _is_woo_installed() ) {
354 - if ( ! current_user_can( 'activate_plugins' ) ) {
355 - return;
356 - }
357 -
358 - $action_url = wp_nonce_url( 'plugins.php?action=activate&amp;plugin=' . $plugin . '&amp;plugin_status=all&amp;paged=1&amp;s', 'activate-plugin_' . $plugin );
359 - $button_label = __( 'Activate WooCommerce', 'cartflows' );
360 -
361 - } else {
362 - if ( ! current_user_can( 'install_plugins' ) ) {
363 - return;
364 - }
365 -
366 - $action_url = wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=woocommerce' ), 'install-plugin_woocommerce' );
367 - $button_label = __( 'Install WooCommerce', 'cartflows' );
368 - }
369 -
370 - $button = '<p><a href="' . $action_url . '" class="button-primary">' . $button_label . '</a></p><p></p>';
371 -
372 - printf( '<div class="%1$s"><p>%2$s</p>%3$s</div>', esc_attr( $class ), $message, $button );
373 - }
374 -
375 - /**
376 - * Activation Reset
377 - */
378 - function activation_reset() {
379 -
380 - include_once CARTFLOWS_DIR . 'modules/flow/classes/class-cartflows-flow-post-type.php';
381 - include_once CARTFLOWS_DIR . 'modules/flow/classes/class-cartflows-step-post-type.php';
382 -
383 - Cartflows_Flow_Post_Type::get_instance()->flow_post_type();
384 - Cartflows_Step_Post_Type::get_instance()->step_post_type();
385 - flush_rewrite_rules();
386 - }
387 -
388 - /**
389 - * Deactivation Reset
390 - */
391 - function deactivation_reset() {
392 - }
393 -
394 - /**
395 - * Logger Class Instance
396 - */
397 - function logger() {
398 - return Cartflows_Logger::get_instance();
399 - }
400 -
401 -
402 - }
403 -
404 - /**
405 - * Prepare if class 'Cartflows_Loader' exist.
406 - * Kicking this off by calling 'get_instance()' method
407 - */
408 - Cartflows_Loader::get_instance();
409 -}
410 -
411 -/**
412 - * Get global class.
413 - *
414 - * @return object
415 - */
416 -function wcf() {
417 - return Cartflows_Loader::get_instance();
418 -}
419 -
420 -if ( ! function_exists( '_is_woo_installed' ) ) {
421 -
422 - /**
423 - * Is woocommerce plugin installed.
424 - *
425 - * @since 1.0.0
426 - *
427 - * @access public
428 - */
429 - function _is_woo_installed() {
430 -
431 - $path = 'woocommerce/woocommerce.php';
432 - $plugins = get_plugins();
433 -
434 - return isset( $plugins[ $path ] );
435 - }
436 -}
1 +<?php
2 +/**
3 + * CartFlows Loader.
4 + *
5 + * @package CartFlows
6 + */
7 +
8 +// Exit if accessed directly.
9 +if ( ! defined( 'ABSPATH' ) ) {
10 + exit;
11 +}
12 +if ( ! class_exists( 'Cartflows_Loader' ) ) {
13 +
14 + /**
15 + * Class Cartflows_Loader.
16 + */
17 + final class Cartflows_Loader {
18 +
19 + /**
20 + * Member Variable
21 + *
22 + * @var instance
23 + */
24 + private static $instance = null;
25 +
26 + /**
27 + * Member Variable
28 + *
29 + * @var utils
30 + */
31 + public $utils = null;
32 +
33 + /**
34 + * Member Variable
35 + *
36 + * @var logger
37 + */
38 + public $logger = null;
39 +
40 + /**
41 + * Member Variable
42 + *
43 + * @var options
44 + */
45 + public $options = null;
46 +
47 + /**
48 + * Member Variable
49 + *
50 + * @var meta
51 + */
52 + public $meta = null;
53 +
54 + /**
55 + * Member Variable
56 + *
57 + * @var Tracking_Data
58 + */
59 + public $alldata;
60 +
61 + /**
62 + * Member Variable
63 + *
64 + * @var flow
65 + */
66 + public $flow = null;
67 +
68 + /**
69 + * Member Variable
70 + *
71 + * @var wcf_step_objs
72 + */
73 +
74 + public $wcf_step_objs = array();
75 +
76 + /**
77 + * Member Variable
78 + *
79 + * @var assets_vars
80 + */
81 + public $assets_vars = null;
82 +
83 + /**
84 + * Member Variable
85 + *
86 + * @var assets_vars
87 + */
88 +
89 + public $is_woo_active = true;
90 +
91 + /**
92 + * Initiator
93 + */
94 + public static function get_instance() {
95 + if ( is_null( self::$instance ) ) {
96 +
97 + self::$instance = new self();
98 +
99 + /**
100 + * CartFlows loaded.
101 + *
102 + * Fires when Cartflows was fully loaded and instantiated.
103 + *
104 + * @since 1.0.0
105 + */
106 + do_action( 'cartflows_loaded' );
107 + }
108 +
109 + return self::$instance;
110 + }
111 +
112 + /**
113 + * Constructor
114 + */
115 + public function __construct() {
116 + $this->define_constants();
117 +
118 + // Activation hook.
119 + register_activation_hook( CARTFLOWS_FILE, array( $this, 'activation_reset' ) );
120 +
121 + // deActivation hook.
122 + register_deactivation_hook( CARTFLOWS_FILE, array( $this, 'deactivation_reset' ) );
123 +
124 + // Need to add library before the plugin loaded. https://actionscheduler.org/usage/.
125 + require_once CARTFLOWS_DIR . '/libraries/action-scheduler/action-scheduler.php';
126 +
127 + add_action( 'plugins_loaded', array( $this, 'load_plugin' ), 99 );
128 + add_action( 'init', array( $this, 'load_cf_textdomain' ) );
129 +
130 + // Priority 5 mirrors Astra's init_bsf_analytics() pattern: set_entity() must
131 + // run before BSF_Analytics_Loader::load_analytics() fires at priority 10.
132 + add_action( 'init', array( $this, 'deactivation_survey_data_handler' ), 5 );
133 + }
134 +
135 + /**
136 + * Defines all constants
137 + *
138 + * @since 1.0.0
139 + */
140 + public function define_constants() {
141 +
142 + define( 'CARTFLOWS_BASE', plugin_basename( CARTFLOWS_FILE ) );
143 + define( 'CARTFLOWS_DIR', plugin_dir_path( CARTFLOWS_FILE ) );
144 + define( 'CARTFLOWS_URL', plugins_url( '/', CARTFLOWS_FILE ) );
145 +
146 + define( 'CARTFLOWS_VER', '3.3.0' );
147 + define( 'CARTFLOWS_SLUG', 'cartflows' );
148 + define( 'CARTFLOWS_SETTINGS', 'cartflows_settings' );
149 + define( 'CARTFLOWS_NAME', 'CartFlows' );
150 +
151 + define( 'CARTFLOWS_REQ_CF_PRO_VER', '3.2.0' );
152 +
153 + // Resolves to true for users upgrading from <3.0.0 (set by Cartflows_Update on first 3.0+ admin_init)
154 + // and stays true until the user opts out via the Advanced-tab toggle or the legacy in-app switch.
155 + // Fresh installs never see this option set, so they default to the new UI. The toggle saves
156 + // 'enable'/'disable' strings; older code paths may have stored a boolean true — accept both.
157 + $cartflows_legacy_admin_saved = get_option( 'cartflows-legacy-admin', false );
158 + define( 'CARTFLOWS_LEGACY_ADMIN', in_array( $cartflows_legacy_admin_saved, array( true, 1, '1', 'enable', 'yes' ), true ) );
159 +
160 + define( 'CARTFLOWS_ASSETS_VERSION', get_option( 'cartflows-assets-version', time() ) );
161 +
162 + define( 'CARTFLOWS_FLOW_POST_TYPE', 'cartflows_flow' );
163 + define( 'CARTFLOWS_STEP_POST_TYPE', 'cartflows_step' );
164 +
165 + define( 'CARTFLOWS_FLOW_PERMALINK_SLUG', 'flow' );
166 + define( 'CARTFLOWS_STEP_PERMALINK_SLUG', 'step' );
167 +
168 + if ( ! defined( 'CARTFLOWS_SERVER_URL' ) ) {
169 + define( 'CARTFLOWS_SERVER_URL', 'https://my.cartflows.com/' );
170 + }
171 + if ( ! defined( 'CARTFLOWS_DOMAIN_URL' ) ) {
172 + define( 'CARTFLOWS_DOMAIN_URL', 'https://cartflows.com/' );
173 + }
174 + if ( ! defined( 'CARTFLOWS_TEMPLATES_URL' ) ) {
175 + define( 'CARTFLOWS_TEMPLATES_URL', 'https://templates.cartflows.com/' );
176 + }
177 + define( 'CARTFLOWS_TAXONOMY_STEP_TYPE', 'cartflows_step_type' );
178 + define( 'CARTFLOWS_TAXONOMY_STEP_FLOW', 'cartflows_step_flow' );
179 +
180 + if ( ! defined( 'CARTFLOWS_TAXONOMY_STEP_PAGE_BUILDER' ) ) {
181 + define( 'CARTFLOWS_TAXONOMY_STEP_PAGE_BUILDER', 'cartflows_step_page_builder' );
182 + }
183 + if ( ! defined( 'CARTFLOWS_TAXONOMY_FLOW_PAGE_BUILDER' ) ) {
184 + define( 'CARTFLOWS_TAXONOMY_FLOW_PAGE_BUILDER', 'cartflows_flow_page_builder' );
185 + }
186 + if ( ! defined( 'CARTFLOWS_TAXONOMY_FLOW_CATEGORY' ) ) {
187 + define( 'CARTFLOWS_TAXONOMY_FLOW_CATEGORY', 'cartflows_flow_category' );
188 + }
189 +
190 + if ( ! defined( 'CARTFLOWS_LOG_DIR' ) ) {
191 +
192 + $upload_dir = wp_upload_dir( null, false );
193 +
194 + define( 'CARTFLOWS_LOG_DIR', $upload_dir['basedir'] . '/cartflows-logs/' );
195 + }
196 +
197 + $cookie_prefix = '';
198 +
199 + if ( defined( 'CARTFLOWS_COOKIE_PREFIX' ) ) {
200 + $cookie_prefix = CARTFLOWS_COOKIE_PREFIX;
201 + }
202 +
203 + define( 'CARTFLOWS_ACTIVE_CHECKOUT', $cookie_prefix . 'wcf_active_checkout' );
204 +
205 + define( 'CARTFLOWS_PINTEREST_CONSENT', $cookie_prefix . 'cartflows_pinterest_consent' );
206 +
207 + if ( ! defined( 'CARTFLOWS_HTTPS' ) ) {
208 + define( 'CARTFLOWS_HTTPS', is_ssl() ? true : false );
209 + }
210 +
211 + define( 'CARTFLOWS_NPS_WEBHOOK_URL', 'https://webhook.ottokit.com/ottokit/af2151cc-6fe3-40a4-a9d3-12859be4d602' );
212 +
213 + $GLOBALS['wcf_step'] = null;
214 + }
215 +
216 + /**
217 + * Get site slug
218 + *
219 + * @since 1.6.15
220 + * @return string
221 + */
222 + public function get_site_slug() {
223 + return Cartflows_Helper::get_common_setting( 'default_page_builder' );
224 + }
225 +
226 + /**
227 + * Get site URL
228 + *
229 + * @since 1.6.15
230 + * @param string $page_builder_slug Page builder slug.
231 + * @return string
232 + */
233 + public function get_site_url( $page_builder_slug = '' ) {
234 +
235 + $page_builder_slug = ( ! empty( $page_builder_slug ) ) ? $page_builder_slug : wcf()->get_site_slug();
236 +
237 + if ( ! empty( $page_builder_slug ) ) {
238 + return trailingslashit( CARTFLOWS_TEMPLATES_URL ) . $page_builder_slug . '/';
239 + }
240 +
241 + return CARTFLOWS_TEMPLATES_URL;
242 + }
243 +
244 + /**
245 + * Loads plugin files.
246 + *
247 + * @since 1.0.0
248 + *
249 + * @return void
250 + */
251 + public function load_plugin() {
252 + $this->load_helper_files_components();
253 + $this->load_core_files();
254 + $this->load_core_components();
255 +
256 + add_action( 'wp_loaded', array( $this, 'initialize' ) );
257 + add_action( 'cartflows_pro_init', array( $this, 'after_cartflows_pro_init' ) );
258 +
259 + if ( ! $this->is_woo_active ) {
260 + add_action( 'admin_notices', array( $this, 'fails_to_load' ) );
261 + }
262 +
263 + /**
264 + * CartFlows Init.
265 + *
266 + * Fires when Cartflows is instantiated.
267 + *
268 + * @since 1.0.0
269 + */
270 + do_action( 'cartflows_init' );
271 + }
272 +
273 + /**
274 + * After CartFlows Pro init.
275 + *
276 + * @since 1.1.19
277 + *
278 + * @return void
279 + */
280 + public function after_cartflows_pro_init() {
281 + if ( ! is_admin() ) {
282 + return;
283 + }
284 +
285 + if ( version_compare( CARTFLOWS_PRO_VER, CARTFLOWS_REQ_CF_PRO_VER, '<' ) ) {
286 + add_action( 'admin_notices', array( $this, 'required_cartflows_pro_notice' ) );
287 + }
288 +
289 + if ( version_compare( CARTFLOWS_PRO_VER, '1.11.14', '=' ) && 'starter' === CARTFLOWS_PRO_PLUGIN_TYPE ) {
290 + add_action( 'admin_notices', array( $this, 'show_upgrade_starter_plan_notice' ) );
291 + }
292 + }
293 +
294 + /**
295 + * Show CartFlows Pro: Starter plan update Notice.
296 + *
297 + * @since 1.11.14
298 + *
299 + * @return void
300 + */
301 + public function show_upgrade_starter_plan_notice() {
302 +
303 + $class = 'notice notice-warning wcf-notice';
304 + /* translators: %s: html tags */
305 + $message = sprintf( __( 'The new version of %1$s%3$s%2$s is released. Please download the latest zip to install the new updates. Click here to %4$sdownload%5$s.', 'cartflows' ), '<strong>', '</strong>', CARTFLOWS_PRO_DISPLAY_TITLE, '<a href="https://my.cartflows.com/" target="_blank">', '</a>' );
306 +
307 + printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), wp_kses_post( $message ) );
308 + }
309 +
310 + /**
311 + * Required CartFlows Pro Notice.
312 + *
313 + * @since 1.1.19
314 + *
315 + * @return void
316 + */
317 + public function required_cartflows_pro_notice() {
318 + $required_pro_version = CARTFLOWS_REQ_CF_PRO_VER;
319 +
320 + $class = 'notice notice-warning wcf-notice';
321 + /* translators: %s: html tags */
322 + $message = sprintf( __( 'You are using an older version of %1$s%3$s%2$s. Please update %1$s%3$s%2$s plugin to version %1$s%4$s%2$s or higher.', 'cartflows' ), '<strong>', '</strong>', CARTFLOWS_PRO_DISPLAY_TITLE, $required_pro_version );
323 +
324 + printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), wp_kses_post( $message ) );
325 + }
326 +
327 + /**
328 + * Load Helper Files and Components.
329 + *
330 + * @since 1.0.0
331 + *
332 + * @return void
333 + */
334 + public function load_helper_files_components() {
335 + $this->is_woo_active = function_exists( 'WC' );
336 +
337 + /* Public Utils */
338 + include_once CARTFLOWS_DIR . 'classes/class-cartflows-utils.php';
339 +
340 + /* Public Global Name space Functions */
341 + include_once CARTFLOWS_DIR . 'classes/class-cartflows-functions.php';
342 +
343 + /* Admin Helper */
344 + include_once CARTFLOWS_DIR . 'classes/class-cartflows-helper.php';
345 +
346 + /* Title and SKU scoped search behind the admin product pickers */
347 + include_once CARTFLOWS_DIR . 'classes/class-cartflows-product-search.php';
348 + include_once CARTFLOWS_DIR . 'classes/class-cartflows-coupon-search.php';
349 +
350 + /* Factory objects */
351 + include_once CARTFLOWS_DIR . 'classes/class-cartflows-step-factory.php';
352 +
353 + /* Meta Default Values */
354 + include_once CARTFLOWS_DIR . 'classes/class-cartflows-default-meta.php';
355 +
356 + require_once CARTFLOWS_DIR . 'classes/class-cartflows-tracking.php';
357 + require_once CARTFLOWS_DIR . 'classes/class-cartflows-rollback.php';
358 +
359 + if ( is_admin() ) {
360 + require_once CARTFLOWS_DIR . 'libraries/astra-notices/class-bsf-admin-notices.php';
361 + }
362 +
363 + if ( ! class_exists( 'BSF_Analytics_Loader' ) ) {
364 + require_once CARTFLOWS_DIR . 'libraries/bsf-analytics/class-bsf-analytics-loader.php';
365 + }
366 +
367 + $this->utils = Cartflows_Utils::get_instance();
368 + $this->options = Cartflows_Default_Meta::get_instance();
369 +
370 + // Plugin major update notice.
371 + if ( ! class_exists( 'Cartflows_Plugin_Update_Notifications' ) ) {
372 + require_once CARTFLOWS_DIR . 'libraries/cartflows-plugin-update-notifications/class-cartflows-plugin-update-notifications.php';
373 + }
374 +
375 + // Load the NPS Survey library.
376 + if ( ! class_exists( 'Cartflows_Nps_Survey' ) ) {
377 + require_once CARTFLOWS_DIR . 'libraries/class-cartflows-nps-survey.php';
378 + }
379 +
380 + // Load the CartFlows Pointer library.
381 + if ( ! class_exists( 'Cartflows_Pointer' ) ) {
382 + require_once CARTFLOWS_DIR . 'libraries/cartflows-pointer/class-cartflows-pointer.php';
383 + }
384 + }
385 +
386 + /**
387 + * Deactivation Survey Data Handler
388 + *
389 + * @since 2.1.17
390 + *
391 + * @return void
392 + */
393 + public function deactivation_survey_data_handler() {
394 + $bsf_analytics = BSF_Analytics_Loader::get_instance();
395 +
396 + $bsf_analytics->set_entity(
397 + array(
398 + 'cf' => array(
399 + 'hide_optin_checkbox' => true,
400 + 'product_name' => 'CartFlows',
401 + 'usage_doc_link' => 'https://my.cartflows.com/usage-tracking/',
402 + 'path' => CARTFLOWS_DIR . 'libraries/bsf-analytics',
403 + 'author' => 'CartFlows Inc',
404 + 'deactivation_survey' => apply_filters(
405 + 'cartflows_bsf_analytics_deactivation_survey_data',
406 + array(
407 + array(
408 + 'id' => 'deactivation-survey-cartflows',
409 + 'popup_logo' => CARTFLOWS_URL . 'admin-core/assets/images/cartflows-icon.svg',
410 + 'plugin_slug' => 'cartflows',
411 + 'plugin_version' => CARTFLOWS_VER,
412 + 'popup_title' => __( 'Quick Feedback', 'cartflows' ),
413 + 'support_url' => 'https://cartflows.com/contact/',
414 + 'popup_description' => __( 'If you have a moment, please share why you are deactivating CartFlows:', 'cartflows' ),
415 + 'show_on_screens' => array( 'plugins' ),
416 + ),
417 + )
418 + ),
419 + ),
420 + )
421 + );
422 + }
423 +
424 + /**
425 + * Init hooked function.
426 + *
427 + * @since 1.0.0
428 + *
429 + * @return void
430 + */
431 + public function initialize() {
432 + $this->assets_vars = $this->utils->get_assets_path();
433 + }
434 +
435 + /**
436 + * Load Core Files.
437 + *
438 + * @since 1.0.0
439 + *
440 + * @return void
441 + */
442 + public function load_core_files() {
443 + /* Update compatibility. */
444 + require_once CARTFLOWS_DIR . 'classes/class-cartflows-update.php';
445 +
446 + /* Page builder compatibilty class */
447 + include_once CARTFLOWS_DIR . 'compatibilities/class-cartflows-compatibility.php';
448 +
449 + /* Theme support */
450 + if ( $this->is_woo_active ) {
451 + /* Woo hooks */
452 + include_once CARTFLOWS_DIR . 'classes/class-cartflows-woo-hooks.php';
453 + }
454 +
455 + /* Importer */
456 + include_once CARTFLOWS_DIR . 'classes/importer/class-cartflows-importer-loader.php';
457 +
458 + /* Admin Meta Fields*/
459 + include_once CARTFLOWS_DIR . 'classes/fields/typography/class-cartflows-font-families.php';
460 +
461 + // Learn progress — shared by the Learn REST route and the analytics payload.
462 + include_once CARTFLOWS_DIR . 'classes/class-cartflows-learn-progress.php';
463 +
464 + // Analytics — BSF Analytics Events integration. Loaded on every request so the
465 + // bsf_core_stats filter is registered for both frontend and admin transmissions.
466 + include_once CARTFLOWS_DIR . 'classes/class-cartflows-analytics.php';
467 +
468 + if ( is_admin() ) {
469 +
470 + /* Admin helper */
471 + include_once CARTFLOWS_DIR . 'classes/class-cartflows-admin.php';
472 +
473 + /* Dashboard widget — funnel performance summary on wp-admin/index.php. */
474 + include_once CARTFLOWS_DIR . 'classes/class-cartflows-dashboard-widget.php';
475 + }
476 +
477 + /* Admin loader — fork between legacy (admin-legacy-core/) and current (admin-core/) UI. */
478 + if ( defined( 'CARTFLOWS_LEGACY_ADMIN' ) && CARTFLOWS_LEGACY_ADMIN ) {
479 + include_once CARTFLOWS_DIR . 'admin-legacy-loader.php';
480 + } else {
481 + include_once CARTFLOWS_DIR . 'admin-loader.php';
482 + }
483 +
484 + if ( class_exists( 'WP_CLI' ) ) {
485 + /* WP-CLI registration follows the active UI tree. */
486 + if ( defined( 'CARTFLOWS_LEGACY_ADMIN' ) && CARTFLOWS_LEGACY_ADMIN ) {
487 + require_once CARTFLOWS_DIR . 'admin-legacy-core/inc/wp-cli.php';
488 + } else {
489 + require_once CARTFLOWS_DIR . 'admin-core/inc/wp-cli.php';
490 + }
491 + }
492 +
493 + /* Logger */
494 + include_once CARTFLOWS_DIR . 'classes/logger/class-cartflows-log-handler-interface.php';
495 + include_once CARTFLOWS_DIR . 'classes/logger/class-cartflows-log-handler.php';
496 + include_once CARTFLOWS_DIR . 'classes/logger/class-cartflows-log-handler-file.php';
497 + include_once CARTFLOWS_DIR . 'classes/logger/class-cartflows-log-levels.php';
498 + include_once CARTFLOWS_DIR . 'classes/logger/class-cartflows-logger-interface.php';
499 + include_once CARTFLOWS_DIR . 'classes/logger/class-cartflows-wc-logger.php';
500 +
501 + /* Core Modules */
502 + include_once CARTFLOWS_DIR . 'classes/class-cartflows-logger.php';
503 +
504 + /* Frontend Global */
505 + include_once CARTFLOWS_DIR . 'classes/class-cartflows-frontend.php';
506 + require_once CARTFLOWS_DIR . 'classes/class-cartflows-flow-frontend.php';
507 +
508 + /* Modules */
509 + include_once CARTFLOWS_DIR . 'modules/flow/class-cartflows-flow.php';
510 + include_once CARTFLOWS_DIR . 'modules/landing/class-cartflows-landing.php';
511 +
512 + if ( $this->is_woo_active ) {
513 + include_once CARTFLOWS_DIR . 'modules/checkout/class-cartflows-checkout.php';
514 + include_once CARTFLOWS_DIR . 'modules/thankyou/class-cartflows-thankyou.php';
515 + include_once CARTFLOWS_DIR . 'modules/optin/class-cartflows-optin.php';
516 + include_once CARTFLOWS_DIR . 'modules/woo-dynamic-flow/class-cartflows-woo-dynamic-flow.php';
517 + include_once CARTFLOWS_DIR . 'modules/email-report/class-cartflows-admin-report-emails.php';
518 + include_once CARTFLOWS_DIR . 'modules/frequently-bought-together/class-cartflows-fbt.php';
519 + }
520 +
521 + if ( class_exists( '\Elementor\Plugin' ) ) {
522 + // Load the widgets.
523 + include_once CARTFLOWS_DIR . 'modules/elementor/class-cartflows-el-widgets-loader.php';
524 + }
525 +
526 + if ( class_exists( 'FLBuilder' ) ) {
527 +
528 + include_once CARTFLOWS_DIR . 'modules/beaver-builder/class-cartflows-bb-modules-loader.php';
529 + }
530 +
531 + include_once CARTFLOWS_DIR . 'classes/class-cartflows-admin-notices.php';
532 +
533 + include_once CARTFLOWS_DIR . 'classes/deprecated/deprecated-hooks.php';
534 +
535 + include_once CARTFLOWS_DIR . 'modules/gutenberg/classes/class-cartflows-block-loader.php';
536 +
537 + // Abilities API (WordPress 6.9+).
538 + require_once CARTFLOWS_DIR . 'abilities/class-cartflows-abilities-loader.php';
539 + include_once CARTFLOWS_DIR . 'modules/webhook/class-cartflows-webhook-loader.php';
540 +
541 + include_once CARTFLOWS_DIR . 'modules/content-generation/class-cartflows-ai-init.php';
542 + }
543 +
544 + /**
545 + * Load Core Components.
546 + *
547 + * @since 1.0.0
548 + *
549 + * @return void
550 + */
551 + public function load_core_components() {
552 + $this->logger = Cartflows_Logger::get_instance();
553 + $this->flow = Cartflows_Flow_Frontend::get_instance();
554 + }
555 +
556 + /**
557 + * Create files/directories.
558 + */
559 + public function create_files() {
560 + // Install files and folders for uploading files and prevent hotlinking.
561 + $upload_dir = wp_upload_dir();
562 +
563 + $files = array(
564 + array(
565 + 'base' => CARTFLOWS_LOG_DIR,
566 + 'file' => '.htaccess',
567 + 'content' => 'deny from all',
568 + ),
569 + array(
570 + 'base' => CARTFLOWS_LOG_DIR,
571 + 'file' => 'index.html',
572 + 'content' => '',
573 + ),
574 + );
575 +
576 + foreach ( $files as $file ) {
577 + if ( wp_mkdir_p( $file['base'] ) && ! file_exists( trailingslashit( $file['base'] ) . $file['file'] ) ) {
578 + $file_handle = @fopen( trailingslashit( $file['base'] ) . $file['file'], 'w' ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_system_read_fopen
579 + if ( $file_handle ) {
580 + fwrite( $file_handle, $file['content'] ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fwrite, WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_fwrite
581 + fclose( $file_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fclose
582 + }
583 + }
584 + }
585 + }
586 +
587 + /**
588 + * Load CartFlows Pro Text Domain.
589 + * This will load the translation textdomain depending on the file priorities.
590 + * 1. Global Languages /wp-content/languages/cartflows/ folder
591 + * 2. Local dorectory /wp-content/plugins/cartflows/languages/ folder
592 + *
593 + * @since 1.0.3
594 + * @return void
595 + */
596 + public function load_cf_textdomain() {
597 + // Default languages directory for CartFlows Pro.
598 + $lang_dir = CARTFLOWS_DIR . 'languages/';
599 +
600 + /**
601 + * Filters the languages directory path to use for CartFlows Pro.
602 + *
603 + * @param string $lang_dir The languages directory path.
604 + */
605 + $lang_dir = apply_filters( 'cartflows_languages_directory', $lang_dir );
606 +
607 + // Traditional WordPress plugin locale filter.
608 + global $wp_version;
609 +
610 + $get_locale = get_locale();
611 +
612 + if ( $wp_version >= 4.7 ) {
613 + $get_locale = get_user_locale();
614 + }
615 +
616 + /**
617 + * Language Locale for CartFlows Pro
618 + *
619 + * @var $get_locale The locale to use.
620 + * Uses get_user_locale()` in WordPress 4.7 or greater,
621 + * otherwise uses `get_locale()`.
622 + */
623 + $locale = apply_filters( 'plugin_locale', $get_locale, 'cartflows' );
624 + $mofile = sprintf( '%1$s-%2$s.mo', 'cartflows', $locale );
625 +
626 + // Setup paths to current locale file.
627 + $mofile_local = $lang_dir . $mofile;
628 + $mofile_global = WP_LANG_DIR . '/plugins/' . $mofile;
629 +
630 + if ( file_exists( $mofile_global ) ) {
631 + // Look in global /wp-content/languages/cartflows/ folder.
632 + load_textdomain( 'cartflows', $mofile_global );
633 + } elseif ( file_exists( $mofile_local ) ) {
634 + // Look in local /wp-content/plugins/cartflows/languages/ folder.
635 + load_textdomain( 'cartflows', $mofile_local );
636 + } else {
637 + // Load the default language files.
638 + load_plugin_textdomain( 'cartflows', false, $lang_dir );
639 + }
640 + }
641 +
642 + /**
643 + * Fires admin notice when Elementor is not installed and activated.
644 + *
645 + * @since 1.0.0
646 + *
647 + * @return void
648 + */
649 + public function fails_to_load() {
650 + $screen = get_current_screen();
651 +
652 + if ( ! wcf()->utils->is_step_post_type() ) {
653 + return;
654 + }
655 +
656 + if ( ! wcf()->utils->check_is_woo_required_page() ) {
657 + return;
658 + }
659 +
660 + $skip_notice = false;
661 +
662 + wp_localize_script( 'wcf-global-admin', 'cartflows_woo', array( 'show_update_post' => $skip_notice ) );
663 +
664 + $class = 'notice notice-warning';
665 + /* translators: %s: html tags */
666 + $message = sprintf( __( 'This %1$sCartFlows%2$s page requires %1$sWooCommerce%2$s plugin installed & activated.', 'cartflows' ), '<strong>', '</strong>' );
667 +
668 + $plugin = 'woocommerce/woocommerce.php';
669 +
670 + if ( _is_woo_installed() ) {
671 + if ( ! current_user_can( 'activate_plugins' ) ) {
672 + return;
673 + }
674 +
675 + $action_url = wp_nonce_url( 'plugins.php?action=activate&amp;plugin=' . $plugin . '&amp;plugin_status=all&amp;paged=1&amp;s', 'activate-plugin_' . $plugin );
676 + $button_label = __( 'Activate WooCommerce', 'cartflows' );
677 + } else {
678 + if ( ! current_user_can( 'install_plugins' ) ) {
679 + return;
680 + }
681 +
682 + $action_url = wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=woocommerce' ), 'install-plugin_woocommerce' );
683 + $button_label = __( 'Install WooCommerce', 'cartflows' );
684 + }
685 +
686 + $button = '<p><a href="' . $action_url . '" class="button-primary">' . $button_label . '</a></p><p></p>';
687 +
688 + printf( '<div class="%1$s"><p>%2$s</p>%3$s</div>', esc_attr( $class ), wp_kses_post( $message ), wp_kses_post( $button ) );
689 + }
690 +
691 + /**
692 + * Activation Reset
693 + */
694 + public function activation_reset() {
695 + if ( ! defined( 'CARTFLOWS_LOG_DIR' ) ) {
696 +
697 + $upload_dir = wp_upload_dir( null, false );
698 +
699 + define( 'CARTFLOWS_LOG_DIR', $upload_dir['basedir'] . '/cartflows-logs/' );
700 + }
701 +
702 + $this->create_files();
703 + include_once CARTFLOWS_DIR . 'classes/class-cartflows-helper.php';
704 + include_once CARTFLOWS_DIR . 'classes/class-cartflows-functions.php';
705 + include_once CARTFLOWS_DIR . 'modules/flow/classes/class-cartflows-flow-post-type.php';
706 + include_once CARTFLOWS_DIR . 'modules/flow/classes/class-cartflows-step-post-type.php';
707 +
708 + Cartflows_Flow_Post_Type::get_instance()->flow_post_type();
709 + Cartflows_Step_Post_Type::get_instance()->step_post_type();
710 + // Required to flush rules while registering custom post type.
711 + flush_rewrite_rules(); //phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.flush_rewrite_rules_flush_rewrite_rules
712 +
713 + // Update the cartflows asset version when plugin activated.
714 + update_option( 'cartflows-assets-version', time() );
715 +
716 + update_option( 'wcf_start_onboarding', true );
717 +
718 + // Record install time for time-to-value analytics (only on fresh install).
719 + Cartflows_Helper::set_analytics_flag( 'usage_installed_time', time() );
720 + }
721 +
722 + /**
723 + * Deactivation Reset
724 + */
725 + public function deactivation_reset() {
726 + }
727 +
728 + /**
729 + * Logger Class Instance
730 + */
731 + public function logger() {
732 + return Cartflows_Logger::get_instance();
733 + }
734 + }
735 +
736 + /**
737 + * Prepare if class 'Cartflows_Loader' exist.
738 + * Kicking this off by calling 'get_instance()' method
739 + */
740 + Cartflows_Loader::get_instance();
741 +}
742 +
743 +/**
744 + * Get global class.
745 + *
746 + * @return object
747 + */
748 +function wcf() { //phpcs:ignore Universal.Files.SeparateFunctionsFromOO.Mixed
749 + return Cartflows_Loader::get_instance();
750 +}
751 +
752 +if ( ! function_exists( '_is_woo_installed' ) ) {
753 +
754 + /**
755 + * Is woocommerce plugin installed.
756 + *
757 + * @since 1.0.0
758 + *
759 + * @access public
760 + */
761 + function _is_woo_installed() {
762 + $path = 'woocommerce/woocommerce.php';
763 + $plugins = get_plugins();
764 +
765 + return isset( $plugins[ $path ] );
766 + }
767 +}