12 * |
12 * |
13 * Contains data from the request, to be passed to the callback. |
13 * Contains data from the request, to be passed to the callback. |
14 * |
14 * |
15 * Note: This implements ArrayAccess, and acts as an array of parameters when |
15 * Note: This implements ArrayAccess, and acts as an array of parameters when |
16 * used in that manner. It does not use ArrayObject (as we cannot rely on SPL), |
16 * used in that manner. It does not use ArrayObject (as we cannot rely on SPL), |
17 * so be aware it may have non-array behaviour in some cases. |
17 * so be aware it may have non-array behavior in some cases. |
18 * |
18 * |
19 * Note: When using features provided by ArrayAccess, be aware that WordPress deliberately |
19 * Note: When using features provided by ArrayAccess, be aware that WordPress deliberately |
20 * does not distinguish between arguments of the same name for different request methods. |
20 * does not distinguish between arguments of the same name for different request methods. |
21 * For instance, in a request with `GET id=1` and `POST id=2`, `$request['id']` will equal |
21 * For instance, in a request with `GET id=1` and `POST id=2`, `$request['id']` will equal |
22 * 2 (`POST`) not 1 (`GET`). For more precision between request methods, use |
22 * 2 (`POST`) not 1 (`GET`). For more precision between request methods, use |
288 $this->set_header( $key, $value ); |
289 $this->set_header( $key, $value ); |
289 } |
290 } |
290 } |
291 } |
291 |
292 |
292 /** |
293 /** |
293 * Retrieves the content-type of the request. |
294 * Retrieves the Content-Type of the request. |
294 * |
295 * |
295 * @since 4.4.0 |
296 * @since 4.4.0 |
296 * |
297 * |
297 * @return array|null Map containing 'value' and 'parameters' keys |
298 * @return array|null Map containing 'value' and 'parameters' keys |
298 * or null when no valid content-type header was |
299 * or null when no valid Content-Type header was |
299 * available. |
300 * available. |
300 */ |
301 */ |
301 public function get_content_type() { |
302 public function get_content_type() { |
302 $value = $this->get_header( 'content-type' ); |
303 $value = $this->get_header( 'Content-Type' ); |
303 if ( empty( $value ) ) { |
304 if ( empty( $value ) ) { |
304 return null; |
305 return null; |
305 } |
306 } |
306 |
307 |
307 $parameters = ''; |
308 $parameters = ''; |
308 if ( strpos( $value, ';' ) ) { |
309 if ( strpos( $value, ';' ) ) { |
309 list( $value, $parameters ) = explode( ';', $value, 2 ); |
310 list( $value, $parameters ) = explode( ';', $value, 2 ); |
310 } |
311 } |
311 |
312 |
312 $value = strtolower( $value ); |
313 $value = strtolower( $value ); |
313 if ( false === strpos( $value, '/' ) ) { |
314 if ( ! str_contains( $value, '/' ) ) { |
314 return null; |
315 return null; |
315 } |
316 } |
316 |
317 |
317 // Parse type and subtype out. |
318 // Parse type and subtype out. |
318 list( $type, $subtype ) = explode( '/', $value, 2 ); |
319 list( $type, $subtype ) = explode( '/', $value, 2 ); |
322 |
323 |
323 return $data; |
324 return $data; |
324 } |
325 } |
325 |
326 |
326 /** |
327 /** |
327 * Checks if the request has specified a JSON content-type. |
328 * Checks if the request has specified a JSON Content-Type. |
328 * |
329 * |
329 * @since 5.6.0 |
330 * @since 5.6.0 |
330 * |
331 * |
331 * @return bool True if the content-type header is JSON. |
332 * @return bool True if the Content-Type header is JSON. |
332 */ |
333 */ |
333 public function is_json_content_type() { |
334 public function is_json_content_type() { |
334 $content_type = $this->get_content_type(); |
335 $content_type = $this->get_content_type(); |
335 |
336 |
336 return isset( $content_type['value'] ) && wp_is_json_media_type( $content_type['value'] ); |
337 return isset( $content_type['value'] ) && wp_is_json_media_type( $content_type['value'] ); |
470 $order = $this->get_parameter_order(); |
471 $order = $this->get_parameter_order(); |
471 $order = array_reverse( $order, true ); |
472 $order = array_reverse( $order, true ); |
472 |
473 |
473 $params = array(); |
474 $params = array(); |
474 foreach ( $order as $type ) { |
475 foreach ( $order as $type ) { |
475 // array_merge() / the "+" operator will mess up |
476 /* |
476 // numeric keys, so instead do a manual foreach. |
477 * array_merge() / the "+" operator will mess up |
|
478 * numeric keys, so instead do a manual foreach. |
|
479 */ |
477 foreach ( (array) $this->params[ $type ] as $key => $value ) { |
480 foreach ( (array) $this->params[ $type ] as $key => $value ) { |
478 $params[ $key ] = $value; |
481 $params[ $key ] = $value; |
479 } |
482 } |
480 } |
483 } |
481 |
484 |
716 } |
719 } |
717 |
720 |
718 $this->parsed_body = true; |
721 $this->parsed_body = true; |
719 |
722 |
720 /* |
723 /* |
721 * Check that we got URL-encoded. Treat a missing content-type as |
724 * Check that we got URL-encoded. Treat a missing Content-Type as |
722 * URL-encoded for maximum compatibility. |
725 * URL-encoded for maximum compatibility. |
723 */ |
726 */ |
724 $content_type = $this->get_content_type(); |
727 $content_type = $this->get_content_type(); |
725 |
728 |
726 if ( ! empty( $content_type ) && 'application/x-www-form-urlencoded' !== $content_type['value'] ) { |
729 if ( ! empty( $content_type ) && 'application/x-www-form-urlencoded' !== $content_type['value'] ) { |
1028 if ( ! empty( $bits['query'] ) ) { |
1031 if ( ! empty( $bits['query'] ) ) { |
1029 wp_parse_str( $bits['query'], $query_params ); |
1032 wp_parse_str( $bits['query'], $query_params ); |
1030 } |
1033 } |
1031 |
1034 |
1032 $api_root = rest_url(); |
1035 $api_root = rest_url(); |
1033 if ( get_option( 'permalink_structure' ) && 0 === strpos( $url, $api_root ) ) { |
1036 if ( get_option( 'permalink_structure' ) && str_starts_with( $url, $api_root ) ) { |
1034 // Pretty permalinks on, and URL is under the API root. |
1037 // Pretty permalinks on, and URL is under the API root. |
1035 $api_url_part = substr( $url, strlen( untrailingslashit( $api_root ) ) ); |
1038 $api_url_part = substr( $url, strlen( untrailingslashit( $api_root ) ) ); |
1036 $route = parse_url( $api_url_part, PHP_URL_PATH ); |
1039 $route = parse_url( $api_url_part, PHP_URL_PATH ); |
1037 } elseif ( ! empty( $query_params['rest_route'] ) ) { |
1040 } elseif ( ! empty( $query_params['rest_route'] ) ) { |
1038 // ?rest_route=... set directly. |
1041 // ?rest_route=... set directly. |