| @@ -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*/ |