diff -r be944660c56a -r 3d72ae0968f4 wp/wp-includes/rest-api.php --- a/wp/wp-includes/rest-api.php Wed Sep 21 18:19:35 2022 +0200 +++ b/wp/wp-includes/rest-api.php Tue Sep 27 16:37:53 2022 +0200 @@ -118,8 +118,8 @@ * @global array $wp_rest_additional_fields Holds registered fields, organized * by object type. * - * @param string|array $object_type Object(s) the field is being registered - * to, "post"|"term"|"comment" etc. + * @param string|array $object_type Object(s) the field is being registered to, + * "post"|"term"|"comment" etc. * @param string $attribute The attribute name. * @param array $args { * Optional. An array of arguments used to handle the registered field. @@ -135,6 +135,8 @@ * } */ function register_rest_field( $object_type, $attribute, $args = array() ) { + global $wp_rest_additional_fields; + $defaults = array( 'get_callback' => null, 'update_callback' => null, @@ -143,8 +145,6 @@ $args = wp_parse_args( $args, $defaults ); - global $wp_rest_additional_fields; - $object_types = (array) $object_type; foreach ( $object_types as $object_type ) { @@ -294,13 +294,17 @@ $controller->register_routes(); // Block Renderer. - $controller = new WP_REST_Block_Renderer_Controller; + $controller = new WP_REST_Block_Renderer_Controller(); $controller->register_routes(); // Block Types. $controller = new WP_REST_Block_Types_Controller(); $controller->register_routes(); + // Global Styles. + $controller = new WP_REST_Global_Styles_Controller; + $controller->register_routes(); + // Settings. $controller = new WP_REST_Settings_Controller; $controller->register_routes(); @@ -333,10 +337,30 @@ $controller = new WP_REST_Pattern_Directory_Controller(); $controller->register_routes(); + // Block Patterns. + $controller = new WP_REST_Block_Patterns_Controller(); + $controller->register_routes(); + + // Block Pattern Categories. + $controller = new WP_REST_Block_Pattern_Categories_Controller(); + $controller->register_routes(); + // Site Health. $site_health = WP_Site_Health::get_instance(); $controller = new WP_REST_Site_Health_Controller( $site_health ); $controller->register_routes(); + + // URL Details. + $controller = new WP_REST_URL_Details_Controller(); + $controller->register_routes(); + + // Menu Locations. + $controller = new WP_REST_Menu_Locations_Controller(); + $controller->register_routes(); + + // Site Editor Export. + $controller = new WP_REST_Edit_Site_Export_Controller(); + $controller->register_routes(); } /** @@ -1091,7 +1115,7 @@ * * @global string|null $wp_rest_application_password_uuid * - * @return string|null The App Password UUID, or null if Application Passwords was not used. + * @return string|null The Application Password UUID, or null if Application Passwords was not used. */ function rest_get_authenticated_app_password() { global $wp_rest_application_password_uuid; @@ -2635,6 +2659,7 @@ * @since 4.7.0 * @since 5.5.0 Added the `$param` parameter. * @since 5.6.0 Support the "anyOf" and "oneOf" keywords. + * @since 5.9.0 Added `text-field` and `textarea-field` formats. * * @param mixed $value The value to sanitize. * @param array $args Schema array to use for sanitization. @@ -2777,6 +2802,12 @@ case 'uuid': return sanitize_text_field( $value ); + + case 'text-field': + return sanitize_text_field( $value ); + + case 'textarea-field': + return sanitize_textarea_field( $value ); } } @@ -2818,6 +2849,11 @@ } } + $path = untrailingslashit( $path ); + if ( empty( $path ) ) { + $path = '/'; + } + $path_parts = parse_url( $path ); if ( false === $path_parts ) { return $memo; @@ -2832,12 +2868,12 @@ $response = rest_do_request( $request ); if ( 200 === $response->status ) { $server = rest_get_server(); + /** This filter is documented in wp-includes/rest-api/class-wp-rest-server.php */ + $response = apply_filters( 'rest_post_dispatch', rest_ensure_response( $response ), $server, $request ); $embed = $request->has_param( '_embed' ) ? rest_parse_embed_param( $request['_embed'] ) : false; $data = (array) $server->response_to_data( $response, $embed ); if ( 'OPTIONS' === $method ) { - $response = rest_send_allow_header( $response, $server, $request ); - $memo[ $method ][ $path ] = array( 'body' => $data, 'headers' => $response->headers, @@ -3028,7 +3064,8 @@ * @since 5.5.0 * * @param int|WP_Post $post Post ID or post object. - * @return string The route path with a leading slash for the given post, or an empty string if there is not a route. + * @return string The route path with a leading slash for the given post, + * or an empty string if there is not a route. */ function rest_get_route_for_post( $post ) { $post = get_post( $post ); @@ -3037,24 +3074,12 @@ return ''; } - $post_type = get_post_type_object( $post->post_type ); - if ( ! $post_type ) { - return ''; - } - - $controller = $post_type->get_rest_controller(); - if ( ! $controller ) { + $post_type_route = rest_get_route_for_post_type_items( $post->post_type ); + if ( ! $post_type_route ) { return ''; } - $route = ''; - - // The only two controllers that we can detect are the Attachments and Posts controllers. - if ( in_array( get_class( $controller ), array( 'WP_REST_Attachments_Controller', 'WP_REST_Posts_Controller' ), true ) ) { - $namespace = 'wp/v2'; - $rest_base = ! empty( $post_type->rest_base ) ? $post_type->rest_base : $post_type->name; - $route = sprintf( '/%s/%s/%d', $namespace, $rest_base, $post->ID ); - } + $route = sprintf( '%s/%d', $post_type_route, $post->ID ); /** * Filters the REST API route for a post. @@ -3068,12 +3093,47 @@ } /** + * Gets the REST API route for a post type. + * + * @since 5.9.0 + * + * @param string $post_type The name of a registered post type. + * @return string The route path with a leading slash for the given post type, + * or an empty string if there is not a route. + */ +function rest_get_route_for_post_type_items( $post_type ) { + $post_type = get_post_type_object( $post_type ); + if ( ! $post_type ) { + return ''; + } + + if ( ! $post_type->show_in_rest ) { + return ''; + } + + $namespace = ! empty( $post_type->rest_namespace ) ? $post_type->rest_namespace : 'wp/v2'; + $rest_base = ! empty( $post_type->rest_base ) ? $post_type->rest_base : $post_type->name; + $route = sprintf( '/%s/%s', $namespace, $rest_base ); + + /** + * Filters the REST API route for a post type. + * + * @since 5.9.0 + * + * @param string $route The route path. + * @param WP_Post_Type $post_type The post type object. + */ + return apply_filters( 'rest_route_for_post_type_items', $route, $post_type ); +} + +/** * Gets the REST API route for a term. * * @since 5.5.0 * * @param int|WP_Term $term Term ID or term object. - * @return string The route path with a leading slash for the given term, or an empty string if there is not a route. + * @return string The route path with a leading slash for the given term, + * or an empty string if there is not a route. */ function rest_get_route_for_term( $term ) { $term = get_term( $term ); @@ -3082,24 +3142,12 @@ return ''; } - $taxonomy = get_taxonomy( $term->taxonomy ); - if ( ! $taxonomy ) { - return ''; - } - - $controller = $taxonomy->get_rest_controller(); - if ( ! $controller ) { + $taxonomy_route = rest_get_route_for_taxonomy_items( $term->taxonomy ); + if ( ! $taxonomy_route ) { return ''; } - $route = ''; - - // The only controller that works is the Terms controller. - if ( $controller instanceof WP_REST_Terms_Controller ) { - $namespace = 'wp/v2'; - $rest_base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name; - $route = sprintf( '/%s/%s/%d', $namespace, $rest_base, $term->term_id ); - } + $route = sprintf( '%s/%d', $taxonomy_route, $term->term_id ); /** * Filters the REST API route for a term. @@ -3113,6 +3161,39 @@ } /** + * Gets the REST API route for a taxonomy. + * + * @since 5.9.0 + * + * @param string $taxonomy Name of taxonomy. + * @return string The route path with a leading slash for the given taxonomy. + */ +function rest_get_route_for_taxonomy_items( $taxonomy ) { + $taxonomy = get_taxonomy( $taxonomy ); + if ( ! $taxonomy ) { + return ''; + } + + if ( ! $taxonomy->show_in_rest ) { + return ''; + } + + $namespace = ! empty( $taxonomy->rest_namespace ) ? $taxonomy->rest_namespace : 'wp/v2'; + $rest_base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name; + $route = sprintf( '/%s/%s', $namespace, $rest_base ); + + /** + * Filters the REST API route for a taxonomy. + * + * @since 5.9.0 + * + * @param string $route The route path. + * @param WP_Taxonomy $taxonomy The taxonomy object. + */ + return apply_filters( 'rest_route_for_taxonomy_items', $route, $taxonomy ); +} + +/** * Gets the REST route for the currently queried object. * * @since 5.5.0 @@ -3222,7 +3303,7 @@ function rest_convert_error_to_response( $error ) { $status = array_reduce( $error->get_all_error_data(), - function ( $status, $error_data ) { + static function ( $status, $error_data ) { return is_array( $error_data ) && isset( $error_data['status'] ) ? $error_data['status'] : $status; }, 500