PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 16.2-a.1
Jetpack – WP Security, Backup, Speed, & Growth v16.2-a.1
16.1.2 16.2-a.1 16.1.1 16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / jetpack_vendor / automattic / jetpack-stats-admin / src / class-wpcom-client.php
jetpack / jetpack_vendor / automattic / jetpack-stats-admin / src Last commit date
class-admin-post-list-column.php 4 days ago class-dashboard.php 4 days ago class-main.php 4 days ago class-notices.php 8 months ago class-odyssey-assets.php 2 weeks ago class-odyssey-config-data.php 4 days ago class-rest-controller.php 1 month ago class-wp-dashboard-odyssey-widget.php 2 years ago class-wpcom-client.php 4 days ago
class-wpcom-client.php
154 lines
1 <?php
2 /**
3 * A class that wraps `Automattic\Jetpack\Connection\Client` and handles cache and errors.
4 *
5 * @package automattic/jetpack-stats-admin
6 */
7
8 namespace Automattic\Jetpack\Stats_Admin;
9
10 use Automattic\Jetpack\Connection\Client;
11 use WP_Error;
12
13 /**
14 * A class that wraps `Automattic\Jetpack\Connection\Client` and handles cache and errors.
15 *
16 * @package Automattic\Jetpack\Stats_Admin
17 */
18 class WPCOM_Client {
19 /**
20 * Transient prefix for caching REST API responses.
21 *
22 * @var string
23 */
24 const CACHE_TRANSIENT_PREFIX = 'STATS_REST_RESP_';
25
26 /**
27 * Query the WordPress.com REST API using the blog token cached.
28 *
29 * @param String $path The API endpoint relative path.
30 * @param String $version The API version.
31 * @param array $args Request arguments.
32 * @param String $body Request body.
33 * @param String $base_api_path (optional) the API base path override, defaults to 'rest'.
34 * @param bool $use_cache (optional) default to true.
35 * @param string $cache_key (optional) default to null meaning the function auto generates cache key.
36 * @return array|WP_Error $response Data.
37 */
38 public static function request_as_blog_cached( $path, $version = '1.1', $args = array(), $body = null, $base_api_path = 'rest', $use_cache = true, $cache_key = null ) {
39 // Only allow caching GET requests.
40 $use_cache = $use_cache && ! ( isset( $args['method'] ) && strtoupper( $args['method'] ) !== 'GET' ) && ! static::should_bypass_cache();
41
42 // Arrays are serialized without considering the order of objects, but it's okay atm.
43 $cache_key = $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 ) ) );
44
45 if ( $use_cache ) {
46 $response_body_content = get_transient( $cache_key );
47 if ( false !== $response_body_content ) {
48 return json_decode( $response_body_content, true );
49 }
50 }
51
52 $response_body = static::request_as_blog( $path, $version, $args, $body, $base_api_path );
53
54 if ( is_wp_error( $response_body ) ) {
55 return $response_body;
56 }
57
58 // Cache the response for 5 minutes.
59 set_transient( $cache_key, wp_json_encode( $response_body, JSON_UNESCAPED_SLASHES ), 5 * MINUTE_IN_SECONDS );
60
61 return $response_body;
62 }
63
64 /**
65 * Query the WordPress.com REST API using the blog token
66 *
67 * @param String $path The API endpoint relative path.
68 * @param String $version The API version.
69 * @param array $args Request arguments.
70 * @param String $body Request body.
71 * @param String $base_api_path (optional) the API base path override, defaults to 'rest'.
72 * @return array|WP_Error $response Data.
73 */
74 public static function request_as_blog( $path, $version = '1.1', $args = array(), $body = null, $base_api_path = 'rest' ) {
75 $response = Client::wpcom_json_api_request_as_blog(
76 $path,
77 $version,
78 $args,
79 $body,
80 $base_api_path
81 );
82
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 if ( in_array( $response->get_error_code(), array( 'missing_token', 'no_possible_tokens' ), true ) ) {
89 return new WP_Error(
90 'site_not_connected',
91 __( 'This site is not connected to WordPress.com.', 'jetpack-stats-admin' ),
92 array( 'status' => 400 )
93 );
94 }
95
96 return $response;
97 }
98
99 $response_code = wp_remote_retrieve_response_code( $response );
100 $response_body_content = wp_remote_retrieve_body( $response );
101 $response_body = json_decode( $response_body_content, true );
102
103 $error = static::get_wp_error( $response_body, (int) $response_code );
104 if ( is_wp_error( $error ) ) {
105 return $error;
106 }
107
108 return $response_body;
109 }
110
111 /**
112 * Build error object from remote response body and status code.
113 *
114 * @param array $response_body Remote response body.
115 * @param int $response_code Http response code.
116 * @return WP_Error
117 */
118 protected static function get_wp_error( $response_body, $response_code = 200 ) {
119 $error_code = null;
120 foreach ( array( 'code', 'error' ) as $error_code_key ) {
121 if ( isset( $response_body[ $error_code_key ] ) ) {
122 $error_code = $response_body[ $error_code_key ];
123 break;
124 }
125 }
126
127 // Sometimes the response code could be 200 but the response body still contains an error.
128 if ( $error_code !== null || $response_code !== 200 ) {
129 return new WP_Error(
130 $error_code,
131 $response_body['message'] ?? 'unknown remote error',
132 array( 'status' => $response_code )
133 );
134 }
135
136 // No error.
137 return null;
138 }
139
140 /**
141 * Check if the cache should be bypassed.
142 *
143 * @return bool
144 */
145 protected static function should_bypass_cache() {
146 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
147 return isset( $_GET['force_refresh'] ) || isset( $_GET['statsPurchaseSuccess'] ) ||
148 // phpcs:ignore WordPress.Arrays.ArrayKeySpacingRestrictions.SpacesAroundArrayKeys, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
149 ( isset( $_SERVER[ 'HTTP_REFERER' ] ) && false !== strpos( $_SERVER[ 'HTTP_REFERER' ], 'force_refresh' ) ) ||
150 // phpcs:ignore WordPress.Arrays.ArrayKeySpacingRestrictions.SpacesAroundArrayKeys, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
151 ( isset( $_SERVER[ 'HTTP_REFERER' ] ) && false !== strpos( $_SERVER[ 'HTTP_REFERER' ], 'statsPurchaseSuccess' ) );
152 }
153 }
154