← All changes
|
jetpack_vendor/automattic/jetpack-stats-admin/src/class-wpcom-client.php
+33
-6
13.7.2
→
16.3-beta
View file →
| @@ -16,8 +16,15 @@ | ||
| 16 | 16 | * @package Automattic\Jetpack\Stats_Admin |
| 17 | 17 | */ |
| 18 | 18 | class WPCOM_Client { |
| 19 | 19 | /** |
| 20 | + * Transient prefix for caching REST API responses. | |
| 21 | + * | |
| 22 | + * @var string | |
| 23 | + */ | |
| 24 | + const CACHE_TRANSIENT_PREFIX = 'STATS_REST_RESP_'; | |
| 25 | + | |
| 26 | + /** | |
| 20 | 27 | * Query the WordPress.com REST API using the blog token cached. |
| 21 | 28 | * |
| 22 | 29 | * @param String $path The API endpoint relative path. |
| 23 | 30 | * @param String $version The API version. |
| @@ -32,9 +39,9 @@ | ||
| 32 | 39 | // Only allow caching GET requests. |
| 33 | 40 | $use_cache = $use_cache && ! ( isset( $args['method'] ) && strtoupper( $args['method'] ) !== 'GET' ) && ! static::should_bypass_cache(); |
| 34 | 41 | |
| 35 | 42 | // Arrays are serialized without considering the order of objects, but it's okay atm. |
| 36 | - $cache_key = $cache_key !== null ? $cache_key : 'STATS_REST_RESP_' . md5( implode( '|', array( $path, $version, wp_json_encode( $args ), wp_json_encode( $body ), $base_api_path ) ) ); | |
| 43 | + $cache_key ??= self::CACHE_TRANSIENT_PREFIX . md5( implode( '|', array( $path, $version, wp_json_encode( $args, JSON_UNESCAPED_SLASHES ), wp_json_encode( $body, JSON_UNESCAPED_SLASHES ), $base_api_path ) ) ); | |
| 37 | 44 | |
| 38 | 45 | if ( $use_cache ) { |
| 39 | 46 | $response_body_content = get_transient( $cache_key ); |
| 40 | 47 | if ( false !== $response_body_content ) { |
| @@ -47,12 +54,10 @@ | ||
| 47 | 54 | if ( is_wp_error( $response_body ) ) { |
| 48 | 55 | return $response_body; |
| 49 | 56 | } |
| 50 | 57 | |
| 51 | - if ( $use_cache ) { | |
| 52 | - // Cache the successful JSON response for 5 minutes. | |
| 53 | - set_transient( $cache_key, wp_json_encode( $response_body ), 5 * MINUTE_IN_SECONDS ); | |
| 54 | - } | |
| 58 | + // Cache the response for 5 minutes. | |
| 59 | + set_transient( $cache_key, wp_json_encode( $response_body, JSON_UNESCAPED_SLASHES ), 5 * MINUTE_IN_SECONDS ); | |
| 55 | 60 | |
| 56 | 61 | return $response_body; |
| 57 | 62 | } |
| 58 | 63 | |
| @@ -75,8 +80,21 @@ | ||
| 75 | 80 | $base_api_path |
| 76 | 81 | ); |
| 77 | 82 | |
| 78 | 83 | if ( is_wp_error( $response ) ) { |
| 84 | + // `Client` fails before sending anything when the site holds no blog token, and that | |
| 85 | + // error carries no status, which the REST API renders as a 500. Say what actually | |
| 86 | + // happened so callers can tell an unconnected site from a broken one. Newer connection | |
| 87 | + // packages name the reason (`no_possible_tokens`); older ones return `missing_token`. | |
| 88 | + // `malformed_token` means the stored token has no secret half and cannot sign anything. | |
| 89 | + if ( in_array( $response->get_error_code(), array( 'missing_token', 'no_possible_tokens', 'malformed_token' ), true ) ) { | |
| 90 | + return new WP_Error( | |
| 91 | + 'site_not_connected', | |
| 92 | + __( 'This site is not connected to WordPress.com.', 'jetpack-stats-admin' ), | |
| 93 | + array( 'status' => 400 ) | |
| 94 | + ); | |
| 95 | + } | |
| 96 | + | |
| 79 | 97 | return $response; |
| 80 | 98 | } |
| 81 | 99 | |
| 82 | 100 | $response_code = wp_remote_retrieve_response_code( $response ); |
| @@ -84,8 +102,17 @@ | ||
| 84 | 102 | $response_body = json_decode( $response_body_content, true ); |
| 85 | 103 | |
| 86 | 104 | $error = static::get_wp_error( $response_body, (int) $response_code ); |
| 87 | 105 | if ( is_wp_error( $error ) ) { |
| 106 | + // Unknown token keys and incorrect secrets also mean the site cannot authenticate. | |
| 107 | + // Expose these rejections like a missing token so callers can identify the broken connection. | |
| 108 | + if ( in_array( $error->get_error_code(), array( 'invalid_token', 'unknown_token', 'signature_mismatch' ), true ) ) { | |
| 109 | + return new WP_Error( | |
| 110 | + 'site_not_connected', | |
| 111 | + __( 'This site is not connected to WordPress.com.', 'jetpack-stats-admin' ), | |
| 112 | + array( 'status' => 400 ) | |
| 113 | + ); | |
| 114 | + } | |
| 88 | 115 | return $error; |
| 89 | 116 | } |
| 90 | 117 | |
| 91 | 118 | return $response_body; |
| @@ -110,9 +137,9 @@ | ||
| 110 | 137 | // Sometimes the response code could be 200 but the response body still contains an error. |
| 111 | 138 | if ( $error_code !== null || $response_code !== 200 ) { |
| 112 | 139 | return new WP_Error( |
| 113 | 140 | $error_code, |
| 114 | - isset( $response_body['message'] ) ? $response_body['message'] : 'unknown remote error', | |
| 141 | + $response_body['message'] ?? 'unknown remote error', | |
| 115 | 142 | array( 'status' => $response_code ) |
| 116 | 143 | ); |
| 117 | 144 | } |
| 118 | 145 | |