diff --git a/includes/Core/Authentication/Setup.php b/includes/Core/Authentication/Setup.php
index 5764d29b182..cb542fef539 100644
--- a/includes/Core/Authentication/Setup.php
+++ b/includes/Core/Authentication/Setup.php
@@ -122,26 +122,69 @@ public function register() {
*
* @since 1.81.0
* @since 1.167.0 Added support for custom error codes.
+ * @since n.e.x.t Added support for message-based error IDs.
*
- * @param string|null $error_code The error code. Optional. Defaults to null.
+ * @param WP_Error|null $error Optional. The proxy request error. Defaults to null.
* @return string The get help link.
*/
- private function get_oauth_proxy_failed_help_link( $error_code = null ) {
- // Map `request_failed` to the error ID `request_to_auth_proxy_failed` for backwards compatibility.
- if ( null === $error_code || 'request_failed' === $error_code ) {
- $error_id = 'request_to_auth_proxy_failed';
- } else {
- $error_id = $error_code;
- }
-
+ private function get_oauth_proxy_failed_help_link( $error = null ) {
return sprintf(
/* translators: 1: Support link URL. 2: Get help string. */
__( '%2$s', 'google-site-kit' ),
- esc_url( add_query_arg( 'error_id', $error_id, $this->proxy_support_link_url ) ),
+ esc_url( add_query_arg( 'error_id', $this->get_oauth_proxy_failed_error_id( $error ), $this->proxy_support_link_url ) ),
esc_html__( 'Get help', 'google-site-kit' )
);
}
+ /**
+ * Resolves the support error_id for a failed oAuth proxy request.
+ *
+ * @since n.e.x.t
+ *
+ * @param WP_Error|null $error Optional. The proxy request error. Defaults to null.
+ * @return string The error_id query value for the support link.
+ */
+ private function get_oauth_proxy_failed_error_id( $error = null ) {
+ if ( ! is_wp_error( $error ) ) {
+ return 'request_to_auth_proxy_failed';
+ }
+
+ $code = (string) $error->get_error_code();
+ $message = (string) $error->get_error_message();
+
+ // Prefer message patterns for transport failures that share a generic code.
+ if ( false !== stripos( $message, 'cURL error 7' ) ) {
+ return 'curl-error-7-operation-timed-out';
+ }
+
+ if ( false !== stripos( $message, 'cURL error 28' ) ) {
+ return 'curl-error-28-operation-timed-out';
+ }
+
+ // WP core uses this code when WP_HTTP_BLOCK_EXTERNAL blocks the request.
+ if ( 'http_request_not_executed' === $code
+ || false !== stripos( $message, 'User has blocked requests through HTTP' )
+ ) {
+ return 'user-has-blocked-requests-through-http';
+ }
+
+ if ( false !== stripos( $message, 'A site with the given URL already exists' ) ) {
+ return 'a-site-with-the-given-url-already-exists';
+ }
+
+ if ( false !== stripos( $message, 'Unable to retrieve site connection' ) ) {
+ return 'unable-to-retrieve-site-connection-you-may-need-to-perform-a-plugin-reset';
+ }
+
+ // Map `request_failed` to the parent guide ID for backwards compatibility.
+ if ( '' === $code || 'request_failed' === $code ) {
+ return 'request_to_auth_proxy_failed';
+ }
+
+ // Pass through custom proxy error codes (e.g. site-not-found).
+ return $code;
+ }
+
/**
* Handles the setup start action, taking the user to the proxy setup screen.
*
@@ -180,7 +223,7 @@ public function handle_action_setup_start() {
esc_html__( 'The request to the authentication proxy has failed with an error: %1$s %2$s.', 'google-site-kit' ),
esc_html( $error_message ),
wp_kses(
- $this->get_oauth_proxy_failed_help_link( $oauth_setup_redirect->get_error_code() ),
+ $this->get_oauth_proxy_failed_help_link( $oauth_setup_redirect ),
array(
'a' => array(
'href' => array(),
diff --git a/tests/phpunit/integration/Core/Authentication/Setup_Test.php b/tests/phpunit/integration/Core/Authentication/Setup_Test.php
index 8f6a5663002..ccda940d097 100644
--- a/tests/phpunit/integration/Core/Authentication/Setup_Test.php
+++ b/tests/phpunit/integration/Core/Authentication/Setup_Test.php
@@ -175,6 +175,9 @@ public function test_handle_action_setup_start__wp_error( $params ) {
$has_credentials = $params['has_credentials'];
$error_code = $params['error_code'];
$expected_error_code = $params['expected_error_code'];
+ $error_message = array_key_exists( 'error_message', $params )
+ ? $params['error_message']
+ : ( $has_credentials ? 'Test error message.' : null );
$user_id = $this->factory()->user->create( array( 'role' => 'administrator' ) );
wp_set_current_user( $user_id );
@@ -195,16 +198,13 @@ public function test_handle_action_setup_start__wp_error( $params ) {
// Fake a WP_Error IF a request is made to the Google Proxy server.
add_filter(
'pre_http_request',
- function ( $preempt, $args, $url ) use ( $context, &$proxy_server_requests, $has_credentials, $error_code ) {
+ function ( $preempt, $args, $url ) use ( $context, &$proxy_server_requests, $error_code, $error_message ) {
if ( ( new Google_Proxy( $context ) )->url( Google_Proxy::OAUTH2_SITE_URI ) !== $url ) {
return $preempt;
}
// Collect any HTTP requests to the proxy server to register/sync site with the proxy server.
$proxy_server_requests[] = $args;
- // Using the two cases for $has_credentials, we can test the error message
- // and the fallback to an error code when there is no message.
- $error_message = $has_credentials ? 'Test error message.' : null;
return new WP_Error( $error_code, $error_message );
},
10,
@@ -217,11 +217,12 @@ function ( $preempt, $args, $url ) use ( $context, &$proxy_server_requests, $has
} catch ( RedirectException $redirect ) {
$this->fail( 'Expected WPDieException!' );
} catch ( WPDieException $exception ) {
- $error = $has_credentials ? 'Test error message.' : $error_code;
+ // Empty messages fall back to the error code in the die message.
+ $displayed_error = ! empty( $error_message ) ? $error_message : $error_code;
$this->assertStringContainsString(
sprintf(
'The request to the authentication proxy has failed with an error: %1$s Get help.',
- $error,
+ $displayed_error,
$expected_error_code
),
$exception->getMessage(),
@@ -262,6 +263,46 @@ public function data_conditionally_throws_error() {
'expected_error_code' => 'request_to_auth_proxy_failed',
),
),
+ 'curl error 7 message' => array(
+ array(
+ 'has_credentials' => true,
+ 'error_code' => 'http_request_failed',
+ 'error_message' => 'cURL error 7: Failed to connect to sitekit.withgoogle.com',
+ 'expected_error_code' => 'curl-error-7-operation-timed-out',
+ ),
+ ),
+ 'curl error 28 message' => array(
+ array(
+ 'has_credentials' => true,
+ 'error_code' => 'http_request_failed',
+ 'error_message' => 'cURL error 28: Operation timed out after 5000 milliseconds',
+ 'expected_error_code' => 'curl-error-28-operation-timed-out',
+ ),
+ ),
+ 'blocked http requests by code' => array(
+ array(
+ 'has_credentials' => true,
+ 'error_code' => 'http_request_not_executed',
+ 'error_message' => 'User has blocked requests through HTTP.',
+ 'expected_error_code' => 'user-has-blocked-requests-through-http',
+ ),
+ ),
+ 'site url already exists message' => array(
+ array(
+ 'has_credentials' => true,
+ 'error_code' => 'request_failed',
+ 'error_message' => 'A site with the given URL already exists',
+ 'expected_error_code' => 'a-site-with-the-given-url-already-exists',
+ ),
+ ),
+ 'unable to retrieve site connection message' => array(
+ array(
+ 'has_credentials' => true,
+ 'error_code' => 'request_failed',
+ 'error_message' => 'Unable to retrieve site connection. You may need to perform a plugin reset',
+ 'expected_error_code' => 'unable-to-retrieve-site-connection-you-may-need-to-perform-a-plugin-reset',
+ ),
+ ),
);
}