116 * @since 4.7.0 |
116 * @since 4.7.0 |
117 * |
117 * |
118 * @global array $wp_rest_additional_fields Holds registered fields, organized |
118 * @global array $wp_rest_additional_fields Holds registered fields, organized |
119 * by object type. |
119 * by object type. |
120 * |
120 * |
121 * @param string|array $object_type Object(s) the field is being registered |
121 * @param string|array $object_type Object(s) the field is being registered to, |
122 * to, "post"|"term"|"comment" etc. |
122 * "post"|"term"|"comment" etc. |
123 * @param string $attribute The attribute name. |
123 * @param string $attribute The attribute name. |
124 * @param array $args { |
124 * @param array $args { |
125 * Optional. An array of arguments used to handle the registered field. |
125 * Optional. An array of arguments used to handle the registered field. |
126 * |
126 * |
127 * @type callable|null $get_callback Optional. The callback function used to retrieve the field value. Default is |
127 * @type callable|null $get_callback Optional. The callback function used to retrieve the field value. Default is |
133 * @type array|null $schema Optional. The schema for this field. |
133 * @type array|null $schema Optional. The schema for this field. |
134 * Default is 'null', no schema entry will be returned. |
134 * Default is 'null', no schema entry will be returned. |
135 * } |
135 * } |
136 */ |
136 */ |
137 function register_rest_field( $object_type, $attribute, $args = array() ) { |
137 function register_rest_field( $object_type, $attribute, $args = array() ) { |
|
138 global $wp_rest_additional_fields; |
|
139 |
138 $defaults = array( |
140 $defaults = array( |
139 'get_callback' => null, |
141 'get_callback' => null, |
140 'update_callback' => null, |
142 'update_callback' => null, |
141 'schema' => null, |
143 'schema' => null, |
142 ); |
144 ); |
143 |
145 |
144 $args = wp_parse_args( $args, $defaults ); |
146 $args = wp_parse_args( $args, $defaults ); |
145 |
|
146 global $wp_rest_additional_fields; |
|
147 |
147 |
148 $object_types = (array) $object_type; |
148 $object_types = (array) $object_type; |
149 |
149 |
150 foreach ( $object_types as $object_type ) { |
150 foreach ( $object_types as $object_type ) { |
151 $wp_rest_additional_fields[ $object_type ][ $attribute ] = $args; |
151 $wp_rest_additional_fields[ $object_type ][ $attribute ] = $args; |
292 |
292 |
293 $controller = new WP_REST_Search_Controller( $search_handlers ); |
293 $controller = new WP_REST_Search_Controller( $search_handlers ); |
294 $controller->register_routes(); |
294 $controller->register_routes(); |
295 |
295 |
296 // Block Renderer. |
296 // Block Renderer. |
297 $controller = new WP_REST_Block_Renderer_Controller; |
297 $controller = new WP_REST_Block_Renderer_Controller(); |
298 $controller->register_routes(); |
298 $controller->register_routes(); |
299 |
299 |
300 // Block Types. |
300 // Block Types. |
301 $controller = new WP_REST_Block_Types_Controller(); |
301 $controller = new WP_REST_Block_Types_Controller(); |
302 $controller->register_routes(); |
302 $controller->register_routes(); |
303 |
303 |
|
304 // Global Styles. |
|
305 $controller = new WP_REST_Global_Styles_Controller; |
|
306 $controller->register_routes(); |
|
307 |
304 // Settings. |
308 // Settings. |
305 $controller = new WP_REST_Settings_Controller; |
309 $controller = new WP_REST_Settings_Controller; |
306 $controller->register_routes(); |
310 $controller->register_routes(); |
307 |
311 |
308 // Themes. |
312 // Themes. |
331 |
335 |
332 // Pattern Directory. |
336 // Pattern Directory. |
333 $controller = new WP_REST_Pattern_Directory_Controller(); |
337 $controller = new WP_REST_Pattern_Directory_Controller(); |
334 $controller->register_routes(); |
338 $controller->register_routes(); |
335 |
339 |
|
340 // Block Patterns. |
|
341 $controller = new WP_REST_Block_Patterns_Controller(); |
|
342 $controller->register_routes(); |
|
343 |
|
344 // Block Pattern Categories. |
|
345 $controller = new WP_REST_Block_Pattern_Categories_Controller(); |
|
346 $controller->register_routes(); |
|
347 |
336 // Site Health. |
348 // Site Health. |
337 $site_health = WP_Site_Health::get_instance(); |
349 $site_health = WP_Site_Health::get_instance(); |
338 $controller = new WP_REST_Site_Health_Controller( $site_health ); |
350 $controller = new WP_REST_Site_Health_Controller( $site_health ); |
|
351 $controller->register_routes(); |
|
352 |
|
353 // URL Details. |
|
354 $controller = new WP_REST_URL_Details_Controller(); |
|
355 $controller->register_routes(); |
|
356 |
|
357 // Menu Locations. |
|
358 $controller = new WP_REST_Menu_Locations_Controller(); |
|
359 $controller->register_routes(); |
|
360 |
|
361 // Site Editor Export. |
|
362 $controller = new WP_REST_Edit_Site_Export_Controller(); |
339 $controller->register_routes(); |
363 $controller->register_routes(); |
340 } |
364 } |
341 |
365 |
342 /** |
366 /** |
343 * Loads the REST API. |
367 * Loads the REST API. |
2633 * Sanitize a value based on a schema. |
2657 * Sanitize a value based on a schema. |
2634 * |
2658 * |
2635 * @since 4.7.0 |
2659 * @since 4.7.0 |
2636 * @since 5.5.0 Added the `$param` parameter. |
2660 * @since 5.5.0 Added the `$param` parameter. |
2637 * @since 5.6.0 Support the "anyOf" and "oneOf" keywords. |
2661 * @since 5.6.0 Support the "anyOf" and "oneOf" keywords. |
|
2662 * @since 5.9.0 Added `text-field` and `textarea-field` formats. |
2638 * |
2663 * |
2639 * @param mixed $value The value to sanitize. |
2664 * @param mixed $value The value to sanitize. |
2640 * @param array $args Schema array to use for sanitization. |
2665 * @param array $args Schema array to use for sanitization. |
2641 * @param string $param The parameter name, used in error messages. |
2666 * @param string $param The parameter name, used in error messages. |
2642 * @return mixed|WP_Error The sanitized value or a WP_Error instance if the value cannot be safely sanitized. |
2667 * @return mixed|WP_Error The sanitized value or a WP_Error instance if the value cannot be safely sanitized. |
2830 } |
2866 } |
2831 |
2867 |
2832 $response = rest_do_request( $request ); |
2868 $response = rest_do_request( $request ); |
2833 if ( 200 === $response->status ) { |
2869 if ( 200 === $response->status ) { |
2834 $server = rest_get_server(); |
2870 $server = rest_get_server(); |
|
2871 /** 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 ); |
2835 $embed = $request->has_param( '_embed' ) ? rest_parse_embed_param( $request['_embed'] ) : false; |
2873 $embed = $request->has_param( '_embed' ) ? rest_parse_embed_param( $request['_embed'] ) : false; |
2836 $data = (array) $server->response_to_data( $response, $embed ); |
2874 $data = (array) $server->response_to_data( $response, $embed ); |
2837 |
2875 |
2838 if ( 'OPTIONS' === $method ) { |
2876 if ( 'OPTIONS' === $method ) { |
2839 $response = rest_send_allow_header( $response, $server, $request ); |
|
2840 |
|
2841 $memo[ $method ][ $path ] = array( |
2877 $memo[ $method ][ $path ] = array( |
2842 'body' => $data, |
2878 'body' => $data, |
2843 'headers' => $response->headers, |
2879 'headers' => $response->headers, |
2844 ); |
2880 ); |
2845 } else { |
2881 } else { |
3026 * Gets the REST API route for a post. |
3062 * Gets the REST API route for a post. |
3027 * |
3063 * |
3028 * @since 5.5.0 |
3064 * @since 5.5.0 |
3029 * |
3065 * |
3030 * @param int|WP_Post $post Post ID or post object. |
3066 * @param int|WP_Post $post Post ID or post object. |
3031 * @return string The route path with a leading slash for the given post, or an empty string if there is not a route. |
3067 * @return string The route path with a leading slash for the given post, |
|
3068 * or an empty string if there is not a route. |
3032 */ |
3069 */ |
3033 function rest_get_route_for_post( $post ) { |
3070 function rest_get_route_for_post( $post ) { |
3034 $post = get_post( $post ); |
3071 $post = get_post( $post ); |
3035 |
3072 |
3036 if ( ! $post instanceof WP_Post ) { |
3073 if ( ! $post instanceof WP_Post ) { |
3037 return ''; |
3074 return ''; |
3038 } |
3075 } |
3039 |
3076 |
3040 $post_type = get_post_type_object( $post->post_type ); |
3077 $post_type_route = rest_get_route_for_post_type_items( $post->post_type ); |
3041 if ( ! $post_type ) { |
3078 if ( ! $post_type_route ) { |
3042 return ''; |
3079 return ''; |
3043 } |
3080 } |
3044 |
3081 |
3045 $controller = $post_type->get_rest_controller(); |
3082 $route = sprintf( '%s/%d', $post_type_route, $post->ID ); |
3046 if ( ! $controller ) { |
|
3047 return ''; |
|
3048 } |
|
3049 |
|
3050 $route = ''; |
|
3051 |
|
3052 // The only two controllers that we can detect are the Attachments and Posts controllers. |
|
3053 if ( in_array( get_class( $controller ), array( 'WP_REST_Attachments_Controller', 'WP_REST_Posts_Controller' ), true ) ) { |
|
3054 $namespace = 'wp/v2'; |
|
3055 $rest_base = ! empty( $post_type->rest_base ) ? $post_type->rest_base : $post_type->name; |
|
3056 $route = sprintf( '/%s/%s/%d', $namespace, $rest_base, $post->ID ); |
|
3057 } |
|
3058 |
3083 |
3059 /** |
3084 /** |
3060 * Filters the REST API route for a post. |
3085 * Filters the REST API route for a post. |
3061 * |
3086 * |
3062 * @since 5.5.0 |
3087 * @since 5.5.0 |
3066 */ |
3091 */ |
3067 return apply_filters( 'rest_route_for_post', $route, $post ); |
3092 return apply_filters( 'rest_route_for_post', $route, $post ); |
3068 } |
3093 } |
3069 |
3094 |
3070 /** |
3095 /** |
|
3096 * Gets the REST API route for a post type. |
|
3097 * |
|
3098 * @since 5.9.0 |
|
3099 * |
|
3100 * @param string $post_type The name of a registered post type. |
|
3101 * @return string The route path with a leading slash for the given post type, |
|
3102 * or an empty string if there is not a route. |
|
3103 */ |
|
3104 function rest_get_route_for_post_type_items( $post_type ) { |
|
3105 $post_type = get_post_type_object( $post_type ); |
|
3106 if ( ! $post_type ) { |
|
3107 return ''; |
|
3108 } |
|
3109 |
|
3110 if ( ! $post_type->show_in_rest ) { |
|
3111 return ''; |
|
3112 } |
|
3113 |
|
3114 $namespace = ! empty( $post_type->rest_namespace ) ? $post_type->rest_namespace : 'wp/v2'; |
|
3115 $rest_base = ! empty( $post_type->rest_base ) ? $post_type->rest_base : $post_type->name; |
|
3116 $route = sprintf( '/%s/%s', $namespace, $rest_base ); |
|
3117 |
|
3118 /** |
|
3119 * Filters the REST API route for a post type. |
|
3120 * |
|
3121 * @since 5.9.0 |
|
3122 * |
|
3123 * @param string $route The route path. |
|
3124 * @param WP_Post_Type $post_type The post type object. |
|
3125 */ |
|
3126 return apply_filters( 'rest_route_for_post_type_items', $route, $post_type ); |
|
3127 } |
|
3128 |
|
3129 /** |
3071 * Gets the REST API route for a term. |
3130 * Gets the REST API route for a term. |
3072 * |
3131 * |
3073 * @since 5.5.0 |
3132 * @since 5.5.0 |
3074 * |
3133 * |
3075 * @param int|WP_Term $term Term ID or term object. |
3134 * @param int|WP_Term $term Term ID or term object. |
3076 * @return string The route path with a leading slash for the given term, or an empty string if there is not a route. |
3135 * @return string The route path with a leading slash for the given term, |
|
3136 * or an empty string if there is not a route. |
3077 */ |
3137 */ |
3078 function rest_get_route_for_term( $term ) { |
3138 function rest_get_route_for_term( $term ) { |
3079 $term = get_term( $term ); |
3139 $term = get_term( $term ); |
3080 |
3140 |
3081 if ( ! $term instanceof WP_Term ) { |
3141 if ( ! $term instanceof WP_Term ) { |
3082 return ''; |
3142 return ''; |
3083 } |
3143 } |
3084 |
3144 |
3085 $taxonomy = get_taxonomy( $term->taxonomy ); |
3145 $taxonomy_route = rest_get_route_for_taxonomy_items( $term->taxonomy ); |
3086 if ( ! $taxonomy ) { |
3146 if ( ! $taxonomy_route ) { |
3087 return ''; |
3147 return ''; |
3088 } |
3148 } |
3089 |
3149 |
3090 $controller = $taxonomy->get_rest_controller(); |
3150 $route = sprintf( '%s/%d', $taxonomy_route, $term->term_id ); |
3091 if ( ! $controller ) { |
|
3092 return ''; |
|
3093 } |
|
3094 |
|
3095 $route = ''; |
|
3096 |
|
3097 // The only controller that works is the Terms controller. |
|
3098 if ( $controller instanceof WP_REST_Terms_Controller ) { |
|
3099 $namespace = 'wp/v2'; |
|
3100 $rest_base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name; |
|
3101 $route = sprintf( '/%s/%s/%d', $namespace, $rest_base, $term->term_id ); |
|
3102 } |
|
3103 |
3151 |
3104 /** |
3152 /** |
3105 * Filters the REST API route for a term. |
3153 * Filters the REST API route for a term. |
3106 * |
3154 * |
3107 * @since 5.5.0 |
3155 * @since 5.5.0 |
3108 * |
3156 * |
3109 * @param string $route The route path. |
3157 * @param string $route The route path. |
3110 * @param WP_Term $term The term object. |
3158 * @param WP_Term $term The term object. |
3111 */ |
3159 */ |
3112 return apply_filters( 'rest_route_for_term', $route, $term ); |
3160 return apply_filters( 'rest_route_for_term', $route, $term ); |
|
3161 } |
|
3162 |
|
3163 /** |
|
3164 * Gets the REST API route for a taxonomy. |
|
3165 * |
|
3166 * @since 5.9.0 |
|
3167 * |
|
3168 * @param string $taxonomy Name of taxonomy. |
|
3169 * @return string The route path with a leading slash for the given taxonomy. |
|
3170 */ |
|
3171 function rest_get_route_for_taxonomy_items( $taxonomy ) { |
|
3172 $taxonomy = get_taxonomy( $taxonomy ); |
|
3173 if ( ! $taxonomy ) { |
|
3174 return ''; |
|
3175 } |
|
3176 |
|
3177 if ( ! $taxonomy->show_in_rest ) { |
|
3178 return ''; |
|
3179 } |
|
3180 |
|
3181 $namespace = ! empty( $taxonomy->rest_namespace ) ? $taxonomy->rest_namespace : 'wp/v2'; |
|
3182 $rest_base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name; |
|
3183 $route = sprintf( '/%s/%s', $namespace, $rest_base ); |
|
3184 |
|
3185 /** |
|
3186 * Filters the REST API route for a taxonomy. |
|
3187 * |
|
3188 * @since 5.9.0 |
|
3189 * |
|
3190 * @param string $route The route path. |
|
3191 * @param WP_Taxonomy $taxonomy The taxonomy object. |
|
3192 */ |
|
3193 return apply_filters( 'rest_route_for_taxonomy_items', $route, $taxonomy ); |
3113 } |
3194 } |
3114 |
3195 |
3115 /** |
3196 /** |
3116 * Gets the REST route for the currently queried object. |
3197 * Gets the REST route for the currently queried object. |
3117 * |
3198 * |