PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 4.6.3
Jetpack – WP Security, Backup, Speed, & Growth v4.6.3
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 / sal / class.json-api-links.php
jetpack / sal Last commit date
class.json-api-date.php 9 years ago class.json-api-links.php 9 years ago class.json-api-metadata.php 9 years ago class.json-api-platform-jetpack.php 9 years ago class.json-api-platform.php 9 years ago class.json-api-post-base.php 9 years ago class.json-api-post-jetpack.php 9 years ago class.json-api-site-base.php 9 years ago class.json-api-site-jetpack-base.php 9 years ago class.json-api-site-jetpack.php 9 years ago class.json-api-token.php 9 years ago
class.json-api-links.php
270 lines
1 <?php
2
3 require_once dirname( __FILE__ ) . '/../class.json-api.php';
4
5 class WPCOM_JSON_API_Links {
6 private $api;
7 private static $instance;
8
9 public static function getInstance() {
10 if ( null === self::$instance ) {
11 self::$instance = new self();
12 }
13
14 return self::$instance;
15 }
16
17 // protect these methods for singleton
18 protected function __construct() {
19 $this->api = WPCOM_JSON_API::init();
20 }
21 private function __clone() { }
22 private function __wakeup() { }
23
24 /**
25 * Generate a URL to an endpoint
26 *
27 * Used to construct meta links in API responses
28 *
29 * @param mixed $args Optional arguments to be appended to URL
30 * @return string Endpoint URL
31 **/
32 function get_link() {
33 $args = func_get_args();
34 $format = array_shift( $args );
35 $base = WPCOM_JSON_API__BASE;
36
37 $path = array_pop( $args );
38
39 if ( $path ) {
40 $path = '/' . ltrim( $path, '/' );
41 }
42
43 $args[] = $path;
44
45 // Escape any % in args before using sprintf
46 $escaped_args = array();
47 foreach ( $args as $arg_key => $arg_value ) {
48 $escaped_args[ $arg_key ] = str_replace( '%', '%%', $arg_value );
49 }
50
51 $relative_path = vsprintf( "$format%s", $escaped_args );
52
53 if ( ! wp_startswith( $relative_path, '.' ) ) {
54 // Generic version. Match the requested version as best we can
55 $api_version = $this->get_closest_version_of_endpoint( $format, $relative_path );
56 $base = substr( $base, 0, - 1 ) . $api_version;
57 }
58
59 // escape any % in the relative path before running it through sprintf again
60 $relative_path = str_replace( '%', '%%', $relative_path );
61 // http, WPCOM_JSON_API__BASE, ... , path
62 // %s , %s , $format, %s
63 return esc_url_raw( sprintf( "https://%s$relative_path", $base ) );
64 }
65
66 function get_me_link( $path = '' ) {
67 return $this->get_link( '/me', $path );
68 }
69
70 function get_taxonomy_link( $blog_id, $taxonomy_id, $taxonomy_type, $path = '' ) {
71 switch ( $taxonomy_type ) {
72 case 'category':
73 return $this->get_link( '/sites/%d/categories/slug:%s', $blog_id, $taxonomy_id, $path );
74
75 case 'post_tag':
76 return $this->get_link( '/sites/%d/tags/slug:%s', $blog_id, $taxonomy_id, $path );
77
78 default:
79 return $this->get_link( '/sites/%d/taxonomies/%s/terms/slug:%s', $blog_id, $taxonomy_type, $taxonomy_id, $path );
80 }
81 }
82
83 function get_media_link( $blog_id, $media_id, $path = '' ) {
84 return $this->get_link( '/sites/%d/media/%d', $blog_id, $media_id, $path );
85 }
86
87 function get_site_link( $blog_id, $path = '' ) {
88 return $this->get_link( '/sites/%d', $blog_id, $path );
89 }
90
91 function get_post_link( $blog_id, $post_id, $path = '' ) {
92 return $this->get_link( '/sites/%d/posts/%d', $blog_id, $post_id, $path );
93 }
94
95 function get_comment_link( $blog_id, $comment_id, $path = '' ) {
96 return $this->get_link( '/sites/%d/comments/%d', $blog_id, $comment_id, $path );
97 }
98
99 function get_publicize_connection_link( $blog_id, $publicize_connection_id, $path = '' ) {
100 return $this->get_link( '.1/sites/%d/publicize-connections/%d', $blog_id, $publicize_connection_id, $path );
101 }
102
103 function get_publicize_connections_link( $keyring_token_id, $path = '' ) {
104 return $this->get_link( '.1/me/publicize-connections/?keyring_connection_ID=%d', $keyring_token_id, $path );
105 }
106
107 function get_keyring_connection_link( $keyring_token_id, $path = '' ) {
108 return $this->get_link( '.1/me/keyring-connections/%d', $keyring_token_id, $path );
109 }
110
111 function get_external_service_link( $external_service, $path = '' ) {
112 return $this->get_link( '.1/meta/external-services/%s', $external_service, $path );
113 }
114
115 /**
116 * Try to find the closest supported version of an endpoint to the current endpoint
117 *
118 * For example, if we were looking at the path /animals/panda:
119 * - if the current endpoint is v1.3 and there is a v1.3 of /animals/%s available, we return 1.3
120 * - if the current endpoint is v1.3 and there is no v1.3 of /animals/%s known, we fall back to the
121 * maximum available version of /animals/%s, e.g. 1.1
122 *
123 * This method is used in get_link() to construct meta links for API responses.
124 *
125 * @param $template_path The generic endpoint path, e.g. /sites/%s
126 * @param $path string The current endpoint path, relative to the version, e.g. /sites/12345
127 * @param $method string Request method used to access the endpoint path
128 * @return string The current version, or otherwise the maximum version available
129 */
130 function get_closest_version_of_endpoint( $template_path, $path, $request_method = 'GET' ) {
131 static $closest_endpoint_cache;
132
133 if ( ! $closest_endpoint_cache ) {
134 $closest_endpoint_cache = array();
135 }
136
137 if ( ! isset( $closest_endpoint_cache[ $template_path ] ) ) {
138 $closest_endpoint_cache[ $template_path ] = array();
139 } elseif ( isset( $closest_endpoint_cache[ $template_path ][ $request_method ] ) ) {
140 return $closest_endpoint_cache[ $template_path ][ $request_method ];
141 }
142
143 $path = untrailingslashit( $path );
144
145 // /help is a special case - always use the current request version
146 if ( wp_endswith( $path, '/help' ) ) {
147 return $closest_endpoint_cache[ $template_path ][ $request_method ] = $this->api->version;
148 }
149
150 static $matches;
151 if ( empty( $matches ) ) {
152 $matches = array();
153 } else {
154 // try to match out of saved matches
155 foreach( $matches as $match ) {
156 $regex = $match->regex;
157 if ( preg_match( "#^$regex\$#", $path ) ) {
158 return $closest_endpoint_cache[ $template_path ][ $request_method ] = $match->version;
159 }
160 }
161 }
162
163 $endpoint_path_versions = $this->get_endpoint_path_versions();
164 $last_path_segment = $this->get_last_segment_of_relative_path( $path );
165 $max_version_found = null;
166
167 foreach ( $endpoint_path_versions as $endpoint_last_path_segment => $endpoints ) {
168
169 // Does the last part of the path match the path key? (e.g. 'posts')
170 // If the last part contains a placeholder (e.g. %s), we want to carry on
171 if ( $last_path_segment != $endpoint_last_path_segment && ! strstr( $endpoint_last_path_segment, '%' ) ) {
172 continue;
173 }
174
175 foreach ( $endpoints as $endpoint ) {
176 // Does the request method match?
177 if ( ! in_array( $request_method, $endpoint['request_methods'] ) ) {
178 continue;
179 }
180
181 $endpoint_path = untrailingslashit( $endpoint['path'] );
182 $endpoint_path_regex = str_replace( array( '%s', '%d' ), array( '([^/?&]+)', '(\d+)' ), $endpoint_path );
183
184 if ( ! preg_match( "#^$endpoint_path_regex\$#", $path ) ) {
185 continue;
186 }
187
188 // Make sure the endpoint exists at the same version
189 if ( version_compare( $this->api->version, $endpoint['min_version'], '>=') &&
190 version_compare( $this->api->version, $endpoint['max_version'], '<=') ) {
191 array_push( $matches, (object) array( 'version' => $this->api->version, 'regex' => $endpoint_path_regex ) );
192 return $closest_endpoint_cache[ $template_path ][ $request_method ] = $this->api->version;
193 }
194
195 // If the endpoint doesn't exist at the same version, record the max version we found
196 if ( empty( $max_version_found ) || version_compare( $max_version_found['version'], $endpoint['max_version'], '<' ) ) {
197 $max_version_found = array( 'version' => $endpoint['max_version'], 'regex' => $endpoint_path_regex );
198 }
199 }
200 }
201
202 // If the endpoint version is less than the requested endpoint version, return the max version found
203 if ( ! empty( $max_version_found ) ) {
204 array_push( $matches, (object) $max_version_found );
205 return $max_version_found['version'];
206 }
207
208 // Otherwise, use the API version of the current request
209 return $this->api->version;
210 }
211
212 /**
213 * Get an array of endpoint paths with their associated versions
214 *
215 * The result is cached for 30 minutes.
216 *
217 * @return array Array of endpoint paths, min_versions and max_versions, keyed by last segment of path
218 **/
219 protected function get_endpoint_path_versions() {
220
221 static $cache_result;
222
223 if ( ! empty ( $cache_result ) ) {
224 return $cache_result;
225 }
226
227 /*
228 * Create a map of endpoints and their min/max versions keyed by the last segment of the path (e.g. 'posts')
229 * This reduces the search space when finding endpoint matches in get_closest_version_of_endpoint()
230 */
231 $endpoint_path_versions = array();
232
233 foreach ( $this->api->endpoints as $key => $endpoint_objects ) {
234
235 // The key contains a serialized path, min_version and max_version
236 list( $path, $min_version, $max_version ) = unserialize( $key );
237
238 // Grab the last component of the relative path to use as the top-level key
239 $last_path_segment = $this->get_last_segment_of_relative_path( $path );
240
241 $endpoint_path_versions[ $last_path_segment ][] = array(
242 'path' => $path,
243 'min_version' => $min_version,
244 'max_version' => $max_version,
245 'request_methods' => array_keys( $endpoint_objects )
246 );
247 }
248
249 $cache_result = $endpoint_path_versions;
250
251 return $endpoint_path_versions;
252 }
253
254 /**
255 * Grab the last segment of a relative path
256 *
257 * @param string $path Path
258 * @return string Last path segment
259 */
260 protected function get_last_segment_of_relative_path( $path) {
261 $path_parts = array_filter( explode( '/', $path ) );
262
263 if ( empty( $path_parts ) ) {
264 return null;
265 }
266
267 return end( $path_parts );
268 }
269 }
270