| @@ -4,8 +4,12 @@ | ||
| 4 | 4 | * |
| 5 | 5 | * @package CartFlows |
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | +// Exit if accessed directly. | |
| 9 | +if ( ! defined( 'ABSPATH' ) ) { | |
| 10 | + exit; | |
| 11 | +} | |
| 8 | 12 | if ( ! class_exists( 'Cartflows_Loader' ) ) { |
| 9 | 13 | |
| 10 | 14 | /** |
| 11 | 15 | * Class Cartflows_Loader. |
| @@ -35,26 +39,25 @@ | ||
| 35 | 39 | |
| 36 | 40 | /** |
| 37 | 41 | * Member Variable |
| 38 | 42 | * |
| 39 | - * @var session | |
| 43 | + * @var options | |
| 40 | 44 | */ |
| 41 | - public $session = null; | |
| 45 | + public $options = null; | |
| 42 | 46 | |
| 43 | - | |
| 44 | 47 | /** |
| 45 | 48 | * Member Variable |
| 46 | 49 | * |
| 47 | - * @var options | |
| 50 | + * @var meta | |
| 48 | 51 | */ |
| 49 | - public $options = null; | |
| 52 | + public $meta = null; | |
| 50 | 53 | |
| 51 | 54 | /** |
| 52 | 55 | * Member Variable |
| 53 | 56 | * |
| 54 | - * @var meta | |
| 57 | + * @var Tracking_Data | |
| 55 | 58 | */ |
| 56 | - public $meta = null; | |
| 59 | + public $alldata; | |
| 57 | 60 | |
| 58 | 61 | /** |
| 59 | 62 | * Member Variable |
| 60 | 63 | * |
| @@ -62,8 +65,16 @@ | ||
| 62 | 65 | */ |
| 63 | 66 | public $flow = null; |
| 64 | 67 | |
| 65 | 68 | /** |
| 69 | + * Member Variable | |
| 70 | + * | |
| 71 | + * @var wcf_step_objs | |
| 72 | + */ | |
| 73 | + | |
| 74 | + public $wcf_step_objs = array(); | |
| 75 | + | |
| 76 | + /** | |
| 66 | 77 | * Member Variable |
| 67 | 78 | * |
| 68 | 79 | * @var assets_vars |
| 69 | 80 | */ |
| @@ -69,15 +80,22 @@ | ||
| 69 | 80 | */ |
| 70 | 81 | public $assets_vars = null; |
| 71 | 82 | |
| 72 | 83 | /** |
| 84 | + * Member Variable | |
| 85 | + * | |
| 86 | + * @var assets_vars | |
| 87 | + */ | |
| 88 | + | |
| 89 | + public $is_woo_active = true; | |
| 90 | + | |
| 91 | + /** | |
| 73 | 92 | * Initiator |
| 74 | 93 | */ |
| 75 | 94 | public static function get_instance() { |
| 76 | - | |
| 77 | 95 | if ( is_null( self::$instance ) ) { |
| 78 | 96 | |
| 79 | - self::$instance = new self; | |
| 97 | + self::$instance = new self(); | |
| 80 | 98 | |
| 81 | 99 | /** |
| 82 | 100 | * CartFlows loaded. |
| 83 | 101 | * |
| @@ -94,9 +112,8 @@ | ||
| 94 | 112 | /** |
| 95 | 113 | * Constructor |
| 96 | 114 | */ |
| 97 | 115 | public function __construct() { |
| 98 | - | |
| 99 | 116 | $this->define_constants(); |
| 100 | 117 | |
| 101 | 118 | // Activation hook. |
| 102 | 119 | register_activation_hook( CARTFLOWS_FILE, array( $this, 'activation_reset' ) ); |
| @@ -103,13 +120,17 @@ | ||
| 103 | 120 | |
| 104 | 121 | // deActivation hook. |
| 105 | 122 | register_deactivation_hook( CARTFLOWS_FILE, array( $this, 'deactivation_reset' ) ); |
| 106 | 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 | + | |
| 107 | 127 | add_action( 'plugins_loaded', array( $this, 'load_plugin' ), 99 ); |
| 108 | - add_action( 'plugins_loaded', array( $this, 'load_cf_textdomain' ) ); | |
| 128 | + add_action( 'init', array( $this, 'load_cf_textdomain' ) ); | |
| 109 | 129 | |
| 110 | - // Update compatibility. | |
| 111 | - require_once CARTFLOWS_DIR . 'classes/class-cartflows-update.php'; | |
| 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 ); | |
| 112 | 133 | } |
| 113 | 134 | |
| 114 | 135 | /** |
| 115 | 136 | * Defines all constants |
| @@ -120,20 +141,40 @@ | ||
| 120 | 141 | |
| 121 | 142 | define( 'CARTFLOWS_BASE', plugin_basename( CARTFLOWS_FILE ) ); |
| 122 | 143 | define( 'CARTFLOWS_DIR', plugin_dir_path( CARTFLOWS_FILE ) ); |
| 123 | 144 | define( 'CARTFLOWS_URL', plugins_url( '/', CARTFLOWS_FILE ) ); |
| 124 | - define( 'CARTFLOWS_VER', '1.1.15' ); | |
| 145 | + | |
| 146 | + define( 'CARTFLOWS_VER', '3.3.0' ); | |
| 125 | 147 | define( 'CARTFLOWS_SLUG', 'cartflows' ); |
| 126 | 148 | define( 'CARTFLOWS_SETTINGS', 'cartflows_settings' ); |
| 149 | + define( 'CARTFLOWS_NAME', 'CartFlows' ); | |
| 127 | 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 | + | |
| 128 | 162 | define( 'CARTFLOWS_FLOW_POST_TYPE', 'cartflows_flow' ); |
| 129 | 163 | define( 'CARTFLOWS_STEP_POST_TYPE', 'cartflows_step' ); |
| 130 | 164 | |
| 165 | + define( 'CARTFLOWS_FLOW_PERMALINK_SLUG', 'flow' ); | |
| 166 | + define( 'CARTFLOWS_STEP_PERMALINK_SLUG', 'step' ); | |
| 167 | + | |
| 131 | 168 | if ( ! defined( 'CARTFLOWS_SERVER_URL' ) ) { |
| 132 | 169 | define( 'CARTFLOWS_SERVER_URL', 'https://my.cartflows.com/' ); |
| 133 | 170 | } |
| 134 | - define( 'CARTFLOWS_DOMAIN_URL', 'https://cartflows.com/' ); | |
| 135 | - define( 'CARTFLOWS_TEMPLATES_URL', 'https://templates.cartflows.com/' ); | |
| 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 | + } | |
| 136 | 177 | define( 'CARTFLOWS_TAXONOMY_STEP_TYPE', 'cartflows_step_type' ); |
| 137 | 178 | define( 'CARTFLOWS_TAXONOMY_STEP_FLOW', 'cartflows_step_flow' ); |
| 138 | 179 | |
| 139 | 180 | if ( ! defined( 'CARTFLOWS_TAXONOMY_STEP_PAGE_BUILDER' ) ) { |
| @@ -144,11 +185,64 @@ | ||
| 144 | 185 | } |
| 145 | 186 | if ( ! defined( 'CARTFLOWS_TAXONOMY_FLOW_CATEGORY' ) ) { |
| 146 | 187 | define( 'CARTFLOWS_TAXONOMY_FLOW_CATEGORY', 'cartflows_flow_category' ); |
| 147 | 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; | |
| 148 | 214 | } |
| 149 | 215 | |
| 150 | 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 | + /** | |
| 151 | 245 | * Loads plugin files. |
| 152 | 246 | * |
| 153 | 247 | * @since 1.0.0 |
| 154 | 248 | * |
| @@ -153,21 +247,20 @@ | ||
| 153 | 247 | * @since 1.0.0 |
| 154 | 248 | * |
| 155 | 249 | * @return void |
| 156 | 250 | */ |
| 157 | - function load_plugin() { | |
| 158 | - | |
| 159 | - if ( ! function_exists( 'WC' ) ) { | |
| 160 | - add_action( 'admin_notices', array( $this, 'fails_to_load' ) ); | |
| 161 | - return; | |
| 162 | - } | |
| 163 | - | |
| 251 | + public function load_plugin() { | |
| 164 | 252 | $this->load_helper_files_components(); |
| 165 | 253 | $this->load_core_files(); |
| 166 | 254 | $this->load_core_components(); |
| 167 | 255 | |
| 168 | 256 | add_action( 'wp_loaded', array( $this, 'initialize' ) ); |
| 257 | + add_action( 'cartflows_pro_init', array( $this, 'after_cartflows_pro_init' ) ); | |
| 169 | 258 | |
| 259 | + if ( ! $this->is_woo_active ) { | |
| 260 | + add_action( 'admin_notices', array( $this, 'fails_to_load' ) ); | |
| 261 | + } | |
| 262 | + | |
| 170 | 263 | /** |
| 171 | 264 | * CartFlows Init. |
| 172 | 265 | * |
| 173 | 266 | * Fires when Cartflows is instantiated. |
| @@ -177,8 +270,62 @@ | ||
| 177 | 270 | do_action( 'cartflows_init' ); |
| 178 | 271 | } |
| 179 | 272 | |
| 180 | 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 | + /** | |
| 181 | 328 | * Load Helper Files and Components. |
| 182 | 329 | * |
| 183 | 330 | * @since 1.0.0 |
| 184 | 331 | * |
| @@ -183,31 +330,99 @@ | ||
| 183 | 330 | * @since 1.0.0 |
| 184 | 331 | * |
| 185 | 332 | * @return void |
| 186 | 333 | */ |
| 187 | - function load_helper_files_components() { | |
| 334 | + public function load_helper_files_components() { | |
| 335 | + $this->is_woo_active = function_exists( 'WC' ); | |
| 188 | 336 | |
| 189 | 337 | /* Public Utils */ |
| 190 | 338 | include_once CARTFLOWS_DIR . 'classes/class-cartflows-utils.php'; |
| 191 | 339 | |
| 192 | - /* Public Session */ | |
| 193 | - include_once CARTFLOWS_DIR . 'classes/class-cartflows-session.php'; | |
| 194 | - | |
| 195 | - /* Public Global namespace functions */ | |
| 340 | + /* Public Global Name space Functions */ | |
| 196 | 341 | include_once CARTFLOWS_DIR . 'classes/class-cartflows-functions.php'; |
| 197 | 342 | |
| 198 | 343 | /* Admin Helper */ |
| 199 | 344 | include_once CARTFLOWS_DIR . 'classes/class-cartflows-helper.php'; |
| 200 | 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 | + | |
| 201 | 353 | /* Meta Default Values */ |
| 202 | 354 | include_once CARTFLOWS_DIR . 'classes/class-cartflows-default-meta.php'; |
| 203 | 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 | + | |
| 204 | 367 | $this->utils = Cartflows_Utils::get_instance(); |
| 205 | - $this->session = Cartflows_Session::get_instance(); | |
| 206 | 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 | + } | |
| 207 | 384 | } |
| 208 | 385 | |
| 209 | 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 | + /** | |
| 210 | 425 | * Init hooked function. |
| 211 | 426 | * |
| 212 | 427 | * @since 1.0.0 |
| 213 | 428 | * |
| @@ -212,9 +427,9 @@ | ||
| 212 | 427 | * @since 1.0.0 |
| 213 | 428 | * |
| 214 | 429 | * @return void |
| 215 | 430 | */ |
| 216 | - function initialize() { | |
| 431 | + public function initialize() { | |
| 217 | 432 | $this->assets_vars = $this->utils->get_assets_path(); |
| 218 | 433 | } |
| 219 | 434 | |
| 220 | 435 | /** |
| @@ -223,24 +438,67 @@ | ||
| 223 | 438 | * @since 1.0.0 |
| 224 | 439 | * |
| 225 | 440 | * @return void |
| 226 | 441 | */ |
| 227 | - function load_core_files() { | |
| 442 | + public function load_core_files() { | |
| 443 | + /* Update compatibility. */ | |
| 444 | + require_once CARTFLOWS_DIR . 'classes/class-cartflows-update.php'; | |
| 228 | 445 | |
| 229 | 446 | /* Page builder compatibilty class */ |
| 230 | - include_once CARTFLOWS_DIR . 'classes/class-cartflows-compatibility.php'; | |
| 447 | + include_once CARTFLOWS_DIR . 'compatibilities/class-cartflows-compatibility.php'; | |
| 231 | 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 | + | |
| 232 | 458 | /* Admin Meta Fields*/ |
| 233 | 459 | include_once CARTFLOWS_DIR . 'classes/fields/typography/class-cartflows-font-families.php'; |
| 234 | - include_once CARTFLOWS_DIR . 'classes/class-cartflows-meta-fields.php'; | |
| 235 | - include_once CARTFLOWS_DIR . 'classes/class-cartflows-meta.php'; | |
| 236 | 460 | |
| 237 | - /* Cloning */ | |
| 238 | - include_once CARTFLOWS_DIR . 'classes/class-cartflows-cloning.php'; | |
| 461 | + // Learn progress — shared by the Learn REST route and the analytics payload. | |
| 462 | + include_once CARTFLOWS_DIR . 'classes/class-cartflows-learn-progress.php'; | |
| 239 | 463 | |
| 240 | - /* Admin Settings */ | |
| 241 | - include_once CARTFLOWS_DIR . 'classes/class-cartflows-admin.php'; | |
| 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'; | |
| 242 | 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 | + | |
| 243 | 501 | /* Core Modules */ |
| 244 | 502 | include_once CARTFLOWS_DIR . 'classes/class-cartflows-logger.php'; |
| 245 | 503 | |
| 246 | 504 | /* Frontend Global */ |
| @@ -249,16 +507,39 @@ | ||
| 249 | 507 | |
| 250 | 508 | /* Modules */ |
| 251 | 509 | include_once CARTFLOWS_DIR . 'modules/flow/class-cartflows-flow.php'; |
| 252 | 510 | include_once CARTFLOWS_DIR . 'modules/landing/class-cartflows-landing.php'; |
| 253 | - include_once CARTFLOWS_DIR . 'modules/checkout/class-cartflows-checkout.php'; | |
| 254 | - include_once CARTFLOWS_DIR . 'modules/thankyou/class-cartflows-thankyou.php'; | |
| 255 | 511 | |
| 256 | - include_once CARTFLOWS_DIR . 'classes/class-cartflows-api.php'; | |
| 257 | - include_once CARTFLOWS_DIR . 'classes/class-cartflows-importer-core.php'; | |
| 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 | + } | |
| 258 | 520 | |
| 259 | - include_once CARTFLOWS_DIR . 'classes/batch-process/class-cartflows-batch-process.php'; | |
| 260 | - include_once CARTFLOWS_DIR . 'classes/class-cartflows-importer.php'; | |
| 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'; | |
| 261 | 542 | } |
| 262 | 543 | |
| 263 | 544 | /** |
| 264 | 545 | * Load Core Components. |
| @@ -266,16 +547,45 @@ | ||
| 266 | 547 | * @since 1.0.0 |
| 267 | 548 | * |
| 268 | 549 | * @return void |
| 269 | 550 | */ |
| 270 | - function load_core_components() { | |
| 271 | - | |
| 272 | - $this->meta = Cartflows_Meta_Fields::get_instance(); | |
| 551 | + public function load_core_components() { | |
| 273 | 552 | $this->logger = Cartflows_Logger::get_instance(); |
| 274 | 553 | $this->flow = Cartflows_Flow_Frontend::get_instance(); |
| 275 | 554 | } |
| 276 | 555 | |
| 277 | 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 | + /** | |
| 278 | 588 | * Load CartFlows Pro Text Domain. |
| 279 | 589 | * This will load the translation textdomain depending on the file priorities. |
| 280 | 590 | * 1. Global Languages /wp-content/languages/cartflows/ folder |
| 281 | 591 | * 2. Local dorectory /wp-content/plugins/cartflows/languages/ folder |
| @@ -283,9 +593,8 @@ | ||
| 283 | 593 | * @since 1.0.3 |
| 284 | 594 | * @return void |
| 285 | 595 | */ |
| 286 | 596 | public function load_cf_textdomain() { |
| 287 | - | |
| 288 | 597 | // Default languages directory for CartFlows Pro. |
| 289 | 598 | $lang_dir = CARTFLOWS_DIR . 'languages/'; |
| 290 | 599 | |
| 291 | 600 | /** |
| @@ -337,18 +646,25 @@ | ||
| 337 | 646 | * |
| 338 | 647 | * @return void |
| 339 | 648 | */ |
| 340 | 649 | public function fails_to_load() { |
| 650 | + $screen = get_current_screen(); | |
| 341 | 651 | |
| 342 | - $screen = get_current_screen(); | |
| 652 | + if ( ! wcf()->utils->is_step_post_type() ) { | |
| 653 | + return; | |
| 654 | + } | |
| 343 | 655 | |
| 344 | - if ( isset( $screen->parent_file ) && 'plugins.php' === $screen->parent_file && 'update' === $screen->id ) { | |
| 656 | + if ( ! wcf()->utils->check_is_woo_required_page() ) { | |
| 345 | 657 | return; |
| 346 | 658 | } |
| 347 | 659 | |
| 348 | - $class = 'notice notice-error'; | |
| 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'; | |
| 349 | 665 | /* translators: %s: html tags */ |
| 350 | - $message = sprintf( __( 'The %1$sCartFlows%2$s plugin requires %1$sWooCommerce%2$s plugin installed & activated.', 'cartflows' ), '<strong>', '</strong>' ); | |
| 666 | + $message = sprintf( __( 'This %1$sCartFlows%2$s page requires %1$sWooCommerce%2$s plugin installed & activated.', 'cartflows' ), '<strong>', '</strong>' ); | |
| 351 | 667 | |
| 352 | 668 | $plugin = 'woocommerce/woocommerce.php'; |
| 353 | 669 | |
| 354 | 670 | if ( _is_woo_installed() ) { |
| @@ -357,9 +673,8 @@ | ||
| 357 | 673 | } |
| 358 | 674 | |
| 359 | 675 | $action_url = wp_nonce_url( 'plugins.php?action=activate&plugin=' . $plugin . '&plugin_status=all&paged=1&s', 'activate-plugin_' . $plugin ); |
| 360 | 676 | $button_label = __( 'Activate WooCommerce', 'cartflows' ); |
| 361 | - | |
| 362 | 677 | } else { |
| 363 | 678 | if ( ! current_user_can( 'install_plugins' ) ) { |
| 364 | 679 | return; |
| 365 | 680 | } |
| @@ -369,38 +684,54 @@ | ||
| 369 | 684 | } |
| 370 | 685 | |
| 371 | 686 | $button = '<p><a href="' . $action_url . '" class="button-primary">' . $button_label . '</a></p><p></p>'; |
| 372 | 687 | |
| 373 | - printf( '<div class="%1$s"><p>%2$s</p>%3$s</div>', esc_attr( $class ), $message, $button ); | |
| 688 | + printf( '<div class="%1$s"><p>%2$s</p>%3$s</div>', esc_attr( $class ), wp_kses_post( $message ), wp_kses_post( $button ) ); | |
| 374 | 689 | } |
| 375 | 690 | |
| 376 | 691 | /** |
| 377 | 692 | * Activation Reset |
| 378 | 693 | */ |
| 379 | - function activation_reset() { | |
| 694 | + public function activation_reset() { | |
| 695 | + if ( ! defined( 'CARTFLOWS_LOG_DIR' ) ) { | |
| 380 | 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'; | |
| 381 | 705 | include_once CARTFLOWS_DIR . 'modules/flow/classes/class-cartflows-flow-post-type.php'; |
| 382 | 706 | include_once CARTFLOWS_DIR . 'modules/flow/classes/class-cartflows-step-post-type.php'; |
| 383 | 707 | |
| 384 | 708 | Cartflows_Flow_Post_Type::get_instance()->flow_post_type(); |
| 385 | 709 | Cartflows_Step_Post_Type::get_instance()->step_post_type(); |
| 386 | - flush_rewrite_rules(); | |
| 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() ); | |
| 387 | 720 | } |
| 388 | 721 | |
| 389 | 722 | /** |
| 390 | 723 | * Deactivation Reset |
| 391 | 724 | */ |
| 392 | - function deactivation_reset() { | |
| 725 | + public function deactivation_reset() { | |
| 393 | 726 | } |
| 394 | 727 | |
| 395 | 728 | /** |
| 396 | 729 | * Logger Class Instance |
| 397 | 730 | */ |
| 398 | - function logger() { | |
| 731 | + public function logger() { | |
| 399 | 732 | return Cartflows_Logger::get_instance(); |
| 400 | 733 | } |
| 401 | - | |
| 402 | - | |
| 403 | 734 | } |
| 404 | 735 | |
| 405 | 736 | /** |
| 406 | 737 | * Prepare if class 'Cartflows_Loader' exist. |
| @@ -413,9 +744,9 @@ | ||
| 413 | 744 | * Get global class. |
| 414 | 745 | * |
| 415 | 746 | * @return object |
| 416 | 747 | */ |
| 417 | -function wcf() { | |
| 748 | +function wcf() { //phpcs:ignore Universal.Files.SeparateFunctionsFromOO.Mixed | |
| 418 | 749 | return Cartflows_Loader::get_instance(); |
| 419 | 750 | } |
| 420 | 751 | |
| 421 | 752 | if ( ! function_exists( '_is_woo_installed' ) ) { |
| @@ -427,9 +758,8 @@ | ||
| 427 | 758 | * |
| 428 | 759 | * @access public |
| 429 | 760 | */ |
| 430 | 761 | function _is_woo_installed() { |
| 431 | - | |
| 432 | 762 | $path = 'woocommerce/woocommerce.php'; |
| 433 | 763 | $plugins = get_plugins(); |
| 434 | 764 | |
| 435 | 765 | return isset( $plugins[ $path ] ); |