changeset 21 | 48c4eec2b7e6 |
parent 19 | 3d72ae0968f4 |
child 22 | 8c2e4d02f4ef |
20:7b1b88e27a20 | 21:48c4eec2b7e6 |
---|---|
21 * |
21 * |
22 * @since 4.4.0 |
22 * @since 4.4.0 |
23 * @since 5.1.0 Added a `_doing_it_wrong()` notice when not called on or after the `rest_api_init` hook. |
23 * @since 5.1.0 Added a `_doing_it_wrong()` notice when not called on or after the `rest_api_init` hook. |
24 * @since 5.5.0 Added a `_doing_it_wrong()` notice when the required `permission_callback` argument is not set. |
24 * @since 5.5.0 Added a `_doing_it_wrong()` notice when the required `permission_callback` argument is not set. |
25 * |
25 * |
26 * @param string $namespace The first URL segment after core prefix. Should be unique to your package/plugin. |
26 * @param string $route_namespace The first URL segment after core prefix. Should be unique to your package/plugin. |
27 * @param string $route The base URL for route you are adding. |
27 * @param string $route The base URL for route you are adding. |
28 * @param array $args Optional. Either an array of options for the endpoint, or an array of arrays for |
28 * @param array $args Optional. Either an array of options for the endpoint, or an array of arrays for |
29 * multiple methods. Default empty array. |
29 * multiple methods. Default empty array. |
30 * @param bool $override Optional. If the route already exists, should we override it? True overrides, |
30 * @param bool $override Optional. If the route already exists, should we override it? True overrides, |
31 * false merges (with newer overriding if duplicate keys exist). Default false. |
31 * false merges (with newer overriding if duplicate keys exist). Default false. |
32 * @return bool True on success, false on error. |
32 * @return bool True on success, false on error. |
33 */ |
33 */ |
34 function register_rest_route( $namespace, $route, $args = array(), $override = false ) { |
34 function register_rest_route( $route_namespace, $route, $args = array(), $override = false ) { |
35 if ( empty( $namespace ) ) { |
35 if ( empty( $route_namespace ) ) { |
36 /* |
36 /* |
37 * Non-namespaced routes are not allowed, with the exception of the main |
37 * Non-namespaced routes are not allowed, with the exception of the main |
38 * and namespace indexes. If you really need to register a |
38 * and namespace indexes. If you really need to register a |
39 * non-namespaced route, call `WP_REST_Server::register_route` directly. |
39 * non-namespaced route, call `WP_REST_Server::register_route` directly. |
40 */ |
40 */ |
43 } elseif ( empty( $route ) ) { |
43 } elseif ( empty( $route ) ) { |
44 _doing_it_wrong( 'register_rest_route', __( 'Route must be specified.' ), '4.4.0' ); |
44 _doing_it_wrong( 'register_rest_route', __( 'Route must be specified.' ), '4.4.0' ); |
45 return false; |
45 return false; |
46 } |
46 } |
47 |
47 |
48 $clean_namespace = trim( $namespace, '/' ); |
48 $clean_namespace = trim( $route_namespace, '/' ); |
49 |
49 |
50 if ( $clean_namespace !== $namespace ) { |
50 if ( $clean_namespace !== $route_namespace ) { |
51 _doing_it_wrong( __FUNCTION__, __( 'Namespace must not start or end with a slash.' ), '5.4.2' ); |
51 _doing_it_wrong( __FUNCTION__, __( 'Namespace must not start or end with a slash.' ), '5.4.2' ); |
52 } |
52 } |
53 |
53 |
54 if ( ! did_action( 'rest_api_init' ) ) { |
54 if ( ! did_action( 'rest_api_init' ) ) { |
55 _doing_it_wrong( |
55 _doing_it_wrong( |
101 '<code>__return_true</code>' |
101 '<code>__return_true</code>' |
102 ), |
102 ), |
103 '5.5.0' |
103 '5.5.0' |
104 ); |
104 ); |
105 } |
105 } |
106 |
|
107 foreach ( $arg_group['args'] as $arg ) { |
|
108 if ( ! is_array( $arg ) ) { |
|
109 _doing_it_wrong( |
|
110 __FUNCTION__, |
|
111 sprintf( |
|
112 /* translators: 1: $args, 2: The REST API route being registered. */ |
|
113 __( 'REST API %1$s should be an array of arrays. Non-array value detected for %2$s.' ), |
|
114 '<code>$args</code>', |
|
115 '<code>' . $clean_namespace . '/' . trim( $route, '/' ) . '</code>' |
|
116 ), |
|
117 '6.1.0' |
|
118 ); |
|
119 break; // Leave the foreach loop once a non-array argument was found. |
|
120 } |
|
121 } |
|
106 } |
122 } |
107 |
123 |
108 $full_route = '/' . $clean_namespace . '/' . trim( $route, '/' ); |
124 $full_route = '/' . $clean_namespace . '/' . trim( $route, '/' ); |
109 rest_get_server()->register_route( $clean_namespace, $full_route, $args, $override ); |
125 rest_get_server()->register_route( $clean_namespace, $full_route, $args, $override ); |
110 return true; |
126 return true; |
191 * to make testing and disabling these filters easier. |
207 * to make testing and disabling these filters easier. |
192 * |
208 * |
193 * @since 4.4.0 |
209 * @since 4.4.0 |
194 */ |
210 */ |
195 function rest_api_default_filters() { |
211 function rest_api_default_filters() { |
196 if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) { |
212 if ( wp_is_serving_rest_request() ) { |
197 // Deprecated reporting. |
213 // Deprecated reporting. |
198 add_action( 'deprecated_function_run', 'rest_handle_deprecated_function', 10, 3 ); |
214 add_action( 'deprecated_function_run', 'rest_handle_deprecated_function', 10, 3 ); |
199 add_filter( 'deprecated_function_trigger_error', '__return_false' ); |
215 add_filter( 'deprecated_function_trigger_error', '__return_false' ); |
200 add_action( 'deprecated_argument_run', 'rest_handle_deprecated_argument', 10, 3 ); |
216 add_action( 'deprecated_argument_run', 'rest_handle_deprecated_argument', 10, 3 ); |
201 add_filter( 'deprecated_argument_trigger_error', '__return_false' ); |
217 add_filter( 'deprecated_argument_trigger_error', '__return_false' ); |
223 |
239 |
224 if ( ! $controller ) { |
240 if ( ! $controller ) { |
225 continue; |
241 continue; |
226 } |
242 } |
227 |
243 |
228 $controller->register_routes(); |
244 if ( ! $post_type->late_route_registration ) { |
229 |
245 $controller->register_routes(); |
230 if ( post_type_supports( $post_type->name, 'revisions' ) ) { |
246 } |
231 $revisions_controller = new WP_REST_Revisions_Controller( $post_type->name ); |
247 |
248 $revisions_controller = $post_type->get_revisions_rest_controller(); |
|
249 if ( $revisions_controller ) { |
|
232 $revisions_controller->register_routes(); |
250 $revisions_controller->register_routes(); |
233 } |
251 } |
234 |
252 |
235 if ( 'attachment' !== $post_type->name ) { |
253 $autosaves_controller = $post_type->get_autosave_rest_controller(); |
236 $autosaves_controller = new WP_REST_Autosaves_Controller( $post_type->name ); |
254 if ( $autosaves_controller ) { |
237 $autosaves_controller->register_routes(); |
255 $autosaves_controller->register_routes(); |
238 } |
256 } |
257 |
|
258 if ( $post_type->late_route_registration ) { |
|
259 $controller->register_routes(); |
|
260 } |
|
239 } |
261 } |
240 |
262 |
241 // Post types. |
263 // Post types. |
242 $controller = new WP_REST_Post_Types_Controller; |
264 $controller = new WP_REST_Post_Types_Controller(); |
243 $controller->register_routes(); |
265 $controller->register_routes(); |
244 |
266 |
245 // Post statuses. |
267 // Post statuses. |
246 $controller = new WP_REST_Post_Statuses_Controller; |
268 $controller = new WP_REST_Post_Statuses_Controller(); |
247 $controller->register_routes(); |
269 $controller->register_routes(); |
248 |
270 |
249 // Taxonomies. |
271 // Taxonomies. |
250 $controller = new WP_REST_Taxonomies_Controller; |
272 $controller = new WP_REST_Taxonomies_Controller(); |
251 $controller->register_routes(); |
273 $controller->register_routes(); |
252 |
274 |
253 // Terms. |
275 // Terms. |
254 foreach ( get_taxonomies( array( 'show_in_rest' => true ), 'object' ) as $taxonomy ) { |
276 foreach ( get_taxonomies( array( 'show_in_rest' => true ), 'object' ) as $taxonomy ) { |
255 $controller = $taxonomy->get_rest_controller(); |
277 $controller = $taxonomy->get_rest_controller(); |
260 |
282 |
261 $controller->register_routes(); |
283 $controller->register_routes(); |
262 } |
284 } |
263 |
285 |
264 // Users. |
286 // Users. |
265 $controller = new WP_REST_Users_Controller; |
287 $controller = new WP_REST_Users_Controller(); |
266 $controller->register_routes(); |
288 $controller->register_routes(); |
267 |
289 |
268 // Application Passwords |
290 // Application Passwords |
269 $controller = new WP_REST_Application_Passwords_Controller(); |
291 $controller = new WP_REST_Application_Passwords_Controller(); |
270 $controller->register_routes(); |
292 $controller->register_routes(); |
271 |
293 |
272 // Comments. |
294 // Comments. |
273 $controller = new WP_REST_Comments_Controller; |
295 $controller = new WP_REST_Comments_Controller(); |
274 $controller->register_routes(); |
296 $controller->register_routes(); |
275 |
297 |
276 $search_handlers = array( |
298 $search_handlers = array( |
277 new WP_REST_Post_Search_Handler(), |
299 new WP_REST_Post_Search_Handler(), |
278 new WP_REST_Term_Search_Handler(), |
300 new WP_REST_Term_Search_Handler(), |
299 |
321 |
300 // Block Types. |
322 // Block Types. |
301 $controller = new WP_REST_Block_Types_Controller(); |
323 $controller = new WP_REST_Block_Types_Controller(); |
302 $controller->register_routes(); |
324 $controller->register_routes(); |
303 |
325 |
304 // Global Styles. |
326 // Settings. |
305 $controller = new WP_REST_Global_Styles_Controller; |
327 $controller = new WP_REST_Settings_Controller(); |
306 $controller->register_routes(); |
328 $controller->register_routes(); |
307 |
329 |
308 // Settings. |
|
309 $controller = new WP_REST_Settings_Controller; |
|
310 $controller->register_routes(); |
|
311 |
|
312 // Themes. |
330 // Themes. |
313 $controller = new WP_REST_Themes_Controller; |
331 $controller = new WP_REST_Themes_Controller(); |
314 $controller->register_routes(); |
332 $controller->register_routes(); |
315 |
333 |
316 // Plugins. |
334 // Plugins. |
317 $controller = new WP_REST_Plugins_Controller(); |
335 $controller = new WP_REST_Plugins_Controller(); |
318 $controller->register_routes(); |
336 $controller->register_routes(); |
359 $controller->register_routes(); |
377 $controller->register_routes(); |
360 |
378 |
361 // Site Editor Export. |
379 // Site Editor Export. |
362 $controller = new WP_REST_Edit_Site_Export_Controller(); |
380 $controller = new WP_REST_Edit_Site_Export_Controller(); |
363 $controller->register_routes(); |
381 $controller->register_routes(); |
382 |
|
383 // Navigation Fallback. |
|
384 $controller = new WP_REST_Navigation_Fallback_Controller(); |
|
385 $controller->register_routes(); |
|
386 |
|
387 // Font Collections. |
|
388 $font_collections_controller = new WP_REST_Font_Collections_Controller(); |
|
389 $font_collections_controller->register_routes(); |
|
364 } |
390 } |
365 |
391 |
366 /** |
392 /** |
367 * Loads the REST API. |
393 * Loads the REST API. |
368 * |
394 * |
447 } |
473 } |
448 |
474 |
449 $url .= $path; |
475 $url .= $path; |
450 } else { |
476 } else { |
451 $url = trailingslashit( get_home_url( $blog_id, '', $scheme ) ); |
477 $url = trailingslashit( get_home_url( $blog_id, '', $scheme ) ); |
452 // nginx only allows HTTP/1.0 methods when redirecting from / to /index.php. |
478 /* |
453 // To work around this, we manually add index.php to the URL, avoiding the redirect. |
479 * nginx only allows HTTP/1.0 methods when redirecting from / to /index.php. |
454 if ( 'index.php' !== substr( $url, 9 ) ) { |
480 * To work around this, we manually add index.php to the URL, avoiding the redirect. |
481 */ |
|
482 if ( ! str_ends_with( $url, 'index.php' ) ) { |
|
455 $url .= 'index.php'; |
483 $url .= 'index.php'; |
456 } |
484 } |
457 |
485 |
458 $url = add_query_arg( 'rest_route', $path, $url ); |
486 $url = add_query_arg( 'rest_route', $path, $url ); |
459 } |
487 } |
544 * @since 4.4.0 |
572 * @since 4.4.0 |
545 * |
573 * |
546 * @param string $class_name The name of the server class. Default 'WP_REST_Server'. |
574 * @param string $class_name The name of the server class. Default 'WP_REST_Server'. |
547 */ |
575 */ |
548 $wp_rest_server_class = apply_filters( 'wp_rest_server_class', 'WP_REST_Server' ); |
576 $wp_rest_server_class = apply_filters( 'wp_rest_server_class', 'WP_REST_Server' ); |
549 $wp_rest_server = new $wp_rest_server_class; |
577 $wp_rest_server = new $wp_rest_server_class(); |
550 |
578 |
551 /** |
579 /** |
552 * Fires when preparing to serve a REST API request. |
580 * Fires when preparing to serve a REST API request. |
553 * |
581 * |
554 * Endpoint objects should be created and register their hooks on this action rather |
582 * Endpoint objects should be created and register their hooks on this action rather |
606 |
634 |
607 if ( $response instanceof WP_REST_Response ) { |
635 if ( $response instanceof WP_REST_Response ) { |
608 return $response; |
636 return $response; |
609 } |
637 } |
610 |
638 |
611 // While WP_HTTP_Response is the base class of WP_REST_Response, it doesn't provide |
639 /* |
612 // all the required methods used in WP_REST_Server::dispatch(). |
640 * While WP_HTTP_Response is the base class of WP_REST_Response, it doesn't provide |
641 * all the required methods used in WP_REST_Server::dispatch(). |
|
642 */ |
|
613 if ( $response instanceof WP_HTTP_Response ) { |
643 if ( $response instanceof WP_HTTP_Response ) { |
614 return new WP_REST_Response( |
644 return new WP_REST_Response( |
615 $response->get_data(), |
645 $response->get_data(), |
616 $response->get_status(), |
646 $response->get_status(), |
617 $response->get_headers() |
647 $response->get_headers() |
624 /** |
654 /** |
625 * Handles _deprecated_function() errors. |
655 * Handles _deprecated_function() errors. |
626 * |
656 * |
627 * @since 4.4.0 |
657 * @since 4.4.0 |
628 * |
658 * |
629 * @param string $function The function that was called. |
659 * @param string $function_name The function that was called. |
630 * @param string $replacement The function that should have been called. |
660 * @param string $replacement The function that should have been called. |
631 * @param string $version Version. |
661 * @param string $version Version. |
632 */ |
662 */ |
633 function rest_handle_deprecated_function( $function, $replacement, $version ) { |
663 function rest_handle_deprecated_function( $function_name, $replacement, $version ) { |
634 if ( ! WP_DEBUG || headers_sent() ) { |
664 if ( ! WP_DEBUG || headers_sent() ) { |
635 return; |
665 return; |
636 } |
666 } |
637 if ( ! empty( $replacement ) ) { |
667 if ( ! empty( $replacement ) ) { |
638 /* translators: 1: Function name, 2: WordPress version number, 3: New function name. */ |
668 /* translators: 1: Function name, 2: WordPress version number, 3: New function name. */ |
639 $string = sprintf( __( '%1$s (since %2$s; use %3$s instead)' ), $function, $version, $replacement ); |
669 $string = sprintf( __( '%1$s (since %2$s; use %3$s instead)' ), $function_name, $version, $replacement ); |
640 } else { |
670 } else { |
641 /* translators: 1: Function name, 2: WordPress version number. */ |
671 /* translators: 1: Function name, 2: WordPress version number. */ |
642 $string = sprintf( __( '%1$s (since %2$s; no alternative available)' ), $function, $version ); |
672 $string = sprintf( __( '%1$s (since %2$s; no alternative available)' ), $function_name, $version ); |
643 } |
673 } |
644 |
674 |
645 header( sprintf( 'X-WP-DeprecatedFunction: %s', $string ) ); |
675 header( sprintf( 'X-WP-DeprecatedFunction: %s', $string ) ); |
646 } |
676 } |
647 |
677 |
648 /** |
678 /** |
649 * Handles _deprecated_argument() errors. |
679 * Handles _deprecated_argument() errors. |
650 * |
680 * |
651 * @since 4.4.0 |
681 * @since 4.4.0 |
652 * |
682 * |
653 * @param string $function The function that was called. |
683 * @param string $function_name The function that was called. |
654 * @param string $message A message regarding the change. |
684 * @param string $message A message regarding the change. |
655 * @param string $version Version. |
685 * @param string $version Version. |
656 */ |
686 */ |
657 function rest_handle_deprecated_argument( $function, $message, $version ) { |
687 function rest_handle_deprecated_argument( $function_name, $message, $version ) { |
658 if ( ! WP_DEBUG || headers_sent() ) { |
688 if ( ! WP_DEBUG || headers_sent() ) { |
659 return; |
689 return; |
660 } |
690 } |
661 if ( $message ) { |
691 if ( $message ) { |
662 /* translators: 1: Function name, 2: WordPress version number, 3: Error message. */ |
692 /* translators: 1: Function name, 2: WordPress version number, 3: Error message. */ |
663 $string = sprintf( __( '%1$s (since %2$s; %3$s)' ), $function, $version, $message ); |
693 $string = sprintf( __( '%1$s (since %2$s; %3$s)' ), $function_name, $version, $message ); |
664 } else { |
694 } else { |
665 /* translators: 1: Function name, 2: WordPress version number. */ |
695 /* translators: 1: Function name, 2: WordPress version number. */ |
666 $string = sprintf( __( '%1$s (since %2$s; no alternative available)' ), $function, $version ); |
696 $string = sprintf( __( '%1$s (since %2$s; no alternative available)' ), $function_name, $version ); |
667 } |
697 } |
668 |
698 |
669 header( sprintf( 'X-WP-DeprecatedParam: %s', $string ) ); |
699 header( sprintf( 'X-WP-DeprecatedParam: %s', $string ) ); |
670 } |
700 } |
671 |
701 |
672 /** |
702 /** |
673 * Handles _doing_it_wrong errors. |
703 * Handles _doing_it_wrong errors. |
674 * |
704 * |
675 * @since 5.5.0 |
705 * @since 5.5.0 |
676 * |
706 * |
677 * @param string $function The function that was called. |
707 * @param string $function_name The function that was called. |
678 * @param string $message A message explaining what has been done incorrectly. |
708 * @param string $message A message explaining what has been done incorrectly. |
679 * @param string|null $version The version of WordPress where the message was added. |
709 * @param string|null $version The version of WordPress where the message was added. |
680 */ |
710 */ |
681 function rest_handle_doing_it_wrong( $function, $message, $version ) { |
711 function rest_handle_doing_it_wrong( $function_name, $message, $version ) { |
682 if ( ! WP_DEBUG || headers_sent() ) { |
712 if ( ! WP_DEBUG || headers_sent() ) { |
683 return; |
713 return; |
684 } |
714 } |
685 |
715 |
686 if ( $version ) { |
716 if ( $version ) { |
687 /* translators: Developer debugging message. 1: PHP function name, 2: WordPress version number, 3: Explanatory message. */ |
717 /* translators: Developer debugging message. 1: PHP function name, 2: WordPress version number, 3: Explanatory message. */ |
688 $string = __( '%1$s (since %2$s; %3$s)' ); |
718 $string = __( '%1$s (since %2$s; %3$s)' ); |
689 $string = sprintf( $string, $function, $version, $message ); |
719 $string = sprintf( $string, $function_name, $version, $message ); |
690 } else { |
720 } else { |
691 /* translators: Developer debugging message. 1: PHP function name, 2: Explanatory message. */ |
721 /* translators: Developer debugging message. 1: PHP function name, 2: Explanatory message. */ |
692 $string = __( '%1$s (%2$s)' ); |
722 $string = __( '%1$s (%2$s)' ); |
693 $string = sprintf( $string, $function, $message ); |
723 $string = sprintf( $string, $function_name, $message ); |
694 } |
724 } |
695 |
725 |
696 header( sprintf( 'X-WP-DoingItWrong: %s', $string ) ); |
726 header( sprintf( 'X-WP-DoingItWrong: %s', $string ) ); |
697 } |
727 } |
698 |
728 |
708 $origin = get_http_origin(); |
738 $origin = get_http_origin(); |
709 |
739 |
710 if ( $origin ) { |
740 if ( $origin ) { |
711 // Requests from file:// and data: URLs send "Origin: null". |
741 // Requests from file:// and data: URLs send "Origin: null". |
712 if ( 'null' !== $origin ) { |
742 if ( 'null' !== $origin ) { |
713 $origin = esc_url_raw( $origin ); |
743 $origin = sanitize_url( $origin ); |
714 } |
744 } |
715 header( 'Access-Control-Allow-Origin: ' . $origin ); |
745 header( 'Access-Control-Allow-Origin: ' . $origin ); |
716 header( 'Access-Control-Allow-Methods: OPTIONS, GET, POST, PUT, PATCH, DELETE' ); |
746 header( 'Access-Control-Allow-Methods: OPTIONS, GET, POST, PUT, PATCH, DELETE' ); |
717 header( 'Access-Control-Allow-Credentials: true' ); |
747 header( 'Access-Control-Allow-Credentials: true' ); |
718 header( 'Vary: Origin', false ); |
748 header( 'Vary: Origin', false ); |
840 } |
870 } |
841 return $array1; |
871 return $array1; |
842 } |
872 } |
843 |
873 |
844 /** |
874 /** |
845 * Filters the REST API response to include only a white-listed set of response object fields. |
875 * Filters the REST API response to include only an allow-listed set of response object fields. |
846 * |
876 * |
847 * @since 4.8.0 |
877 * @since 4.8.0 |
848 * |
878 * |
849 * @param WP_REST_Response $response Current response being served. |
879 * @param WP_REST_Response $response Current response being served. |
850 * @param WP_REST_Server $server ResponseHandler instance (usually WP_REST_Server). |
880 * @param WP_REST_Server $server ResponseHandler instance (usually WP_REST_Server). |
919 if ( in_array( $field, $fields, true ) ) { |
949 if ( in_array( $field, $fields, true ) ) { |
920 return true; |
950 return true; |
921 } |
951 } |
922 |
952 |
923 foreach ( $fields as $accepted_field ) { |
953 foreach ( $fields as $accepted_field ) { |
924 // Check to see if $field is the parent of any item in $fields. |
954 /* |
925 // A field "parent" should be accepted if "parent.child" is accepted. |
955 * Check to see if $field is the parent of any item in $fields. |
926 if ( strpos( $accepted_field, "$field." ) === 0 ) { |
956 * A field "parent" should be accepted if "parent.child" is accepted. |
957 */ |
|
958 if ( str_starts_with( $accepted_field, "$field." ) ) { |
|
927 return true; |
959 return true; |
928 } |
960 } |
929 // Conversely, if "parent" is accepted, all "parent.child" fields |
961 /* |
930 // should also be accepted. |
962 * Conversely, if "parent" is accepted, all "parent.child" fields |
931 if ( strpos( $field, "$accepted_field." ) === 0 ) { |
963 * should also be accepted. |
964 */ |
|
965 if ( str_starts_with( $field, "$accepted_field." ) ) { |
|
932 return true; |
966 return true; |
933 } |
967 } |
934 } |
968 } |
935 |
969 |
936 return false; |
970 return false; |
971 printf( '<link rel="https://api.w.org/" href="%s" />', esc_url( $api_root ) ); |
1005 printf( '<link rel="https://api.w.org/" href="%s" />', esc_url( $api_root ) ); |
972 |
1006 |
973 $resource = rest_get_queried_resource_route(); |
1007 $resource = rest_get_queried_resource_route(); |
974 |
1008 |
975 if ( $resource ) { |
1009 if ( $resource ) { |
976 printf( '<link rel="alternate" type="application/json" href="%s" />', esc_url( rest_url( $resource ) ) ); |
1010 printf( |
1011 '<link rel="alternate" title="%1$s" type="application/json" href="%2$s" />', |
|
1012 _x( 'JSON', 'REST API resource link name' ), |
|
1013 esc_url( rest_url( $resource ) ) |
|
1014 ); |
|
977 } |
1015 } |
978 } |
1016 } |
979 |
1017 |
980 /** |
1018 /** |
981 * Sends a Link header for the REST API. |
1019 * Sends a Link header for the REST API. |
991 |
1029 |
992 if ( empty( $api_root ) ) { |
1030 if ( empty( $api_root ) ) { |
993 return; |
1031 return; |
994 } |
1032 } |
995 |
1033 |
996 header( sprintf( 'Link: <%s>; rel="https://api.w.org/"', esc_url_raw( $api_root ) ), false ); |
1034 header( sprintf( 'Link: <%s>; rel="https://api.w.org/"', sanitize_url( $api_root ) ), false ); |
997 |
1035 |
998 $resource = rest_get_queried_resource_route(); |
1036 $resource = rest_get_queried_resource_route(); |
999 |
1037 |
1000 if ( $resource ) { |
1038 if ( $resource ) { |
1001 header( sprintf( 'Link: <%s>; rel="alternate"; type="application/json"', esc_url_raw( rest_url( $resource ) ) ), false ); |
1039 header( |
1040 sprintf( |
|
1041 'Link: <%1$s>; rel="alternate"; title="%2$s"; type="application/json"', |
|
1042 sanitize_url( rest_url( $resource ) ), |
|
1043 _x( 'JSON', 'REST API resource link name' ) |
|
1044 ), |
|
1045 false |
|
1046 ); |
|
1002 } |
1047 } |
1003 } |
1048 } |
1004 |
1049 |
1005 /** |
1050 /** |
1006 * Checks for errors when using cookie-based authentication. |
1051 * Checks for errors when using cookie-based authentication. |
1050 |
1095 |
1051 // Check the nonce. |
1096 // Check the nonce. |
1052 $result = wp_verify_nonce( $nonce, 'wp_rest' ); |
1097 $result = wp_verify_nonce( $nonce, 'wp_rest' ); |
1053 |
1098 |
1054 if ( ! $result ) { |
1099 if ( ! $result ) { |
1100 add_filter( 'rest_send_nocache_headers', '__return_true', 20 ); |
|
1055 return new WP_Error( 'rest_cookie_invalid_nonce', __( 'Cookie check failed' ), array( 'status' => 403 ) ); |
1101 return new WP_Error( 'rest_cookie_invalid_nonce', __( 'Cookie check failed' ), array( 'status' => 403 ) ); |
1056 } |
1102 } |
1057 |
1103 |
1058 // Send a refreshed nonce in header. |
1104 // Send a refreshed nonce in header. |
1059 rest_get_server()->send_header( 'X-WP-Nonce', wp_create_nonce( 'wp_rest' ) ); |
1105 rest_get_server()->send_header( 'X-WP-Nonce', wp_create_nonce( 'wp_rest' ) ); |
1181 |
1227 |
1182 return $response; |
1228 return $response; |
1183 } |
1229 } |
1184 |
1230 |
1185 /** |
1231 /** |
1186 * Retrieves the avatar urls in various sizes. |
1232 * Retrieves the avatar URLs in various sizes. |
1187 * |
1233 * |
1188 * @since 4.7.0 |
1234 * @since 4.7.0 |
1189 * |
1235 * |
1190 * @see get_avatar_url() |
1236 * @see get_avatar_url() |
1191 * |
1237 * |
1192 * @param mixed $id_or_email The Gravatar to retrieve a URL for. Accepts a user_id, gravatar md5 hash, |
1238 * @param mixed $id_or_email The avatar to retrieve a URL for. Accepts a user ID, Gravatar MD5 hash, |
1193 * user email, WP_User object, WP_Post object, or WP_Comment object. |
1239 * user email, WP_User object, WP_Post object, or WP_Comment object. |
1194 * @return array Avatar URLs keyed by size. Each value can be a URL string or boolean false. |
1240 * @return (string|false)[] Avatar URLs keyed by size. Each value can be a URL string or boolean false. |
1195 */ |
1241 */ |
1196 function rest_get_avatar_urls( $id_or_email ) { |
1242 function rest_get_avatar_urls( $id_or_email ) { |
1197 $avatar_sizes = rest_get_avatar_sizes(); |
1243 $avatar_sizes = rest_get_avatar_sizes(); |
1198 |
1244 |
1199 $urls = array(); |
1245 $urls = array(); |
1232 * @since 4.4.0 |
1278 * @since 4.4.0 |
1233 * |
1279 * |
1234 * @param string $date RFC3339 timestamp. |
1280 * @param string $date RFC3339 timestamp. |
1235 * @param bool $force_utc Optional. Whether to force UTC timezone instead of using |
1281 * @param bool $force_utc Optional. Whether to force UTC timezone instead of using |
1236 * the timestamp's timezone. Default false. |
1282 * the timestamp's timezone. Default false. |
1237 * @return int Unix timestamp. |
1283 * @return int|false Unix timestamp on success, false on failure. |
1238 */ |
1284 */ |
1239 function rest_parse_date( $date, $force_utc = false ) { |
1285 function rest_parse_date( $date, $force_utc = false ) { |
1240 if ( $force_utc ) { |
1286 if ( $force_utc ) { |
1241 $date = preg_replace( '/[+-]\d+:?\d+$/', '+00:00', $date ); |
1287 $date = preg_replace( '/[+-]\d+:?\d+$/', '+00:00', $date ); |
1242 } |
1288 } |
1254 * Parses a 3 or 6 digit hex color (with #). |
1300 * Parses a 3 or 6 digit hex color (with #). |
1255 * |
1301 * |
1256 * @since 5.4.0 |
1302 * @since 5.4.0 |
1257 * |
1303 * |
1258 * @param string $color 3 or 6 digit hex color (with #). |
1304 * @param string $color 3 or 6 digit hex color (with #). |
1259 * @return string|false |
1305 * @return string|false Color value on success, false on failure. |
1260 */ |
1306 */ |
1261 function rest_parse_hex_color( $color ) { |
1307 function rest_parse_hex_color( $color ) { |
1262 $regex = '|^#([A-Fa-f0-9]{3}){1,2}$|'; |
1308 $regex = '|^#([A-Fa-f0-9]{3}){1,2}$|'; |
1263 if ( ! preg_match( $regex, $color, $matches ) ) { |
1309 if ( ! preg_match( $regex, $color, $matches ) ) { |
1264 return false; |
1310 return false; |
1274 * |
1320 * |
1275 * @see rest_parse_date() |
1321 * @see rest_parse_date() |
1276 * |
1322 * |
1277 * @param string $date RFC3339 timestamp. |
1323 * @param string $date RFC3339 timestamp. |
1278 * @param bool $is_utc Whether the provided date should be interpreted as UTC. Default false. |
1324 * @param bool $is_utc Whether the provided date should be interpreted as UTC. Default false. |
1279 * @return array|null Local and UTC datetime strings, in MySQL datetime format (Y-m-d H:i:s), |
1325 * @return array|null { |
1280 * null on failure. |
1326 * Local and UTC datetime strings, in MySQL datetime format (Y-m-d H:i:s), |
1327 * null on failure. |
|
1328 * |
|
1329 * @type string $0 Local datetime string. |
|
1330 * @type string $1 UTC datetime string. |
|
1331 * } |
|
1281 */ |
1332 */ |
1282 function rest_get_date_with_gmt( $date, $is_utc = false ) { |
1333 function rest_get_date_with_gmt( $date, $is_utc = false ) { |
1283 /* |
1334 /* |
1284 * Whether or not the original date actually has a timezone string |
1335 * Whether or not the original date actually has a timezone string |
1285 * changes the way we need to do timezone conversion. |
1336 * changes the way we need to do timezone conversion. |
1396 * @return string|false The valid IP address, otherwise false. |
1447 * @return string|false The valid IP address, otherwise false. |
1397 */ |
1448 */ |
1398 function rest_is_ip_address( $ip ) { |
1449 function rest_is_ip_address( $ip ) { |
1399 $ipv4_pattern = '/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/'; |
1450 $ipv4_pattern = '/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/'; |
1400 |
1451 |
1401 if ( ! preg_match( $ipv4_pattern, $ip ) && ! Requests_IPv6::check_ipv6( $ip ) ) { |
1452 if ( ! preg_match( $ipv4_pattern, $ip ) && ! WpOrg\Requests\Ipv6::check_ipv6( $ip ) ) { |
1402 return false; |
1453 return false; |
1403 } |
1454 } |
1404 |
1455 |
1405 return $ip; |
1456 return $ip; |
1406 } |
1457 } |
1531 |
1582 |
1532 return is_array( $maybe_object ); |
1583 return is_array( $maybe_object ); |
1533 } |
1584 } |
1534 |
1585 |
1535 /** |
1586 /** |
1536 * Converts an object-like value to an object. |
1587 * Converts an object-like value to an array. |
1537 * |
1588 * |
1538 * @since 5.5.0 |
1589 * @since 5.5.0 |
1539 * |
1590 * |
1540 * @param mixed $maybe_object The value being evaluated. |
1591 * @param mixed $maybe_object The value being evaluated. |
1541 * @return array Returns the object extracted from the value. |
1592 * @return array Returns the object extracted from the value as an associative array. |
1542 */ |
1593 */ |
1543 function rest_sanitize_object( $maybe_object ) { |
1594 function rest_sanitize_object( $maybe_object ) { |
1544 if ( '' === $maybe_object ) { |
1595 if ( '' === $maybe_object ) { |
1545 return array(); |
1596 return array(); |
1546 } |
1597 } |
1563 /** |
1614 /** |
1564 * Gets the best type for a value. |
1615 * Gets the best type for a value. |
1565 * |
1616 * |
1566 * @since 5.5.0 |
1617 * @since 5.5.0 |
1567 * |
1618 * |
1568 * @param mixed $value The value to check. |
1619 * @param mixed $value The value to check. |
1569 * @param array $types The list of possible types. |
1620 * @param string[] $types The list of possible types. |
1570 * @return string The best matching type, an empty string if no types match. |
1621 * @return string The best matching type, an empty string if no types match. |
1571 */ |
1622 */ |
1572 function rest_get_best_type_for_value( $value, $types ) { |
1623 function rest_get_best_type_for_value( $value, $types ) { |
1573 static $checks = array( |
1624 static $checks = array( |
1574 'array' => 'rest_is_array', |
1625 'array' => 'rest_is_array', |
1578 'boolean' => 'rest_is_boolean', |
1629 'boolean' => 'rest_is_boolean', |
1579 'string' => 'is_string', |
1630 'string' => 'is_string', |
1580 'null' => 'is_null', |
1631 'null' => 'is_null', |
1581 ); |
1632 ); |
1582 |
1633 |
1583 // Both arrays and objects allow empty strings to be converted to their types. |
1634 /* |
1584 // But the best answer for this type is a string. |
1635 * Both arrays and objects allow empty strings to be converted to their types. |
1636 * But the best answer for this type is a string. |
|
1637 */ |
|
1585 if ( '' === $value && in_array( 'string', $types, true ) ) { |
1638 if ( '' === $value && in_array( 'string', $types, true ) ) { |
1586 return 'string'; |
1639 return 'string'; |
1587 } |
1640 } |
1588 |
1641 |
1589 foreach ( $types as $type ) { |
1642 foreach ( $types as $type ) { |
1638 /** |
1691 /** |
1639 * Checks if an array is made up of unique items. |
1692 * Checks if an array is made up of unique items. |
1640 * |
1693 * |
1641 * @since 5.5.0 |
1694 * @since 5.5.0 |
1642 * |
1695 * |
1643 * @param array $array The array to check. |
1696 * @param array $input_array The array to check. |
1644 * @return bool True if the array contains unique items, false otherwise. |
1697 * @return bool True if the array contains unique items, false otherwise. |
1645 */ |
1698 */ |
1646 function rest_validate_array_contains_unique_items( $array ) { |
1699 function rest_validate_array_contains_unique_items( $input_array ) { |
1647 $seen = array(); |
1700 $seen = array(); |
1648 |
1701 |
1649 foreach ( $array as $item ) { |
1702 foreach ( $input_array as $item ) { |
1650 $stabilized = rest_stabilize_value( $item ); |
1703 $stabilized = rest_stabilize_value( $item ); |
1651 $key = serialize( $stabilized ); |
1704 $key = serialize( $stabilized ); |
1652 |
1705 |
1653 if ( ! isset( $seen[ $key ] ) ) { |
1706 if ( ! isset( $seen[ $key ] ) ) { |
1654 $seen[ $key ] = true; |
1707 $seen[ $key ] = true; |
2160 if ( is_wp_error( $enum_contains_value ) ) { |
2213 if ( is_wp_error( $enum_contains_value ) ) { |
2161 return $enum_contains_value; |
2214 return $enum_contains_value; |
2162 } |
2215 } |
2163 } |
2216 } |
2164 |
2217 |
2165 // The "format" keyword should only be applied to strings. However, for backward compatibility, |
2218 /* |
2166 // we allow the "format" keyword if the type keyword was not specified, or was set to an invalid value. |
2219 * The "format" keyword should only be applied to strings. However, for backward compatibility, |
2220 * we allow the "format" keyword if the type keyword was not specified, or was set to an invalid value. |
|
2221 */ |
|
2167 if ( isset( $args['format'] ) |
2222 if ( isset( $args['format'] ) |
2168 && ( ! isset( $args['type'] ) || 'string' === $args['type'] || ! in_array( $args['type'], $allowed_types, true ) ) |
2223 && ( ! isset( $args['type'] ) || 'string' === $args['type'] || ! in_array( $args['type'], $allowed_types, true ) ) |
2169 ) { |
2224 ) { |
2170 switch ( $args['format'] ) { |
2225 switch ( $args['format'] ) { |
2171 case 'hex-color': |
2226 case 'hex-color': |
2793 case 'email': |
2848 case 'email': |
2794 // sanitize_email() validates, which would be unexpected. |
2849 // sanitize_email() validates, which would be unexpected. |
2795 return sanitize_text_field( $value ); |
2850 return sanitize_text_field( $value ); |
2796 |
2851 |
2797 case 'uri': |
2852 case 'uri': |
2798 return esc_url_raw( $value ); |
2853 return sanitize_url( $value ); |
2799 |
2854 |
2800 case 'ip': |
2855 case 'ip': |
2801 return sanitize_text_field( $value ); |
2856 return sanitize_text_field( $value ); |
2802 |
2857 |
2803 case 'uuid': |
2858 case 'uuid': |
2827 * @param array $memo Reduce accumulator. |
2882 * @param array $memo Reduce accumulator. |
2828 * @param string $path REST API path to preload. |
2883 * @param string $path REST API path to preload. |
2829 * @return array Modified reduce accumulator. |
2884 * @return array Modified reduce accumulator. |
2830 */ |
2885 */ |
2831 function rest_preload_api_request( $memo, $path ) { |
2886 function rest_preload_api_request( $memo, $path ) { |
2832 // array_reduce() doesn't support passing an array in PHP 5.2, |
2887 /* |
2833 // so we need to make sure we start with one. |
2888 * array_reduce() doesn't support passing an array in PHP 5.2, |
2889 * so we need to make sure we start with one. |
|
2890 */ |
|
2834 if ( ! is_array( $memo ) ) { |
2891 if ( ! is_array( $memo ) ) { |
2835 $memo = array(); |
2892 $memo = array(); |
2836 } |
2893 } |
2837 |
2894 |
2838 if ( empty( $path ) ) { |
2895 if ( empty( $path ) ) { |
2868 $response = rest_do_request( $request ); |
2925 $response = rest_do_request( $request ); |
2869 if ( 200 === $response->status ) { |
2926 if ( 200 === $response->status ) { |
2870 $server = rest_get_server(); |
2927 $server = rest_get_server(); |
2871 /** This filter is documented in wp-includes/rest-api/class-wp-rest-server.php */ |
2928 /** This filter is documented in wp-includes/rest-api/class-wp-rest-server.php */ |
2872 $response = apply_filters( 'rest_post_dispatch', rest_ensure_response( $response ), $server, $request ); |
2929 $response = apply_filters( 'rest_post_dispatch', rest_ensure_response( $response ), $server, $request ); |
2873 $embed = $request->has_param( '_embed' ) ? rest_parse_embed_param( $request['_embed'] ) : false; |
2930 $embed = $request->has_param( '_embed' ) ? rest_parse_embed_param( $request['_embed'] ) : false; |
2874 $data = (array) $server->response_to_data( $response, $embed ); |
2931 $data = (array) $server->response_to_data( $response, $embed ); |
2875 |
2932 |
2876 if ( 'OPTIONS' === $method ) { |
2933 if ( 'OPTIONS' === $method ) { |
2877 $memo[ $method ][ $path ] = array( |
2934 $memo[ $method ][ $path ] = array( |
2878 'body' => $data, |
2935 'body' => $data, |
2879 'headers' => $response->headers, |
2936 'headers' => $response->headers, |
2916 * |
2973 * |
2917 * @since 5.5.0 |
2974 * @since 5.5.0 |
2918 * @since 5.6.0 Support the "patternProperties" keyword for objects. |
2975 * @since 5.6.0 Support the "patternProperties" keyword for objects. |
2919 * Support the "anyOf" and "oneOf" keywords. |
2976 * Support the "anyOf" and "oneOf" keywords. |
2920 * |
2977 * |
2921 * @param array|object $data The response data to modify. |
2978 * @param array|object $response_data The response data to modify. |
2922 * @param array $schema The schema for the endpoint used to filter the response. |
2979 * @param array $schema The schema for the endpoint used to filter the response. |
2923 * @param string $context The requested context. |
2980 * @param string $context The requested context. |
2924 * @return array|object The filtered response data. |
2981 * @return array|object The filtered response data. |
2925 */ |
2982 */ |
2926 function rest_filter_response_by_context( $data, $schema, $context ) { |
2983 function rest_filter_response_by_context( $response_data, $schema, $context ) { |
2927 if ( isset( $schema['anyOf'] ) ) { |
2984 if ( isset( $schema['anyOf'] ) ) { |
2928 $matching_schema = rest_find_any_matching_schema( $data, $schema, '' ); |
2985 $matching_schema = rest_find_any_matching_schema( $response_data, $schema, '' ); |
2929 if ( ! is_wp_error( $matching_schema ) ) { |
2986 if ( ! is_wp_error( $matching_schema ) ) { |
2930 if ( ! isset( $schema['type'] ) ) { |
2987 if ( ! isset( $schema['type'] ) ) { |
2931 $schema['type'] = $matching_schema['type']; |
2988 $schema['type'] = $matching_schema['type']; |
2932 } |
2989 } |
2933 |
2990 |
2934 $data = rest_filter_response_by_context( $data, $matching_schema, $context ); |
2991 $response_data = rest_filter_response_by_context( $response_data, $matching_schema, $context ); |
2935 } |
2992 } |
2936 } |
2993 } |
2937 |
2994 |
2938 if ( isset( $schema['oneOf'] ) ) { |
2995 if ( isset( $schema['oneOf'] ) ) { |
2939 $matching_schema = rest_find_one_matching_schema( $data, $schema, '', true ); |
2996 $matching_schema = rest_find_one_matching_schema( $response_data, $schema, '', true ); |
2940 if ( ! is_wp_error( $matching_schema ) ) { |
2997 if ( ! is_wp_error( $matching_schema ) ) { |
2941 if ( ! isset( $schema['type'] ) ) { |
2998 if ( ! isset( $schema['type'] ) ) { |
2942 $schema['type'] = $matching_schema['type']; |
2999 $schema['type'] = $matching_schema['type']; |
2943 } |
3000 } |
2944 |
3001 |
2945 $data = rest_filter_response_by_context( $data, $matching_schema, $context ); |
3002 $response_data = rest_filter_response_by_context( $response_data, $matching_schema, $context ); |
2946 } |
3003 } |
2947 } |
3004 } |
2948 |
3005 |
2949 if ( ! is_array( $data ) && ! is_object( $data ) ) { |
3006 if ( ! is_array( $response_data ) && ! is_object( $response_data ) ) { |
2950 return $data; |
3007 return $response_data; |
2951 } |
3008 } |
2952 |
3009 |
2953 if ( isset( $schema['type'] ) ) { |
3010 if ( isset( $schema['type'] ) ) { |
2954 $type = $schema['type']; |
3011 $type = $schema['type']; |
2955 } elseif ( isset( $schema['properties'] ) ) { |
3012 } elseif ( isset( $schema['properties'] ) ) { |
2956 $type = 'object'; // Back compat if a developer accidentally omitted the type. |
3013 $type = 'object'; // Back compat if a developer accidentally omitted the type. |
2957 } else { |
3014 } else { |
2958 return $data; |
3015 return $response_data; |
2959 } |
3016 } |
2960 |
3017 |
2961 $is_array_type = 'array' === $type || ( is_array( $type ) && in_array( 'array', $type, true ) ); |
3018 $is_array_type = 'array' === $type || ( is_array( $type ) && in_array( 'array', $type, true ) ); |
2962 $is_object_type = 'object' === $type || ( is_array( $type ) && in_array( 'object', $type, true ) ); |
3019 $is_object_type = 'object' === $type || ( is_array( $type ) && in_array( 'object', $type, true ) ); |
2963 |
3020 |
2964 if ( $is_array_type && $is_object_type ) { |
3021 if ( $is_array_type && $is_object_type ) { |
2965 if ( rest_is_array( $data ) ) { |
3022 if ( rest_is_array( $response_data ) ) { |
2966 $is_object_type = false; |
3023 $is_object_type = false; |
2967 } else { |
3024 } else { |
2968 $is_array_type = false; |
3025 $is_array_type = false; |
2969 } |
3026 } |
2970 } |
3027 } |
2971 |
3028 |
2972 $has_additional_properties = $is_object_type && isset( $schema['additionalProperties'] ) && is_array( $schema['additionalProperties'] ); |
3029 $has_additional_properties = $is_object_type && isset( $schema['additionalProperties'] ) && is_array( $schema['additionalProperties'] ); |
2973 |
3030 |
2974 foreach ( $data as $key => $value ) { |
3031 foreach ( $response_data as $key => $value ) { |
2975 $check = array(); |
3032 $check = array(); |
2976 |
3033 |
2977 if ( $is_array_type ) { |
3034 if ( $is_array_type ) { |
2978 $check = isset( $schema['items'] ) ? $schema['items'] : array(); |
3035 $check = isset( $schema['items'] ) ? $schema['items'] : array(); |
2979 } elseif ( $is_object_type ) { |
3036 } elseif ( $is_object_type ) { |
2994 } |
3051 } |
2995 |
3052 |
2996 if ( ! in_array( $context, $check['context'], true ) ) { |
3053 if ( ! in_array( $context, $check['context'], true ) ) { |
2997 if ( $is_array_type ) { |
3054 if ( $is_array_type ) { |
2998 // All array items share schema, so there's no need to check each one. |
3055 // All array items share schema, so there's no need to check each one. |
2999 $data = array(); |
3056 $response_data = array(); |
3000 break; |
3057 break; |
3001 } |
3058 } |
3002 |
3059 |
3003 if ( is_object( $data ) ) { |
3060 if ( is_object( $response_data ) ) { |
3004 unset( $data->$key ); |
3061 unset( $response_data->$key ); |
3005 } else { |
3062 } else { |
3006 unset( $data[ $key ] ); |
3063 unset( $response_data[ $key ] ); |
3007 } |
3064 } |
3008 } elseif ( is_array( $value ) || is_object( $value ) ) { |
3065 } elseif ( is_array( $value ) || is_object( $value ) ) { |
3009 $new_value = rest_filter_response_by_context( $value, $check, $context ); |
3066 $new_value = rest_filter_response_by_context( $value, $check, $context ); |
3010 |
3067 |
3011 if ( is_object( $data ) ) { |
3068 if ( is_object( $response_data ) ) { |
3012 $data->$key = $new_value; |
3069 $response_data->$key = $new_value; |
3013 } else { |
3070 } else { |
3014 $data[ $key ] = $new_value; |
3071 $response_data[ $key ] = $new_value; |
3015 } |
3072 } |
3016 } |
3073 } |
3017 } |
3074 } |
3018 |
3075 |
3019 return $data; |
3076 return $response_data; |
3020 } |
3077 } |
3021 |
3078 |
3022 /** |
3079 /** |
3023 * Sets the "additionalProperties" to false by default for all object definitions in the schema. |
3080 * Sets the "additionalProperties" to false by default for all object definitions in the schema. |
3024 * |
3081 * |
3289 |
3346 |
3290 /** |
3347 /** |
3291 * Converts an error to a response object. |
3348 * Converts an error to a response object. |
3292 * |
3349 * |
3293 * This iterates over all error codes and messages to change it into a flat |
3350 * This iterates over all error codes and messages to change it into a flat |
3294 * array. This enables simpler client behaviour, as it is represented as a |
3351 * array. This enables simpler client behavior, as it is represented as a |
3295 * list in JSON rather than an object/map. |
3352 * list in JSON rather than an object/map. |
3296 * |
3353 * |
3297 * @since 5.7.0 |
3354 * @since 5.7.0 |
3298 * |
3355 * |
3299 * @param WP_Error $error WP_Error instance. |
3356 * @param WP_Error $error WP_Error instance. |
3337 $data['additional_errors'] = $errors; |
3394 $data['additional_errors'] = $errors; |
3338 } |
3395 } |
3339 |
3396 |
3340 return new WP_REST_Response( $data, $status ); |
3397 return new WP_REST_Response( $data, $status ); |
3341 } |
3398 } |
3399 |
|
3400 /** |
|
3401 * Checks whether a REST API endpoint request is currently being handled. |
|
3402 * |
|
3403 * This may be a standalone REST API request, or an internal request dispatched from within a regular page load. |
|
3404 * |
|
3405 * @since 6.5.0 |
|
3406 * |
|
3407 * @global WP_REST_Server $wp_rest_server REST server instance. |
|
3408 * |
|
3409 * @return bool True if a REST endpoint request is currently being handled, false otherwise. |
|
3410 */ |
|
3411 function wp_is_rest_endpoint() { |
|
3412 /* @var WP_REST_Server $wp_rest_server */ |
|
3413 global $wp_rest_server; |
|
3414 |
|
3415 // Check whether this is a standalone REST request. |
|
3416 $is_rest_endpoint = wp_is_serving_rest_request(); |
|
3417 if ( ! $is_rest_endpoint ) { |
|
3418 // Otherwise, check whether an internal REST request is currently being handled. |
|
3419 $is_rest_endpoint = isset( $wp_rest_server ) |
|
3420 && $wp_rest_server->is_dispatching(); |
|
3421 } |
|
3422 |
|
3423 /** |
|
3424 * Filters whether a REST endpoint request is currently being handled. |
|
3425 * |
|
3426 * This may be a standalone REST API request, or an internal request dispatched from within a regular page load. |
|
3427 * |
|
3428 * @since 6.5.0 |
|
3429 * |
|
3430 * @param bool $is_request_endpoint Whether a REST endpoint request is currently being handled. |
|
3431 */ |
|
3432 return (bool) apply_filters( 'wp_is_rest_endpoint', $is_rest_endpoint ); |
|
3433 } |