wp/wp-includes/rest-api.php
changeset 19 3d72ae0968f4
parent 18 be944660c56a
child 21 48c4eec2b7e6
equal deleted inserted replaced
18:be944660c56a 19:3d72ae0968f4
   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.
  1089  *
  1113  *
  1090  * @since 5.7.0
  1114  * @since 5.7.0
  1091  *
  1115  *
  1092  * @global string|null $wp_rest_application_password_uuid
  1116  * @global string|null $wp_rest_application_password_uuid
  1093  *
  1117  *
  1094  * @return string|null The App Password UUID, or null if Application Passwords was not used.
  1118  * @return string|null The Application Password UUID, or null if Application Passwords was not used.
  1095  */
  1119  */
  1096 function rest_get_authenticated_app_password() {
  1120 function rest_get_authenticated_app_password() {
  1097 	global $wp_rest_application_password_uuid;
  1121 	global $wp_rest_application_password_uuid;
  1098 
  1122 
  1099 	return $wp_rest_application_password_uuid;
  1123 	return $wp_rest_application_password_uuid;
  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.
  2775 			case 'ip':
  2800 			case 'ip':
  2776 				return sanitize_text_field( $value );
  2801 				return sanitize_text_field( $value );
  2777 
  2802 
  2778 			case 'uuid':
  2803 			case 'uuid':
  2779 				return sanitize_text_field( $value );
  2804 				return sanitize_text_field( $value );
       
  2805 
       
  2806 			case 'text-field':
       
  2807 				return sanitize_text_field( $value );
       
  2808 
       
  2809 			case 'textarea-field':
       
  2810 				return sanitize_textarea_field( $value );
  2780 		}
  2811 		}
  2781 	}
  2812 	}
  2782 
  2813 
  2783 	if ( 'string' === $args['type'] ) {
  2814 	if ( 'string' === $args['type'] ) {
  2784 		return (string) $value;
  2815 		return (string) $value;
  2816 		if ( ! in_array( $method, array( 'GET', 'OPTIONS' ), true ) ) {
  2847 		if ( ! in_array( $method, array( 'GET', 'OPTIONS' ), true ) ) {
  2817 			$method = 'GET';
  2848 			$method = 'GET';
  2818 		}
  2849 		}
  2819 	}
  2850 	}
  2820 
  2851 
       
  2852 	$path = untrailingslashit( $path );
       
  2853 	if ( empty( $path ) ) {
       
  2854 		$path = '/';
       
  2855 	}
       
  2856 
  2821 	$path_parts = parse_url( $path );
  2857 	$path_parts = parse_url( $path );
  2822 	if ( false === $path_parts ) {
  2858 	if ( false === $path_parts ) {
  2823 		return $memo;
  2859 		return $memo;
  2824 	}
  2860 	}
  2825 
  2861 
  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  *
  3220  * @return WP_REST_Response List of associative arrays with code and message keys.
  3301  * @return WP_REST_Response List of associative arrays with code and message keys.
  3221  */
  3302  */
  3222 function rest_convert_error_to_response( $error ) {
  3303 function rest_convert_error_to_response( $error ) {
  3223 	$status = array_reduce(
  3304 	$status = array_reduce(
  3224 		$error->get_all_error_data(),
  3305 		$error->get_all_error_data(),
  3225 		function ( $status, $error_data ) {
  3306 		static function ( $status, $error_data ) {
  3226 			return is_array( $error_data ) && isset( $error_data['status'] ) ? $error_data['status'] : $status;
  3307 			return is_array( $error_data ) && isset( $error_data['status'] ) ? $error_data['status'] : $status;
  3227 		},
  3308 		},
  3228 		500
  3309 		500
  3229 	);
  3310 	);
  3230 
  3311