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 | admin-core/inc/admin-menu.php +45 -5 3.1.2 → 3.3.0 View file →
@@ -222,8 +222,12 @@
222 222 // Ignoring nonce verification as using SuperGlobal variables on WordPress hooks.
223 223 if ( isset( $_GET['page'] ) && ( 'cartflows' === sanitize_text_field( $_GET['page'] ) || false !== strpos( sanitize_text_field( $_GET['page'] ), 'cartflows_' ) ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
224 224
225 225 add_action( 'admin_enqueue_scripts', array( $this, 'styles_scripts' ) );
226 +
227 + // Twemoji rewrites emoji text nodes inside our React tree, detaching nodes React still tracks and crashing the editor.
228 + remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
229 + remove_action( 'admin_print_styles', 'print_emoji_styles' );
226 230 }
227 231 }
228 232
229 233 /**
@@ -276,8 +280,22 @@
276 280 $capability,
277 281 'admin.php?page=' . $this->menu_slug . '&path=analytics'
278 282 );
279 283
284 + // Persistent re-entry point until the guided setup is finished.
285 + if ( current_user_can( 'manage_options' ) && '1' !== get_option( 'wcf_setup_complete', false ) ) {
286 + $exit_step = get_option( 'wcf_exit_setup_step', '' );
287 + $resume_link = 'index.php?page=cartflows-onboarding' . ( ! empty( $exit_step ) && is_string( $exit_step ) ? '&step=' . sanitize_key( $exit_step ) : '' );
288 +
289 + add_submenu_page(
290 + $parent_slug,
291 + __( 'Resume Setup', 'cartflows' ),
292 + __( 'Resume Setup', 'cartflows' ),
293 + $capability,
294 + $resume_link
295 + );
296 + }
297 +
280 298 if ( current_user_can( 'cartflows_manage_settings' ) ) {
281 299
282 300 add_submenu_page(
283 301 $parent_slug,
@@ -354,10 +372,8 @@
354 372 if ( $this->is_current_page( 'cartflows' ) ) {
355 373 include_once CARTFLOWS_ADMIN_CORE_DIR . 'views/settings-app.php';
356 374 } elseif ( $this->is_current_page( 'cartflows', array( 'wcf-edit-flow' ) ) ) {
357 375 include_once CARTFLOWS_ADMIN_CORE_DIR . 'views/editor-app.php';
358 - } elseif ( $this->is_current_page( 'cartflows', array( 'wcf-log' ) ) ) {
359 - include_once CARTFLOWS_ADMIN_CORE_DIR . 'views/debugger.php';
360 376 } elseif ( $this->is_current_page( 'cartflows', array( 'wcf-license' ) ) && _is_cartflows_pro() ) {
361 377 do_action( 'cartflows_admin_log', 'wcf-license' );
362 378 } else {
363 379 include_once CARTFLOWS_ADMIN_CORE_DIR . 'views/404-error.php';
@@ -443,8 +459,9 @@
443 459 'required_plugins_data' => $this->get_required_plugins_data(),
444 460 'is_any_required_plugins_missing' => $this->get_any_required_plugins_status(),
445 461 'admin_base_slug' => $this->menu_slug,
446 462 'admin_base_url' => admin_url(),
463 + 'is_onboarding_completed' => '1' === get_option( 'wcf_setup_complete', false ),
447 464 'title_length' => apply_filters(
448 465 'cartflows_flows_steps_title_length',
449 466 array(
450 467 'max' => 50,
@@ -474,10 +491,16 @@
474 491 'cf_font_family' => AdminHelper::get_font_family(),
475 492 'flows_and_steps' => ! empty( $flows_and_steps ) ? $flows_and_steps : '',
476 493 'store_checkout_flows_and_steps' => \Cartflows_Helper::get_instance()->get_flows_and_steps( '', 'store-checkout' ),
477 494 'woo_currency' => function_exists( 'get_woocommerce_currency_symbol' ) ? get_woocommerce_currency_symbol() : '',
495 + 'woo_currency_pos' => function_exists( 'wc' ) ? get_option( 'woocommerce_currency_pos', 'left' ) : 'left',
496 + 'woo_decimal_sep' => function_exists( 'wc_get_price_decimal_separator' ) ? wc_get_price_decimal_separator() : '.',
497 + 'woo_thousand_sep' => function_exists( 'wc_get_price_thousand_separator' ) ? wc_get_price_thousand_separator() : ',',
498 + 'woo_decimals' => function_exists( 'wc_get_price_decimals' ) ? wc_get_price_decimals() : 2,
478 499 'template_library_url' => wcf()->get_site_url(),
479 500 'image_placeholder' => esc_url_raw( CARTFLOWS_URL . 'admin-core/assets/images/image-placeholder.png' ),
501 + 'ai_connected' => class_exists( '\Cartflows_Ai_Auth' ) ? \Cartflows_Ai_Auth::get_instance()->get_auth_status() : false,
502 + 'can_manage_ai_auth' => current_user_can( 'manage_options' ),
480 503 'google_fonts' => \CartFlows_Font_Families::get_google_fonts(),
481 504 'system_fonts' => \CartFlows_Font_Families::get_system_fonts(),
482 505 'font_weights' => array(
483 506 '100' => __( 'Thin 100', 'cartflows' ),
@@ -500,9 +523,8 @@
500 523 'moderncart_status' => $this->get_plugin_status( 'modern-cart/modern-cart.php' ),
501 524 'cpsw_connection_status' => 'success' === get_option( 'cpsw_test_con_status', false ) || 'success' === get_option( 'cpsw_con_status', false ),
502 525 'current_user_can_manage_cartflows' => current_user_can( 'cartflows_manage_settings' ),
503 526 'is_set_report_email_ids' => get_option( 'cartflows_stats_report_email_ids', false ),
504 - 'cf_docs_data' => get_option( 'cartflows_docs_data', false ),
505 527 'woo_order_url' => $order_url,
506 528 'integrations' => $this->get_recommendation_integrations(),
507 529 'plugin_installer_nonce' => wp_create_nonce( 'updates' ),
508 530 'instant_checkout_notice_status' => \Cartflows_Helper::get_admin_settings_option( 'wcf-instant-checkout-notice-skipped', false, false ),
@@ -807,8 +829,17 @@
807 829 array(),
808 830 CARTFLOWS_VER
809 831 );
810 832
833 + // Store Checkout renders the canvas inside this app too, so it needs the React Flow base styles.
834 + wp_register_style(
835 + 'wcf-canvas-base-style',
836 + $build_url . 'style-editor-app.css',
837 + array(),
838 + CARTFLOWS_VER
839 + );
840 + wp_enqueue_style( 'wcf-canvas-base-style' );
841 +
811 842 wp_enqueue_script( $handle );
812 843
813 844 wp_set_script_translations( $handle, 'cartflows' );
814 845
@@ -1173,10 +1204,19 @@
1173 1204
1174 1205 // Fetch the RSS feed from the URL. This saves us from the CORS issue.
1175 1206 $feed = wp_remote_retrieve_body( wp_safe_remote_get( 'https://cartflows.com/product/cartflows/feed/' ) ); // phpcs:ignore -- This is a valid use case cannot use VIP rules here.
1176 1207
1177 - // Security: Set proper content type header and strip script tags to prevent XSS.
1178 - echo $feed; // phpcs:ignore -- RSS feed content sanitized via wp_kses_post.
1208 + /*
1209 + * This is an RSS document, parsed as XML by the What's New client. It must not be
1210 + * run through wp_kses_post() — that strips the feed's own elements and leaves the
1211 + * client nothing to parse. Declaring the type is what stops a browser sniffing the
1212 + * response as HTML; the body itself is fetched over HTTPS from our own domain and
1213 + * this endpoint is behind a nonce and a capability check.
1214 + */
1215 + header( 'Content-Type: application/rss+xml; charset=' . get_option( 'blog_charset' ) );
1216 + header( 'X-Content-Type-Options: nosniff' );
1217 +
1218 + echo $feed; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- RSS/XML body, see above.
1179 1219 exit;
1180 1220 }
1181 1221 }
1182 1222