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 | wizard/ajax/wizard.php +26 -14 3.1.1 → 3.3.0 View file →
@@ -354,9 +354,11 @@
354 354 $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) );
355 355 wp_send_json_error( $response_data );
356 356 }
357 357
358 - $page_builder = isset( $_POST['page_builder'] ) ? sanitize_text_field( wp_unslash( $_POST['page_builder'] ) ) : '';
358 + // sanitize_key() here as well as sanitize_text_field(): import_templates() writes the
359 + // cache under the sanitized slug, so reading with the raw one missed it permanently.
360 + $page_builder = isset( $_POST['page_builder'] ) ? sanitize_key( wp_unslash( $_POST['page_builder'] ) ) : '';
359 361
360 362 $page = 1;
361 363 $flows_list = array();
362 364
@@ -407,9 +409,11 @@
407 409 $api_args = array(
408 410 'timeout' => 30, //phpcs:ignore WordPressVIPMinimum.Performance.RemoteRequestTimeout.timeout_timeout
409 411 );
410 412
411 - $sites_and_pages = array();
413 + // Always shaped like a successful response so the error paths below cannot return
414 + // null for 'flows' — the client reads .flows.length off it.
415 + $sites_and_pages = array( 'flows' => array() );
412 416 $site_url = wcf()->get_site_url();
413 417
414 418 $query_args = array(
415 419 'per_page' => 100,
@@ -422,27 +426,35 @@
422 426 $api_url = add_query_arg( $query_args, $site_url . 'wp-json/cartflows-server/v1/flows-and-steps/' );
423 427
424 428 $response = wp_remote_get( $api_url, $api_args );
425 429
426 - if ( ! is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) === 200 ) {
430 + if ( ! is_wp_error( $response ) && 200 === wp_remote_retrieve_response_code( $response ) ) {
427 431
428 - $sites_and_pages = json_decode( wp_remote_retrieve_body( $response ), true );
432 + // Decode into its own variable — assigning over $sites_and_pages let the error
433 + // branches below return a response with no 'flows' key at all.
434 + $decoded = json_decode( wp_remote_retrieve_body( $response ), true );
429 435
430 - if ( isset( $sites_and_pages['code'] ) ) {
431 - $message = isset( $sites_and_pages['message'] ) ? $sites_and_pages['message'] : '';
436 + if ( is_array( $decoded ) && isset( $decoded['code'] ) ) {
437 + $message = isset( $decoded['message'] ) ? $decoded['message'] : '';
432 438 if ( ! empty( $message ) ) {
433 439 wcf()->logger->sync_log( 'HTTP Request Error: ' . $message );
434 440 } else {
435 441 wcf()->logger->sync_log( 'HTTP Request Error!' );
436 442 }
437 - } elseif ( is_array( $sites_and_pages ) && isset( $sites_and_pages['flows'] ) && ! empty( $sites_and_pages['flows'] ) ) {
438 - $option_name = 'cartflows-store-checkout-' . sanitize_key( $page_builder ) . '-flows-and-steps-' . $page;
439 - update_site_option( $option_name, $sites_and_pages['flows'] );
440 - } else {
441 - $sites_and_pages['flows'] = array();
443 + } elseif ( is_array( $decoded ) && ! empty( $decoded['flows'] ) ) {
444 + $sites_and_pages['flows'] = $decoded['flows'];
445 +
446 + $option_name = 'cartflows-store-checkout-' . $page_builder . '-flows-and-steps-' . $page;
447 + update_site_option( $option_name, $decoded['flows'] );
442 448 }
443 449 } else {
444 - wcf()->logger->sync_log( 'API Error: ' . $response->get_error_message() );
450 + // A non-200 response is not necessarily a WP_Error, and get_error_message()
451 + // only exists on one — the previous `||` sent those into the branch above.
452 + $error_message = is_wp_error( $response )
453 + ? $response->get_error_message()
454 + : sprintf( 'HTTP %s', wp_remote_retrieve_response_code( $response ) );
455 +
456 + wcf()->logger->sync_log( 'API Error: ' . $error_message );
445 457 }
446 458
447 459 return $sites_and_pages['flows'];
448 460 }
@@ -513,9 +525,9 @@
513 525
514 526 if ( is_wp_error( $response['data'] ) ) {
515 527
516 528 /* translators: %1$s: html tag, %2$s: link html start %3$s: link html end */
517 - $btn = sprintf( __( 'Request timeout error. Please check if the firewall or any security plugin is blocking the outgoing HTTP/HTTPS requests to templates.cartflows.com or not. %1$sTo resolve this issue, please check this %2$sarticle%3$s.', 'cartflows' ), '<br><br>', '<a target="_blank" href="https://cartflows.com/docs/request-timeout-error-while-importing-the-flow-step-templates/?utm_source=dashboard&utm_medium=free-cartflows&utm_campaign=docs">', '</a>' );
529 + $btn = sprintf( __( 'Request timeout error. Please check if the firewall or any security plugin is blocking the outgoing HTTP/HTTPS requests to templates.cartflows.com or not. %1$sTo resolve this issue, please check this %2$sarticle%3$s.', 'cartflows' ), '<br><br>', '<a target="_blank" href="' . esc_url( \Cartflows_Helper::get_kb_doc_link( 'https://cartflows.com/docs/request-timeout-error-while-importing-the-flow-step-templates/' ) ) . '">', '</a>' );
518 530
519 531 wp_send_json_error(
520 532 array(
521 533 'message' => $response['data']->get_error_message(),
@@ -536,9 +548,9 @@
536 548 $title = '';
537 549 $msg = '';
538 550 if ( 'not-installed' === $cf_pro_status ) {
539 551 /* translators: %1$s: link html start, %2$s: link html end*/
540 - $msg = sprintf( __( 'To import this template, CartFlows Pro Required! %1$sUpgrade to CartFlows Pro%2$s', 'cartflows' ), '<a target="_blank" href="https://cartflows.com/?utm_source=dashboard&utm_medium=free-cartflows&utm_campaign=go-pro">', '</a>' );
552 + $msg = sprintf( __( 'To import this template, CartFlows Pro Required! %1$sUpgrade to CartFlows Pro%2$s', 'cartflows' ), '<a target="_blank" href="' . esc_url( \Cartflows_Helper::get_upgrade_to_pro_link( '', 'https://cartflows.com/' ) ) . '">', '</a>' );
541 553 $title = __( 'CartFlows Pro Required', 'cartflows' );
542 554 } elseif ( 'inactive' === $cf_pro_status ) {
543 555 $title = __( 'CartFlows Pro Required', 'cartflows' );
544 556 /* translators: %1$s: link html start, %2$s: link html end*/