PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 6.4
Jetpack – WP Security, Backup, Speed, & Growth v6.4
16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 All 501 releases
← All changes | class.json-api.php +182 -705 12.2.36.4 View file →
@@ -1,236 +1,77 @@
1 -<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2 -/**
3 - * Jetpack JSON API.
4 - *
5 - * @package automattic/jetpack
6 - */
1 +<?php
7 2
8 -use Automattic\Jetpack\Status;
3 +defined( 'WPCOM_JSON_API__DEBUG' ) or define( 'WPCOM_JSON_API__DEBUG', false );
9 4
10 -if ( ! defined( 'WPCOM_JSON_API__DEBUG' ) ) {
11 - define( 'WPCOM_JSON_API__DEBUG', false );
12 -}
5 +require_once dirname( __FILE__ ) . '/sal/class.json-api-platform.php';
13 6
14 -require_once __DIR__ . '/sal/class.json-api-platform.php';
15 -
16 -/**
17 - * Jetpack JSON API.
18 - */
19 7 class WPCOM_JSON_API {
20 - /**
21 - * Static instance.
22 - *
23 - * @todo This should be private.
24 - * @var self|null
25 - */
26 - public static $self = null;
8 + static $self = null;
27 9
28 - /**
29 - * Registered endpoints.
30 - *
31 - * @var WPCOM_JSON_API_Endpoint[]
32 - */
33 10 public $endpoints = array();
34 11
35 - /**
36 - * Endpoint being processed.
37 - *
38 - * @var WPCOM_JSON_API_Endpoint
39 - */
40 - public $endpoint = null;
41 -
42 - /**
43 - * Token details.
44 - *
45 - * @var array
46 - */
47 12 public $token_details = array();
48 13
49 - /**
50 - * Request HTTP method.
51 - *
52 - * @var string
53 - */
54 14 public $method = '';
55 -
56 - /**
57 - * Request URL.
58 - *
59 - * @var string
60 - */
61 15 public $url = '';
62 -
63 - /**
64 - * Path part of the request URL.
65 - *
66 - * @var string
67 - */
68 16 public $path = '';
69 -
70 - /**
71 - * Version extracted from the request URL.
72 - *
73 - * @var string|null
74 - */
75 17 public $version = null;
76 -
77 - /**
78 - * Parsed query data.
79 - *
80 - * @var array
81 - */
82 18 public $query = array();
83 -
84 - /**
85 - * Post body, if the request is a POST.
86 - *
87 - * @var string|null
88 - */
89 19 public $post_body = null;
90 -
91 - /**
92 - * Copy of `$_FILES` if the request is a POST.
93 - *
94 - * @var null|array
95 - */
96 20 public $files = null;
97 -
98 - /**
99 - * Content type of the request.
100 - *
101 - * @var string|null
102 - */
103 21 public $content_type = null;
104 -
105 - /**
106 - * Value of `$_SERVER['HTTP_ACCEPT']`, if any
107 - *
108 - * @var string
109 - */
110 22 public $accept = '';
111 23
112 - /**
113 - * Value of `$_SERVER['HTTPS']`, or "--UNset--" if unset.
114 - *
115 - * @var string
116 - */
117 - public $_server_https; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore
118 -
119 - /**
120 - * Whether to exit after serving a response.
121 - *
122 - * @var bool
123 - */
24 + public $_server_https;
124 25 public $exit = true;
125 -
126 - /**
127 - * Public API scheme.
128 - *
129 - * @var string
130 - */
131 26 public $public_api_scheme = 'https';
132 27
133 - /**
134 - * Output status code.
135 - *
136 - * @var int
137 - */
138 28 public $output_status_code = 200;
139 29
140 - /**
141 - * Trapped error.
142 - *
143 - * @var null|array
144 - */
145 30 public $trapped_error = null;
146 -
147 - /**
148 - * Whether output has been done.
149 - *
150 - * @var bool
151 - */
152 31 public $did_output = false;
153 32
154 - /**
155 - * Extra HTTP headers.
156 - *
157 - * @var string
158 - */
159 33 public $extra_headers = array();
160 34
161 35 /**
162 - * AMP source origin.
163 - *
164 - * @var string
165 - */
166 - public $amp_source_origin = null;
167 -
168 - /**
169 - * Initialize.
170 - *
171 - * @param string|null $method As for `$this->setup_inputs()`.
172 - * @param string|null $url As for `$this->setup_inputs()`.
173 - * @param string|null $post_body As for `$this->setup_inputs()`.
174 36 * @return WPCOM_JSON_API instance
175 37 */
176 - public static function init( $method = null, $url = null, $post_body = null ) {
177 - if ( ! self::$self ) {
178 - $class = function_exists( 'get_called_class' ) ? get_called_class() : __CLASS__; // phpcs:ignore PHPCompatibility.PHP.NewFunctions.get_called_classFound
38 + static function init( $method = null, $url = null, $post_body = null ) {
39 + if ( !self::$self ) {
40 + $class = function_exists( 'get_called_class' ) ? get_called_class() : __CLASS__; // phpcs:ignore PHPCompatibility
179 41 self::$self = new $class( $method, $url, $post_body );
180 42 }
181 43 return self::$self;
182 44 }
183 45
184 - /**
185 - * Add an endpoint.
186 - *
187 - * @param WPCOM_JSON_API_Endpoint $endpoint Endpoint to add.
188 - */
189 - public function add( WPCOM_JSON_API_Endpoint $endpoint ) {
190 - // @todo Determine if anything depends on this being serialized rather than e.g. JSON.
191 - // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize -- Legacy, possibly depended on elsewhere.
192 - $path_versions = serialize(
193 - array(
194 - $endpoint->path,
195 - $endpoint->min_version,
196 - $endpoint->max_version,
197 - )
198 - );
199 - if ( ! isset( $this->endpoints[ $path_versions ] ) ) {
200 - $this->endpoints[ $path_versions ] = array();
46 + function add( WPCOM_JSON_API_Endpoint $endpoint ) {
47 + $path_versions = serialize( array (
48 + $endpoint->path,
49 + $endpoint->min_version,
50 + $endpoint->max_version,
51 + ) );
52 + if ( !isset( $this->endpoints[$path_versions] ) ) {
53 + $this->endpoints[$path_versions] = array();
201 54 }
202 - $this->endpoints[ $path_versions ][ $endpoint->method ] = $endpoint;
55 + $this->endpoints[$path_versions][$endpoint->method] = $endpoint;
203 56 }
204 57
205 - /**
206 - * Determine if a string is truthy.
207 - *
208 - * @param string $value "1", "t", and "true" (case insensitive) are falsey, everything else isn't.
209 - * @return bool
210 - */
211 - public static function is_truthy( $value ) {
58 + static function is_truthy( $value ) {
212 59 switch ( strtolower( (string) $value ) ) {
213 - case '1':
214 - case 't':
215 - case 'true':
216 - return true;
60 + case '1' :
61 + case 't' :
62 + case 'true' :
63 + return true;
217 64 }
218 65
219 66 return false;
220 67 }
221 68
222 - /**
223 - * Determine if a string is falsey.
224 - *
225 - * @param string $value "0", "f", and "false" (case insensitive) are falsey, everything else isn't.
226 - * @return bool
227 - */
228 - public static function is_falsy( $value ) {
69 + static function is_falsy( $value ) {
229 70 switch ( strtolower( (string) $value ) ) {
230 - case '0':
231 - case 'f':
232 - case 'false':
71 + case '0' :
72 + case 'f' :
73 + case 'false' :
233 74 return true;
234 75 }
235 76
236 77 return false;
@@ -235,61 +76,44 @@
235 76
236 77 return false;
237 78 }
238 79
239 - /**
240 - * Constructor.
241 - *
242 - * @todo This should be private.
243 - * @param string|null $method As for `$this->setup_inputs()`.
244 - * @param string|null $url As for `$this->setup_inputs()`.
245 - * @param string|null $post_body As for `$this->setup_inputs()`.
246 - */
247 - public function __construct( $method = null, $url = null, $post_body = null ) {
248 - $this->setup_inputs( $method, $url, $post_body );
80 + function __construct() {
81 + $args = func_get_args();
82 + call_user_func_array( array( $this, 'setup_inputs' ), $args );
249 83 }
250 84
251 - /**
252 - * Setup inputs.
253 - *
254 - * @param string|null $method Request HTTP method. Fetched from `$_SERVER` if null.
255 - * @param string|null $url URL requested. Determined from `$_SERVER` if null.
256 - * @param string|null $post_body POST body. Read from `php://input` if null and method is POST.
257 - */
258 - public function setup_inputs( $method = null, $url = null, $post_body = null ) {
259 - if ( $method === null ) {
260 - $this->method = isset( $_SERVER['REQUEST_METHOD'] ) ? strtoupper( filter_var( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) ) : '';
85 + function setup_inputs( $method = null, $url = null, $post_body = null ) {
86 + if ( is_null( $method ) ) {
87 + $this->method = strtoupper( $_SERVER['REQUEST_METHOD'] );
261 88 } else {
262 89 $this->method = strtoupper( $method );
263 90 }
264 - if ( $url === null ) {
265 - // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sniff misses the esc_url_raw.
266 - $this->url = esc_url_raw( set_url_scheme( 'http://' . ( isset( $_SERVER['HTTP_HOST'] ) ? wp_unslash( $_SERVER['HTTP_HOST'] ) : '' ) . ( isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '' ) ) );
91 + if ( is_null( $url ) ) {
92 + $this->url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
267 93 } else {
268 94 $this->url = $url;
269 95 }
270 96
271 - $parsed = wp_parse_url( $this->url );
272 - if ( ! empty( $parsed['path'] ) ) {
273 - $this->path = $parsed['path'];
274 - }
97 + $parsed = parse_url( $this->url );
98 + $this->path = $parsed['path'];
275 99
276 - if ( ! empty( $parsed['query'] ) ) {
100 + if ( !empty( $parsed['query'] ) ) {
277 101 wp_parse_str( $parsed['query'], $this->query );
278 102 }
279 103
280 - if ( ! empty( $_SERVER['HTTP_ACCEPT'] ) ) {
281 - $this->accept = filter_var( wp_unslash( $_SERVER['HTTP_ACCEPT'] ) );
104 + if ( isset( $_SERVER['HTTP_ACCEPT'] ) && $_SERVER['HTTP_ACCEPT'] ) {
105 + $this->accept = $_SERVER['HTTP_ACCEPT'];
282 106 }
283 107
284 108 if ( 'POST' === $this->method ) {
285 - if ( $post_body === null ) {
109 + if ( is_null( $post_body ) ) {
286 110 $this->post_body = file_get_contents( 'php://input' );
287 111
288 - if ( ! empty( $_SERVER['HTTP_CONTENT_TYPE'] ) ) {
289 - $this->content_type = filter_var( wp_unslash( $_SERVER['HTTP_CONTENT_TYPE'] ) );
290 - } elseif ( ! empty( $_SERVER['CONTENT_TYPE'] ) ) {
291 - $this->content_type = filter_var( wp_unslash( $_SERVER['CONTENT_TYPE'] ) );
112 + if ( isset( $_SERVER['HTTP_CONTENT_TYPE'] ) && $_SERVER['HTTP_CONTENT_TYPE'] ) {
113 + $this->content_type = $_SERVER['HTTP_CONTENT_TYPE'];
114 + } elseif ( isset( $_SERVER['CONTENT_TYPE'] ) && $_SERVER['CONTENT_TYPE'] ) {
115 + $this->content_type = $_SERVER['CONTENT_TYPE'] ;
292 116 } elseif ( '{' === $this->post_body[0] ) {
293 117 $this->content_type = 'application/json';
294 118 } else {
295 119 $this->content_type = 'application/x-www-form-urlencoded';
@@ -295,83 +119,36 @@
295 119 $this->content_type = 'application/x-www-form-urlencoded';
296 120 }
297 121
298 122 if ( 0 === strpos( strtolower( $this->content_type ), 'multipart/' ) ) {
299 - // phpcs:ignore WordPress.Security.NonceVerification.Missing
300 - $this->post_body = http_build_query( stripslashes_deep( $_POST ) );
301 - $this->files = $_FILES;
123 + $this->post_body = http_build_query( stripslashes_deep( $_POST ) );
124 + $this->files = $_FILES;
302 125 $this->content_type = 'multipart/form-data';
303 126 }
304 127 } else {
305 - $this->post_body = $post_body;
306 - $this->content_type = isset( $this->post_body[0] ) && '{' === $this->post_body[0] ? 'application/json' : 'application/x-www-form-urlencoded';
128 + $this->post_body = $post_body;
129 + $this->content_type = '{' === isset( $this->post_body[0] ) && $this->post_body[0] ? 'application/json' : 'application/x-www-form-urlencoded';
307 130 }
308 131 } else {
309 - $this->post_body = null;
132 + $this->post_body = null;
310 133 $this->content_type = null;
311 134 }
312 135
313 - $this->_server_https = array_key_exists( 'HTTPS', $_SERVER ) ? filter_var( wp_unslash( $_SERVER['HTTPS'] ) ) : '--UNset--';
136 + $this->_server_https = array_key_exists( 'HTTPS', $_SERVER ) ? $_SERVER['HTTPS'] : '--UNset--';
314 137 }
315 138
316 - /**
317 - * Initialize.
318 - *
319 - * @return null|WP_Error (although this implementation always returns null)
320 - */
321 - public function initialize() {
139 + function initialize() {
322 140 $this->token_details['blog_id'] = Jetpack_Options::get_option( 'id' );
323 - return null;
324 141 }
325 142
326 - /**
327 - * Checks if the current request is authorized with a blog token.
328 - * This method is overridden by a child class in WPCOM.
329 - *
330 - * @since 9.1.0
331 - *
332 - * @param boolean|int $site_id The site id.
333 - * @return boolean
334 - */
335 - public function is_jetpack_authorized_for_site( $site_id = false ) {
336 - if ( ! $this->token_details ) {
337 - return false;
338 - }
143 + function serve( $exit = true ) {
144 + ini_set( 'display_errors', false );
339 145
340 - $token_details = (object) $this->token_details;
341 -
342 - $site_in_token = (int) $token_details->blog_id;
343 -
344 - if ( $site_in_token < 1 ) {
345 - return false;
346 - }
347 -
348 - if ( $site_id && $site_in_token !== (int) $site_id ) {
349 - return false;
350 - }
351 -
352 - if ( (int) get_current_user_id() !== 0 ) {
353 - // If Jetpack blog token is used, no logged-in user should exist.
354 - return false;
355 - }
356 -
357 - return true;
358 - }
359 -
360 - /**
361 - * Serve.
362 - *
363 - * @param bool $exit Whether to exit.
364 - * @return string|null Content type (assuming it didn't exit), or null in certain error cases.
365 - */
366 - public function serve( $exit = true ) {
367 - ini_set( 'display_errors', false ); // phpcs:ignore WordPress.PHP.IniSet.display_errors_Blacklisted
368 -
369 146 $this->exit = (bool) $exit;
370 147
371 148 // This was causing problems with Jetpack, but is necessary for wpcom
372 149 // @see https://github.com/Automattic/jetpack/pull/2603
373 - // @see r124548-wpcom .
150 + // @see r124548-wpcom
374 151 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
375 152 add_filter( 'home_url', array( $this, 'ensure_http_scheme_of_home_url' ), 10, 3 );
376 153 }
377 154
@@ -379,9 +156,9 @@
379 156
380 157 add_filter( 'comment_edit_pre', array( $this, 'comment_edit_pre' ) );
381 158
382 159 $initialization = $this->initialize();
383 - if ( 'OPTIONS' === $this->method ) {
160 + if ( 'OPTIONS' == $this->method ) {
384 161 /**
385 162 * Fires before the page output.
386 163 * Can be used to specify custom header options.
387 164 *
@@ -397,32 +174,32 @@
397 174 $this->output_error( $initialization );
398 175 return;
399 176 }
400 177
401 - // Normalize path and extract API version.
178 + // Normalize path and extract API version
402 179 $this->path = untrailingslashit( $this->path );
403 180 preg_match( '#^/rest/v(\d+(\.\d+)*)#', $this->path, $matches );
404 - $this->path = substr( $this->path, strlen( $matches[0] ) );
181 + $this->path = substr( $this->path, strlen( $matches[0] ) );
405 182 $this->version = $matches[1];
406 183
407 184 $allowed_methods = array( 'GET', 'POST' );
408 - $four_oh_five = false;
185 + $four_oh_five = false;
409 186
410 - $is_help = preg_match( '#/help/?$#i', $this->path );
187 + $is_help = preg_match( '#/help/?$#i', $this->path );
411 188 $matching_endpoints = array();
412 189
413 190 if ( $is_help ) {
414 191 $origin = get_http_origin();
415 192
416 - if ( ! empty( $origin ) && 'GET' === $this->method ) {
193 + if ( !empty( $origin ) && 'GET' == $this->method ) {
417 194 header( 'Access-Control-Allow-Origin: ' . esc_url_raw( $origin ) );
418 195 }
419 196
420 197 $this->path = substr( rtrim( $this->path, '/' ), 0, -5 );
421 - // Show help for all matching endpoints regardless of method.
422 - $methods = $allowed_methods;
198 + // Show help for all matching endpoints regardless of method
199 + $methods = $allowed_methods;
423 200 $find_all_matching_endpoints = true;
424 - // How deep to truncate each endpoint's path to see if it matches this help request.
201 + // How deep to truncate each endpoint's path to see if it matches this help request
425 202 $depth = substr_count( $this->path, '/' ) + 1;
426 203 if ( false !== stripos( $this->accept, 'javascript' ) || false !== stripos( $this->accept, 'json' ) ) {
427 204 $help_content_type = 'json';
428 205 } else {
@@ -427,50 +204,50 @@
427 204 $help_content_type = 'json';
428 205 } else {
429 206 $help_content_type = 'html';
430 207 }
431 - } elseif ( in_array( $this->method, $allowed_methods, true ) ) {
432 - // Only serve requested method.
433 - $methods = array( $this->method );
434 - $find_all_matching_endpoints = false;
435 208 } else {
436 - // We don't allow this requested method - find matching endpoints and send 405.
437 - $methods = $allowed_methods;
438 - $find_all_matching_endpoints = true;
439 - $four_oh_five = true;
209 + if ( in_array( $this->method, $allowed_methods ) ) {
210 + // Only serve requested method
211 + $methods = array( $this->method );
212 + $find_all_matching_endpoints = false;
213 + } else {
214 + // We don't allow this requested method - find matching endpoints and send 405
215 + $methods = $allowed_methods;
216 + $find_all_matching_endpoints = true;
217 + $four_oh_five = true;
218 + }
440 219 }
441 220
442 - // Find which endpoint to serve.
221 + // Find which endpoint to serve
443 222 $found = false;
444 223 foreach ( $this->endpoints as $endpoint_path_versions => $endpoints_by_method ) {
445 - // @todo Determine if anything depends on this being serialized rather than e.g. JSON.
446 - // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize -- Legacy, possibly depended on elsewhere.
447 224 $endpoint_path_versions = unserialize( $endpoint_path_versions );
448 - $endpoint_path = $endpoint_path_versions[0];
449 - $endpoint_min_version = $endpoint_path_versions[1];
450 - $endpoint_max_version = $endpoint_path_versions[2];
225 + $endpoint_path = $endpoint_path_versions[0];
226 + $endpoint_min_version = $endpoint_path_versions[1];
227 + $endpoint_max_version = $endpoint_path_versions[2];
451 228
452 - // Make sure max_version is not less than min_version.
229 + // Make sure max_version is not less than min_version
453 230 if ( version_compare( $endpoint_max_version, $endpoint_min_version, '<' ) ) {
454 231 $endpoint_max_version = $endpoint_min_version;
455 232 }
456 233
457 234 foreach ( $methods as $method ) {
458 - if ( ! isset( $endpoints_by_method[ $method ] ) ) {
235 + if ( !isset( $endpoints_by_method[$method] ) ) {
459 236 continue;
460 237 }
461 238
462 - // Normalize.
239 + // Normalize
463 240 $endpoint_path = untrailingslashit( $endpoint_path );
464 241 if ( $is_help ) {
465 - // Truncate path at help depth.
466 - $endpoint_path = implode( '/', array_slice( explode( '/', $endpoint_path ), 0, $depth ) );
242 + // Truncate path at help depth
243 + $endpoint_path = join( '/', array_slice( explode( '/', $endpoint_path ), 0, $depth ) );
467 244 }
468 245
469 - // Generate regular expression from sprintf().
246 + // Generate regular expression from sprintf()
470 247 $endpoint_path_regex = str_replace( array( '%s', '%d' ), array( '([^/?&]+)', '(\d+)' ), $endpoint_path );
471 248
472 - if ( ! preg_match( "#^$endpoint_path_regex\$#", $this->path, $path_pieces ) ) {
249 + if ( !preg_match( "#^$endpoint_path_regex\$#", $this->path, $path_pieces ) ) {
473 250 // This endpoint does not match the requested path.
474 251 continue;
475 252 }
476 253
@@ -481,18 +258,18 @@
481 258
482 259 $found = true;
483 260
484 261 if ( $find_all_matching_endpoints ) {
485 - $matching_endpoints[] = array( $endpoints_by_method[ $method ], $path_pieces );
262 + $matching_endpoints[] = array( $endpoints_by_method[$method], $path_pieces );
486 263 } else {
487 - // The method parameters are now in $path_pieces.
488 - $endpoint = $endpoints_by_method[ $method ];
264 + // The method parameters are now in $path_pieces
265 + $endpoint = $endpoints_by_method[$method];
489 266 break 2;
490 267 }
491 268 }
492 269 }
493 270
494 - if ( ! $found ) {
271 + if ( !$found ) {
495 272 return $this->output( 404, '', 'text/plain' );
496 273 }
497 274
498 275 if ( $four_oh_five ) {
@@ -500,16 +277,10 @@
500 277 foreach ( $matching_endpoints as $matching_endpoint ) {
501 278 $allowed_methods[] = $matching_endpoint[0]->method;
502 279 }
503 280
504 - header( 'Allow: ' . strtoupper( implode( ',', array_unique( $allowed_methods ) ) ) );
505 - return $this->output(
506 - 405,
507 - array(
508 - 'error' => 'not_allowed',
509 - 'error_message' => 'Method not allowed',
510 - )
511 - );
281 + header( 'Allow: ' . strtoupper( join( ',', array_unique( $allowed_methods ) ) ) );
282 + return $this->output( 405, array( 'error' => 'not_allowed', 'error_message' => 'Method not allowed' ) );
512 283 }
513 284
514 285 if ( $is_help ) {
515 286 /**
@@ -523,25 +294,23 @@
523 294 $proxied = function_exists( 'wpcom_is_proxied_request' ) ? wpcom_is_proxied_request() : false;
524 295 if ( 'json' === $help_content_type ) {
525 296 $docs = array();
526 297 foreach ( $matching_endpoints as $matching_endpoint ) {
527 - if ( $matching_endpoint[0]->is_publicly_documentable() || $proxied || WPCOM_JSON_API__DEBUG ) {
298 + if ( $matching_endpoint[0]->is_publicly_documentable() || $proxied || WPCOM_JSON_API__DEBUG )
528 299 $docs[] = call_user_func( array( $matching_endpoint[0], 'generate_documentation' ) );
529 - }
530 300 }
531 301 return $this->output( 200, $docs );
532 302 } else {
533 303 status_header( 200 );
534 304 foreach ( $matching_endpoints as $matching_endpoint ) {
535 - if ( $matching_endpoint[0]->is_publicly_documentable() || $proxied || WPCOM_JSON_API__DEBUG ) {
305 + if ( $matching_endpoint[0]->is_publicly_documentable() || $proxied || WPCOM_JSON_API__DEBUG )
536 306 call_user_func( array( $matching_endpoint[0], 'document' ) );
537 - }
538 307 }
539 308 }
540 309 exit;
541 310 }
542 311
543 - if ( $endpoint->in_testing && ! WPCOM_JSON_API__DEBUG ) {
312 + if ( $endpoint->in_testing && !WPCOM_JSON_API__DEBUG ) {
544 313 return $this->output( 404, '', 'text/plain' );
545 314 }
546 315
547 316 /** This action is documented in class.json-api.php */
@@ -548,9 +317,9 @@
548 317 do_action( 'wpcom_json_api_output', $endpoint->stat );
549 318
550 319 $response = $this->process_request( $endpoint, $path_pieces );
551 320
552 - if ( ! $response && ! is_array( $response ) ) {
321 + if ( !$response && !is_array( $response ) ) {
553 322 return $this->output( 500, '', 'text/plain' );
554 323 } elseif ( is_wp_error( $response ) ) {
555 324 return $this->output_error( $response );
556 325 }
@@ -560,35 +329,20 @@
560 329
561 330 return $this->output( $output_status_code, $response, 'application/json', $this->extra_headers );
562 331 }
563 332
564 - /**
565 - * Process a request.
566 - *
567 - * @param WPCOM_JSON_API_Endpoint $endpoint Endpoint.
568 - * @param array $path_pieces Path pieces.
569 - * @return array|WP_Error Return value from the endpoint's callback.
570 - */
571 - public function process_request( WPCOM_JSON_API_Endpoint $endpoint, $path_pieces ) {
333 + function process_request( WPCOM_JSON_API_Endpoint $endpoint, $path_pieces ) {
572 334 $this->endpoint = $endpoint;
573 335 return call_user_func_array( array( $endpoint, 'callback' ), $path_pieces );
574 336 }
575 337
576 - /**
577 - * Output a response or error without exiting.
578 - *
579 - * @param int $status_code HTTP status code.
580 - * @param mixed $response Response data.
581 - * @param string $content_type Content type of the response.
582 - */
583 - public function output_early( $status_code, $response = null, $content_type = 'application/json' ) {
584 - $exit = $this->exit;
338 + function output_early( $status_code, $response = null, $content_type = 'application/json' ) {
339 + $exit = $this->exit;
585 340 $this->exit = false;
586 - if ( is_wp_error( $response ) ) {
341 + if ( is_wp_error( $response ) )
587 342 $this->output_error( $response );
588 - } else {
343 + else
589 344 $this->output( $status_code, $response, $content_type );
590 - }
591 345 $this->exit = $exit;
592 346 if ( ! defined( 'XMLRPC_REQUEST' ) || ! XMLRPC_REQUEST ) {
593 347 $this->finish_request();
594 348 }
@@ -593,61 +347,36 @@
593 347 $this->finish_request();
594 348 }
595 349 }
596 350
597 - /**
598 - * Set output status code.
599 - *
600 - * @param int $code HTTP status code.
601 - */
602 - public function set_output_status_code( $code = 200 ) {
351 + function set_output_status_code( $code = 200 ) {
603 352 $this->output_status_code = $code;
604 353 }
605 354
606 - /**
607 - * Output a response.
608 - *
609 - * @param int $status_code HTTP status code.
610 - * @param mixed $response Response data.
611 - * @param string $content_type Content type of the response.
612 - * @param array $extra Additional HTTP headers.
613 - * @return string Content type (assuming it didn't exit).
614 - */
615 - public function output( $status_code, $response = null, $content_type = 'application/json', $extra = array() ) {
616 - $status_code = (int) $status_code;
617 -
618 - // In case output() was called before the callback returned.
355 + function output( $status_code, $response = null, $content_type = 'application/json', $extra = array() ) {
356 + // In case output() was called before the callback returned
619 357 if ( $this->did_output ) {
620 - if ( $this->exit ) {
358 + if ( $this->exit )
621 359 exit;
622 - }
623 360 return $content_type;
624 361 }
625 362 $this->did_output = true;
626 363
627 364 // 400s and 404s are allowed for all origins
628 - if ( 404 === $status_code || 400 === $status_code ) {
365 + if ( 404 == $status_code || 400 == $status_code )
629 366 header( 'Access-Control-Allow-Origin: *' );
630 - }
631 367
632 - /* Add headers for form submission from <amp-form/> */
633 - if ( $this->amp_source_origin ) {
634 - header( 'Access-Control-Allow-Origin: ' . wp_unslash( $this->amp_source_origin ) );
635 - header( 'Access-Control-Allow-Credentials: true' );
368 + if ( is_null( $response ) ) {
369 + $response = new stdClass;
636 370 }
637 371
638 - if ( $response === null ) {
639 - $response = new stdClass();
640 - }
641 -
642 - if ( 'text/plain' === $content_type ||
643 - 'text/html' === $content_type ) {
372 + if ( 'text/plain' === $content_type ) {
644 373 status_header( (int) $status_code );
645 - header( 'Content-Type: ' . $content_type );
646 - foreach ( $extra as $key => $value ) {
374 + header( 'Content-Type: text/plain' );
375 + foreach( $extra as $key => $value ) {
647 376 header( "$key: $value" );
648 377 }
649 - echo $response; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
378 + echo $response;
650 379 if ( $this->exit ) {
651 380 exit;
652 381 }
653 382
@@ -658,26 +387,23 @@
658 387
659 388 if ( isset( $this->query['http_envelope'] ) && self::is_truthy( $this->query['http_envelope'] ) ) {
660 389 $headers = array(
661 390 array(
662 - 'name' => 'Content-Type',
391 + 'name' => 'Content-Type',
663 392 'value' => $content_type,
664 - ),
393 + )
665 394 );
666 395
667 - foreach ( $extra as $key => $value ) {
668 - $headers[] = array(
669 - 'name' => $key,
670 - 'value' => $value,
671 - );
396 + foreach( $extra as $key => $value ) {
397 + $headers[] = array( 'name' => $key, 'value' => $value );
672 398 }
673 399
674 - $response = array(
675 - 'code' => (int) $status_code,
400 + $response = array(
401 + 'code' => (int) $status_code,
676 402 'headers' => $headers,
677 - 'body' => $response,
403 + 'body' => $response,
678 404 );
679 - $status_code = 200;
405 + $status_code = 200;
680 406 $content_type = 'application/json';
681 407 }
682 408
683 409 status_header( (int) $status_code );
@@ -690,15 +416,15 @@
690 416
691 417 if ( $callback ) {
692 418 // Mitigate Rosetta Flash [1] by setting the Content-Type-Options: nosniff header
693 419 // and by prepending the JSONP response with a JS comment.
694 - // [1] <https://blog.miki.it/2014/7/8/abusing-jsonp-with-rosetta-flash/index.html>.
695 - echo "/**/$callback("; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- This is JSONP output, not HTML.
420 + // [1] http://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/
421 + echo "/**/$callback(";
696 422
697 423 }
698 - echo $this->json_encode( $response ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- This is JSON or JSONP output, not HTML.
424 + echo $this->json_encode( $response );
699 425 if ( $callback ) {
700 - echo ');';
426 + echo ");";
701 427 }
702 428
703 429 if ( $this->exit ) {
704 430 exit;
@@ -706,15 +432,9 @@
706 432
707 433 return $content_type;
708 434 }
709 435
710 - /**
711 - * Serialize an error.
712 - *
713 - * @param WP_Error $error Error.
714 - * @return array with 'status_code' and 'errors' data.
715 - */
716 - public static function serializable_error( $error ) {
436 + public static function serializable_error ( $error ) {
717 437
718 438 $status_code = $error->get_error_data();
719 439
720 440 if ( is_array( $status_code ) ) {
@@ -720,9 +440,9 @@
720 440 if ( is_array( $status_code ) ) {
721 441 $status_code = $status_code['status_code'];
722 442 }
723 443
724 - if ( ! $status_code ) {
444 + if ( !$status_code ) {
725 445 $status_code = 400;
726 446 }
727 447 $response = array(
728 448 'error' => $error->get_error_code(),
@@ -728,41 +448,27 @@
728 448 'error' => $error->get_error_code(),
729 449 'message' => $error->get_error_message(),
730 450 );
731 451
732 - $additional_data = $error->get_error_data( 'additional_data' );
733 - if ( $additional_data ) {
452 + if ( $additional_data = $error->get_error_data( 'additional_data' ) ) {
734 453 $response['data'] = $additional_data;
735 454 }
736 455
737 456 return array(
738 457 'status_code' => $status_code,
739 - 'errors' => $response,
458 + 'errors' => $response
740 459 );
741 460 }
742 461
743 - /**
744 - * Output an error.
745 - *
746 - * @param WP_Error $error Error.
747 - * @return string Content type (assuming it didn't exit).
748 - */
749 - public function output_error( $error ) {
462 + function output_error( $error ) {
750 463 $error_response = $this->serializable_error( $error );
751 464
752 - return $this->output( $error_response['status_code'], $error_response['errors'] );
465 + return $this->output( $error_response[ 'status_code'], $error_response['errors'] );
753 466 }
754 467
755 - /**
756 - * Filter fields in a response.
757 - *
758 - * @param array|object $response Response.
759 - * @return array|object Filtered response.
760 - */
761 - public function filter_fields( $response ) {
762 - if ( empty( $this->query['fields'] ) || ( is_array( $response ) && ! empty( $response['error'] ) ) || ! empty( $this->endpoint->custom_fields_filtering ) ) {
468 + function filter_fields( $response ) {
469 + if ( empty( $this->query['fields'] ) || ( is_array( $response ) && ! empty( $response['error'] ) ) || ! empty( $this->endpoint->custom_fields_filtering ) )
763 470 return $response;
764 - }
765 471
766 472 $fields = array_map( 'trim', explode( ',', $this->query['fields'] ) );
767 473
768 474 if ( is_object( $response ) ) {
@@ -790,16 +496,14 @@
790 496 'users',
791 497 );
792 498
793 499 foreach ( $keys_to_filter as $key_to_filter ) {
794 - if ( ! isset( $response[ $key_to_filter ] ) || $has_filtered ) {
500 + if ( ! isset( $response[ $key_to_filter ] ) || $has_filtered )
795 501 continue;
796 - }
797 502
798 503 foreach ( $response[ $key_to_filter ] as $key => $values ) {
799 504 if ( is_object( $values ) ) {
800 505 if ( is_object( $response[ $key_to_filter ] ) ) {
801 - // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.Found -- False positive.
802 506 $response[ $key_to_filter ]->$key = (object) array_intersect_key( ( (array) $values ), array_flip( $fields ) );
803 507 } elseif ( is_array( $response[ $key_to_filter ] ) ) {
804 508 $response[ $key_to_filter ][ $key ] = (object) array_intersect_key( ( (array) $values ), array_flip( $fields ) );
805 509 }
@@ -814,9 +518,9 @@
814 518
815 519 if ( ! $has_filtered ) {
816 520 if ( is_object( $response ) ) {
817 521 $response = (object) array_intersect_key( (array) $response, array_flip( $fields ) );
818 - } elseif ( is_array( $response ) ) {
522 + } else if ( is_array( $response ) ) {
819 523 $response = array_intersect_key( $response, array_flip( $fields ) );
820 524 }
821 525 }
822 526
@@ -822,19 +526,9 @@
822 526
823 527 return $response;
824 528 }
825 529
826 - /**
827 - * Filter for `home_url`.
828 - *
829 - * If `$original_scheme` is null, turns an https URL to http.
830 - *
831 - * @param string $url The complete home URL including scheme and path.
832 - * @param string $path Path relative to the home URL. Blank string if no path is specified.
833 - * @param string|null $original_scheme Scheme to give the home URL context. Accepts 'http', 'https', 'relative', 'rest', or null.
834 - * @return string URL.
835 - */
836 - public function ensure_http_scheme_of_home_url( $url, $path, $original_scheme ) {
530 + function ensure_http_scheme_of_home_url( $url, $path, $original_scheme ) {
837 531 if ( $original_scheme ) {
838 532 return $url;
839 533 }
840 534
@@ -840,78 +534,36 @@
840 534
841 535 return preg_replace( '#^https:#', 'http:', $url );
842 536 }
843 537
844 - /**
845 - * Decode HTML special characters in comment content.
846 - *
847 - * @param string $comment_content Comment content.
848 - * @return string
849 - */
850 - public function comment_edit_pre( $comment_content ) {
538 + function comment_edit_pre( $comment_content ) {
851 539 return htmlspecialchars_decode( $comment_content, ENT_QUOTES );
852 540 }
853 541
854 - /**
855 - * JSON encode.
856 - *
857 - * @param mixed $data Data.
858 - * @return string|false
859 - */
860 - public function json_encode( $data ) {
861 - return wp_json_encode( $data );
542 + function json_encode( $data ) {
543 + return json_encode( $data );
862 544 }
863 545
864 - /**
865 - * Test if a string ends with a string.
866 - *
867 - * @param string $haystack String to check.
868 - * @param string $needle Suffix to check.
869 - * @return bool
870 - */
871 - public function ends_with( $haystack, $needle ) {
872 - return substr( $haystack, -strlen( $needle ) ) === $needle;
546 + function ends_with( $haystack, $needle ) {
547 + return $needle === substr( $haystack, -strlen( $needle ) );
873 548 }
874 549
875 - /**
876 - * Returns the site's blog_id in the WP.com ecosystem
877 - *
878 - * @return int
879 - */
880 - public function get_blog_id_for_output() {
550 + // Returns the site's blog_id in the WP.com ecosystem
551 + function get_blog_id_for_output() {
881 552 return $this->token_details['blog_id'];
882 553 }
883 554
884 - /**
885 - * Returns the site's local blog_id.
886 - *
887 - * @param int $blog_id Blog ID.
888 - * @return int
889 - */
890 - public function get_blog_id( $blog_id ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
555 + // Returns the site's local blog_id
556 + function get_blog_id( $blog_id ) {
891 557 return $GLOBALS['blog_id'];
892 558 }
893 559
894 - /**
895 - * Switch to blog and validate user.
896 - *
897 - * @param int $blog_id Blog ID.
898 - * @param bool $verify_token_for_blog Whether to verify the token.
899 - * @return int Blog ID.
900 - */
901 - public function switch_to_blog_and_validate_user( $blog_id = 0, $verify_token_for_blog = true ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
560 + function switch_to_blog_and_validate_user( $blog_id = 0, $verify_token_for_blog = true ) {
902 561 if ( $this->is_restricted_blog( $blog_id ) ) {
903 562 return new WP_Error( 'unauthorized', 'User cannot access this restricted blog', 403 );
904 563 }
905 - /**
906 - * If this is a private site we check for 2 things:
907 - * 1. In case of user based authentication, we need to check if the logged-in user has the 'read' capability.
908 - * 2. In case of site based authentication, make sure the endpoint accepts it.
909 - */
910 - if ( ( new Status() )->is_private_site() &&
911 - ! current_user_can( 'read' ) &&
912 - ! $this->endpoint->accepts_site_based_authentication()
913 - ) {
564 +
565 + if ( -1 == get_option( 'blog_public' ) && !current_user_can( 'read' ) ) {
914 566 return new WP_Error( 'unauthorized', 'User cannot access this private blog.', 403 );
915 567 }
916 568
917 569 return $blog_id;
@@ -916,15 +568,10 @@
916 568
917 569 return $blog_id;
918 570 }
919 571
920 - /**
921 - * Returns true if the specified blog ID is a restricted blog
922 - *
923 - * @param int $blog_id Blog ID.
924 - * @return bool
925 - */
926 - public function is_restricted_blog( $blog_id ) {
572 + // Returns true if the specified blog ID is a restricted blog
573 + function is_restricted_blog( $blog_id ) {
927 574 /**
928 575 * Filters all REST API access and return a 403 unauthorized response for all Restricted blog IDs.
929 576 *
930 577 * @module json-api
@@ -933,73 +580,32 @@
933 580 *
934 581 * @param array $array Array of Blog IDs.
935 582 */
936 583 $restricted_blog_ids = apply_filters( 'wpcom_json_api_restricted_blog_ids', array() );
937 - return true === in_array( $blog_id, $restricted_blog_ids ); // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict -- I don't trust filters to return the right types.
584 + return true === in_array( $blog_id, $restricted_blog_ids );
938 585 }
939 586
940 - /**
941 - * Post like count.
942 - *
943 - * @param int $blog_id Blog ID.
944 - * @param int $post_id Post ID.
945 - * @return int
946 - */
947 - public function post_like_count( $blog_id, $post_id ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
587 + function post_like_count( $blog_id, $post_id ) {
948 588 return 0;
949 589 }
950 590
951 - /**
952 - * Is liked?
953 - *
954 - * @param int $blog_id Blog ID.
955 - * @param int $post_id Post ID.
956 - * @return bool
957 - */
958 - public function is_liked( $blog_id, $post_id ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
591 + function is_liked( $blog_id, $post_id ) {
959 592 return false;
960 593 }
961 594
962 - /**
963 - * Is reblogged?
964 - *
965 - * @param int $blog_id Blog ID.
966 - * @param int $post_id Post ID.
967 - * @return bool
968 - */
969 - public function is_reblogged( $blog_id, $post_id ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
595 + function is_reblogged( $blog_id, $post_id ) {
970 596 return false;
971 597 }
972 598
973 - /**
974 - * Is following?
975 - *
976 - * @param int $blog_id Blog ID.
977 - * @return bool
978 - */
979 - public function is_following( $blog_id ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
599 + function is_following( $blog_id ) {
980 600 return false;
981 601 }
982 602
983 - /**
984 - * Add global ID.
985 - *
986 - * @param int $blog_id Blog ID.
987 - * @param int $post_id Post ID.
988 - * @return string
989 - */
990 - public function add_global_ID( $blog_id, $post_id ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable, WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid
603 + function add_global_ID( $blog_id, $post_id ) {
991 604 return '';
992 605 }
993 606
994 - /**
995 - * Get avatar URL.
996 - *
997 - * @param string $email Email.
998 - * @param array $avatar_size Args for `get_avatar_url()`.
999 - * @return string|false
1000 - */
1001 - public function get_avatar_url( $email, $avatar_size = null ) {
607 + function get_avatar_url( $email, $avatar_size = null ) {
1002 608 if ( function_exists( 'wpcom_get_avatar_url' ) ) {
1003 609 return null === $avatar_size
1004 610 ? wpcom_get_avatar_url( $email )
1005 611 : wpcom_get_avatar_url( $email, $avatar_size );
@@ -1010,125 +616,19 @@
1010 616 }
1011 617 }
1012 618
1013 619 /**
1014 - * Counts the number of comments on a site, including certain comment types.
1015 - *
1016 - * @param int $post_id Post ID.
1017 - * @return array Array of counts, matching the output of https://developer.wordpress.org/reference/functions/get_comment_count/.
1018 - */
1019 - public function wp_count_comments( $post_id ) {
1020 - global $wpdb;
1021 - if ( 0 !== $post_id ) {
1022 - return wp_count_comments( $post_id );
1023 - }
1024 -
1025 - $counts = array(
1026 - 'total_comments' => 0,
1027 - 'all' => 0,
1028 - );
1029 -
1030 - /**
1031 - * Exclude certain comment types from comment counts in the REST API.
1032 - *
1033 - * @since 6.9.0
1034 - * @deprecated 11.1
1035 - * @module json-api
1036 - *
1037 - * @param array Array of comment types to exclude (default: 'order_note', 'webhook_delivery', 'review', 'action_log')
1038 - */
1039 - $exclude = apply_filters_deprecated( 'jetpack_api_exclude_comment_types_count', array( 'order_note', 'webhook_delivery', 'review', 'action_log' ), 'jetpack-11.1', 'jetpack_api_include_comment_types_count' ); // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
1040 -
1041 - /**
1042 - * Include certain comment types in comment counts in the REST API.
1043 - * Note: the default array of comment types includes an empty string,
1044 - * to support comments posted before WP 5.5, that used an empty string as comment type.
1045 - *
1046 - * @since 11.1
1047 - * @module json-api
1048 - *
1049 - * @param array Array of comment types to include (default: 'comment', 'pingback', 'trackback')
1050 - */
1051 - $include = apply_filters(
1052 - 'jetpack_api_include_comment_types_count',
1053 - array( 'comment', 'pingback', 'trackback', '' )
1054 - );
1055 -
1056 - if ( empty( $include ) ) {
1057 - return wp_count_comments( $post_id );
1058 - }
1059 -
1060 - array_walk( $include, 'esc_sql' );
1061 - $where = sprintf(
1062 - "WHERE comment_type IN ( '%s' )",
1063 - implode( "','", $include )
1064 - );
1065 -
1066 - // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- `$where` is built with escaping just above.
1067 - $count = $wpdb->get_results(
1068 - "SELECT comment_approved, COUNT(*) AS num_comments
1069 - FROM $wpdb->comments
1070 - {$where}
1071 - GROUP BY comment_approved
1072 - "
1073 - );
1074 - // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
1075 -
1076 - $approved = array(
1077 - '0' => 'moderated',
1078 - '1' => 'approved',
1079 - 'spam' => 'spam',
1080 - 'trash' => 'trash',
1081 - 'post-trashed' => 'post-trashed',
1082 - );
1083 -
1084 - // <https://developer.wordpress.org/reference/functions/get_comment_count/#source>
1085 - foreach ( $count as $row ) {
1086 - if ( ! in_array( $row->comment_approved, array( 'post-trashed', 'trash', 'spam' ), true ) ) {
1087 - $counts['all'] += $row->num_comments;
1088 - $counts['total_comments'] += $row->num_comments;
1089 - } elseif ( ! in_array( $row->comment_approved, array( 'post-trashed', 'trash' ), true ) ) {
1090 - $counts['total_comments'] += $row->num_comments;
1091 - }
1092 - if ( isset( $approved[ $row->comment_approved ] ) ) {
1093 - $counts[ $approved[ $row->comment_approved ] ] = $row->num_comments;
1094 - }
1095 - }
1096 -
1097 - foreach ( $approved as $key ) {
1098 - if ( empty( $counts[ $key ] ) ) {
1099 - $counts[ $key ] = 0;
1100 - }
1101 - }
1102 -
1103 - $counts = (object) $counts;
1104 -
1105 - return $counts;
1106 - }
1107 -
1108 - /**
1109 - * Traps `wp_die()` calls and outputs a JSON response instead.
620 + * traps `wp_die()` calls and outputs a JSON response instead.
1110 621 * The result is always output, never returned.
1111 622 *
1112 623 * @param string|null $error_code Call with string to start the trapping. Call with null to stop.
1113 624 * @param int $http_status HTTP status code, 400 by default.
1114 625 */
1115 - public function trap_wp_die( $error_code = null, $http_status = 400 ) {
1116 - // Determine the filter name; based on the conditionals inside the wp_die function.
1117 - if ( wp_is_json_request() ) {
1118 - $die_handler = 'wp_die_json_handler';
1119 - } elseif ( wp_is_jsonp_request() ) {
1120 - $die_handler = 'wp_die_jsonp_handler';
1121 - } elseif ( wp_is_xml_request() ) {
1122 - $die_handler = 'wp_die_xml_handler';
1123 - } else {
1124 - $die_handler = 'wp_die_handler';
1125 - }
1126 -
1127 - if ( $error_code === null ) {
626 + function trap_wp_die( $error_code = null, $http_status = 400 ) {
627 + if ( is_null( $error_code ) ) {
1128 628 $this->trapped_error = null;
1129 - // Stop trapping.
1130 - remove_filter( $die_handler, array( $this, 'wp_die_handler_callback' ) );
629 + // Stop trapping
630 + remove_filter( 'wp_die_handler', array( $this, 'wp_die_handler_callback' ) );
1131 631 return;
1132 632 }
1133 633
1134 634 // If API called via PHP, bail: don't do our custom wp_die(). Do the normal wp_die().
@@ -1135,10 +635,12 @@
1135 635 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
1136 636 if ( ! defined( 'REST_API_REQUEST' ) || ! REST_API_REQUEST ) {
1137 637 return;
1138 638 }
1139 - } elseif ( ! defined( 'XMLRPC_REQUEST' ) || ! XMLRPC_REQUEST ) {
1140 - return;
639 + } else {
640 + if ( ! defined( 'XMLRPC_REQUEST' ) || ! XMLRPC_REQUEST ) {
641 + return;
642 + }
1141 643 }
1142 644
1143 645 $this->trapped_error = array(
1144 646 'status' => $http_status,
@@ -1144,39 +646,24 @@
1144 646 'status' => $http_status,
1145 647 'code' => $error_code,
1146 648 'message' => '',
1147 649 );
1148 - // Start trapping.
1149 - add_filter( $die_handler, array( $this, 'wp_die_handler_callback' ) );
650 + // Start trapping
651 + add_filter( 'wp_die_handler', array( $this, 'wp_die_handler_callback' ) );
1150 652 }
1151 653
1152 - /**
1153 - * Filter function for `wp_die_handler` and similar filters.
1154 - *
1155 - * @return callable
1156 - */
1157 - public function wp_die_handler_callback() {
654 + function wp_die_handler_callback() {
1158 655 return array( $this, 'wp_die_handler' );
1159 656 }
1160 657
1161 - /**
1162 - * Handler for `wp_die` calls.
1163 - *
1164 - * @param string|WP_Error $message As for `wp_die()`.
1165 - * @param string|int $title As for `wp_die()`.
1166 - * @param string|array|int $args As for `wp_die()`.
1167 - */
1168 - public function wp_die_handler( $message, $title = '', $args = array() ) {
658 + function wp_die_handler( $message, $title = '', $args = array() ) {
1169 659 // Allow wp_die calls to override HTTP status code...
1170 - $args = wp_parse_args(
1171 - $args,
1172 - array(
1173 - 'response' => $this->trapped_error['status'],
1174 - )
1175 - );
660 + $args = wp_parse_args( $args, array(
661 + 'response' => $this->trapped_error['status'],
662 + ) );
1176 663
1177 - // ... unless it's 500
1178 - if ( 500 !== (int) $args['response'] ) {
664 + // ... unless it's 500 ( see http://wp.me/pMz3w-5VV )
665 + if ( (int) $args['response'] !== 500 ) {
1179 666 $this->trapped_error['status'] = $args['response'];
1180 667 }
1181 668
1182 669 if ( $title ) {
@@ -1185,12 +672,12 @@
1185 672
1186 673 $this->trapped_error['message'] = wp_kses( $message, array() );
1187 674
1188 675 switch ( $this->trapped_error['code'] ) {
1189 - case 'comment_failure':
676 + case 'comment_failure' :
1190 677 if ( did_action( 'comment_duplicate_trigger' ) ) {
1191 678 $this->trapped_error['code'] = 'comment_duplicate';
1192 - } elseif ( did_action( 'comment_flood_trigger' ) ) {
679 + } else if ( did_action( 'comment_flood_trigger' ) ) {
1193 680 $this->trapped_error['code'] = 'comment_flood';
1194 681 }
1195 682 break;
1196 683 }
@@ -1195,32 +682,22 @@
1195 682 break;
1196 683 }
1197 684
1198 685 // We still want to exit so that code execution stops where it should.
1199 - // Attach the JSON output to the WordPress shutdown handler.
686 + // Attach the JSON output to the WordPress shutdown handler
1200 687 add_action( 'shutdown', array( $this, 'output_trapped_error' ), 0 );
1201 688 exit;
1202 689 }
1203 690
1204 - /**
1205 - * Output the trapped error.
1206 - */
1207 - public function output_trapped_error() {
691 + function output_trapped_error() {
1208 692 $this->exit = false; // We're already exiting once. Don't do it twice.
1209 - $this->output(
1210 - $this->trapped_error['status'],
1211 - (object) array(
1212 - 'error' => $this->trapped_error['code'],
1213 - 'message' => $this->trapped_error['message'],
1214 - )
1215 - );
693 + $this->output( $this->trapped_error['status'], (object) array(
694 + 'error' => $this->trapped_error['code'],
695 + 'message' => $this->trapped_error['message'],
696 + ) );
1216 697 }
1217 698
1218 - /**
1219 - * Finish the request.
1220 - */
1221 - public function finish_request() {
1222 - if ( function_exists( 'fastcgi_finish_request' ) ) {
699 + function finish_request() {
700 + if ( function_exists( 'fastcgi_finish_request' ) )
1223 701 return fastcgi_finish_request();
1224 - }
1225 702 }
1226 703 }