diff --git a/docs/designers-developers/developers/backward-compatibility/deprecations.md b/docs/designers-developers/developers/backward-compatibility/deprecations.md index 6db2ed322b6a5..85e82f25549c6 100644 --- a/docs/designers-developers/developers/backward-compatibility/deprecations.md +++ b/docs/designers-developers/developers/backward-compatibility/deprecations.md @@ -12,6 +12,15 @@ The Gutenberg project's deprecation policy is intended to support backward compa - The PHP function `strip_dynamic_blocks_remove_filter` has been removed. - The PHP function `gutenberg_post_has_blocks` has been removed. Use [`has_blocks`](https://developer.wordpress.org/reference/functions/has_blocks/) instead. - The PHP function `gutenberg_content_has_blocks` has been removed. Use [`has_blocks`](https://developer.wordpress.org/reference/functions/has_blocks/) instead. +- The PHP function `gutenberg_register_rest_routes` has been removed. +- The PHP function `gutenberg_add_taxonomy_visibility_field` has been removed. +- The PHP function `gutenberg_get_taxonomy_visibility_data` has been removed. +- The PHP function `gutenberg_add_permalink_template_to_posts` has been removed. +- The PHP function `gutenberg_add_block_format_to_post_content` has been removed. +- The PHP function `gutenberg_add_target_schema_to_links` has been removed. +- The PHP function `gutenberg_register_post_prepare_functions` has been removed. +- The PHP function `gutenberg_silence_rest_errors` has been removed. +- The PHP function `gutenberg_filter_post_type_labels` has been removed. ## 4.5.0 - `Dropdown.refresh()` has been deprecated as the contained `Popover` is now automatically refreshed. diff --git a/lib/class-wp-rest-autosaves-controller.php b/lib/class-wp-rest-autosaves-controller.php deleted file mode 100644 index 6f6496c35790e..0000000000000 --- a/lib/class-wp-rest-autosaves-controller.php +++ /dev/null @@ -1,426 +0,0 @@ -parent_post_type = $parent_post_type; - $post_type_object = get_post_type_object( $parent_post_type ); - - // Ensure that post type-specific controller logic is available. - $parent_controller_class = ! empty( $post_type_object->rest_controller_class ) ? $post_type_object->rest_controller_class : 'WP_REST_Posts_Controller'; - - $this->parent_controller = new $parent_controller_class( $post_type_object->name ); - $this->revisions_controller = new WP_REST_Revisions_Controller( $parent_post_type ); - $this->rest_namespace = 'wp/v2'; - $this->rest_base = 'autosaves'; - $this->parent_base = ! empty( $post_type_object->rest_base ) ? $post_type_object->rest_base : $post_type_object->name; - } - - /** - * Registers routes for autosaves. - * - * @since 5.0.0 - * - * @see register_rest_route() - */ - public function register_routes() { - register_rest_route( - $this->rest_namespace, - '/' . $this->parent_base . '/(?P[\d]+)/' . $this->rest_base, - array( - 'args' => array( - 'parent' => array( - 'description' => __( 'The ID for the parent of the object.', 'gutenberg' ), - 'type' => 'integer', - ), - ), - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => array( $this, 'get_items' ), - 'permission_callback' => array( $this, 'get_items_permissions_check' ), - 'args' => $this->get_collection_params(), - ), - array( - 'methods' => WP_REST_Server::CREATABLE, - 'callback' => array( $this, 'create_item' ), - 'permission_callback' => array( $this, 'create_item_permissions_check' ), - 'args' => $this->parent_controller->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ), - ), - 'schema' => array( $this, 'get_public_item_schema' ), - ) - ); - - register_rest_route( - $this->rest_namespace, - '/' . $this->parent_base . '/(?P[\d]+)/' . $this->rest_base . '/(?P[\d]+)', - array( - 'args' => array( - 'parent' => array( - 'description' => __( 'The ID for the parent of the object.', 'gutenberg' ), - 'type' => 'integer', - ), - 'id' => array( - 'description' => __( 'The ID for the object.', 'gutenberg' ), - 'type' => 'integer', - ), - ), - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => array( $this, 'get_item' ), - 'permission_callback' => array( $this->revisions_controller, 'get_item_permissions_check' ), - 'args' => array( - 'context' => $this->get_context_param( array( 'default' => 'view' ) ), - ), - ), - 'schema' => array( $this, 'get_public_item_schema' ), - ) - ); - - } - - /** - * Get the parent post. - * - * @since 5.0.0 - * - * @param int $parent_id Supplied ID. - * @return WP_Post|WP_Error Post object if ID is valid, WP_Error otherwise. - */ - protected function get_parent( $parent_id ) { - return $this->revisions_controller->get_parent( $parent_id ); - } - - /** - * Checks if a given request has access to get autosaves. - * - * @since 5.0.0 - * - * @param WP_REST_Request $request Full data about the request. - * @return true|WP_Error True if the request has read access, WP_Error object otherwise. - */ - public function get_items_permissions_check( $request ) { - $parent = $this->get_parent( $request['id'] ); - if ( is_wp_error( $parent ) ) { - return $parent; - } - - $parent_post_type_obj = get_post_type_object( $parent->post_type ); - if ( ! current_user_can( $parent_post_type_obj->cap->edit_post, $parent->ID ) ) { - return new WP_Error( 'rest_cannot_read', __( 'Sorry, you are not allowed to view revisions of this post.', 'gutenberg' ), array( 'status' => rest_authorization_required_code() ) ); - } - - return true; - } - - /** - * Checks if a given request has access to create an autosave revision. - * - * Autosave revisions inherit permissions from the parent post, - * check if the current user has permission to edit the post. - * - * @since 5.0.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return true|WP_Error True if the request has access to create the item, WP_Error object otherwise. - */ - public function create_item_permissions_check( $request ) { - $id = $request->get_param( 'id' ); - if ( empty( $id ) ) { - return new WP_Error( 'rest_post_invalid_id', __( 'Invalid item ID.', 'gutenberg' ), array( 'status' => 404 ) ); - } - - return $this->parent_controller->update_item_permissions_check( $request ); - } - - /** - * Creates, updates or deletes an autosave revision. - * - * @since 5.0.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function create_item( $request ) { - - if ( ! defined( 'DOING_AUTOSAVE' ) ) { - define( 'DOING_AUTOSAVE', true ); - } - - $post = get_post( $request['id'] ); - - if ( is_wp_error( $post ) ) { - return $post; - } - - $prepared_post = $this->parent_controller->prepare_item_for_database( $request ); - $prepared_post->ID = $post->ID; - $user_id = get_current_user_id(); - - if ( ( 'draft' === $post->post_status || 'auto-draft' === $post->post_status ) && $post->post_author == $user_id ) { - // Draft posts for the same author: autosaving updates the post and does not create a revision. - // Convert the post object to an array and add slashes, wp_update_post expects escaped array. - $autosave_id = wp_update_post( wp_slash( (array) $prepared_post ), true ); - } else { - // Non-draft posts: create or update the post autosave. - $autosave_id = $this->create_post_autosave( (array) $prepared_post ); - } - - if ( is_wp_error( $autosave_id ) ) { - return $autosave_id; - } - - $autosave = get_post( $autosave_id ); - $request->set_param( 'context', 'edit' ); - - $response = $this->prepare_item_for_response( $autosave, $request ); - $response = rest_ensure_response( $response ); - - return $response; - } - - /** - * Get the autosave, if the ID is valid. - * - * @since 5.0.0 - * - * @param WP_REST_Request $request Full data about the request. - * @return WP_Post|WP_Error Revision post object if ID is valid, WP_Error otherwise. - */ - public function get_item( $request ) { - $parent_id = (int) $request->get_param( 'parent' ); - - if ( $parent_id <= 0 ) { - return new WP_Error( 'rest_post_invalid_id', __( 'Invalid parent post ID.', 'gutenberg' ), array( 'status' => 404 ) ); - } - - $autosave = wp_get_post_autosave( $parent_id ); - - if ( ! $autosave ) { - return new WP_Error( 'rest_post_no_autosave', __( 'There is no autosave revision for this post.', 'gutenberg' ), array( 'status' => 404 ) ); - } - - $response = $this->prepare_item_for_response( $autosave, $request ); - return $response; - } - - /** - * Gets a collection of autosaves using wp_get_post_autosave. - * - * Contains the user's autosave, for empty if it doesn't exist. - * - * @since 5.0.0 - * - * @param WP_REST_Request $request Full data about the request. - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function get_items( $request ) { - $parent = $this->get_parent( $request['id'] ); - if ( is_wp_error( $parent ) ) { - return $parent; - } - - $response = array(); - $parent_id = $parent->ID; - $revisions = wp_get_post_revisions( $parent_id, array( 'check_enabled' => false ) ); - - foreach ( $revisions as $revision ) { - if ( false !== strpos( $revision->post_name, "{$parent_id}-autosave" ) ) { - $data = $this->prepare_item_for_response( $revision, $request ); - $response[] = $this->prepare_response_for_collection( $data ); - } - } - - return rest_ensure_response( $response ); - } - - - /** - * Retrieves the autosave's schema, conforming to JSON Schema. - * - * @since 5.0.0 - * - * @return array Item schema data. - */ - public function get_item_schema() { - $schema = $this->revisions_controller->get_item_schema(); - - $schema['properties']['preview_link'] = array( - 'description' => __( 'Preview link for the post.', 'gutenberg' ), - 'type' => 'string', - 'format' => 'uri', - 'context' => array( 'edit' ), - 'readonly' => true, - ); - - return $schema; - } - - /** - * Creates autosave for the specified post. - * - * From wp-admin/post.php. - * - * @since 5.0.0 - * - * @param mixed $post_data Associative array containing the post data. - * @return mixed The autosave revision ID or WP_Error. - */ - public function create_post_autosave( $post_data ) { - - $post_id = (int) $post_data['ID']; - $post = get_post( $post_id ); - - if ( is_wp_error( $post ) ) { - return $post; - } - - $user_id = get_current_user_id(); - - // Store one autosave per author. If there is already an autosave, overwrite it. - $old_autosave = wp_get_post_autosave( $post_id, $user_id ); - - if ( $old_autosave ) { - $new_autosave = _wp_post_revision_data( $post_data, true ); - $new_autosave['ID'] = $old_autosave->ID; - $new_autosave['post_author'] = $user_id; - - // If the new autosave has the same content as the post, delete the autosave. - $autosave_is_different = false; - - foreach ( array_intersect( array_keys( $new_autosave ), array_keys( _wp_post_revision_fields( $post ) ) ) as $field ) { - if ( normalize_whitespace( $new_autosave[ $field ] ) != normalize_whitespace( $post->$field ) ) { - $autosave_is_different = true; - break; - } - } - - if ( ! $autosave_is_different ) { - wp_delete_post_revision( $old_autosave->ID ); - return new WP_Error( 'rest_autosave_no_changes', __( 'There is nothing to save. The autosave and the post content are the same.', 'gutenberg' ), array( 'status' => 400 ) ); - } - - /** - * This filter is documented in wp-admin/post.php. - */ - do_action( 'wp_creating_autosave', $new_autosave ); - - // wp_update_post expects escaped array. - return wp_update_post( wp_slash( $new_autosave ) ); - } - - // Create the new autosave as a special post revision. - return _wp_put_post_revision( $post_data, true ); - } - - /** - * Prepares the revision for the REST response. - * - * @since 5.0.0 - * - * @param WP_Post $post Post revision object. - * @param WP_REST_Request $request Request object. - * - * @return WP_REST_Response Response object. - */ - public function prepare_item_for_response( $post, $request ) { - - $response = $this->revisions_controller->prepare_item_for_response( $post, $request ); - - $schema = $this->get_item_schema(); - - if ( ! empty( $schema['properties']['preview_link'] ) ) { - $parent_id = wp_is_post_autosave( $post ); - $preview_post_id = false === $parent_id ? $post->ID : $parent_id; - $preview_query_args = array(); - - if ( false !== $parent_id ) { - $preview_query_args['preview_id'] = $parent_id; - $preview_query_args['preview_nonce'] = wp_create_nonce( 'post_preview_' . $parent_id ); - } - - $response->data['preview_link'] = get_preview_post_link( $preview_post_id, $preview_query_args ); - } - - $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; - $response->data = $this->filter_response_by_context( $response->data, $context ); - - /** - * Filters a revision returned from the API. - * - * Allows modification of the revision right before it is returned. - * - * @since 5.0.0 - * - * @param WP_REST_Response $response The response object. - * @param WP_Post $post The original revision object. - * @param WP_REST_Request $request Request used to generate the response. - */ - return apply_filters( 'rest_prepare_autosave', $response, $post, $request ); - } - - /** - * Retrieves the query params for the autosaves collection. - * - * @since 5.0.0 - * - * @return array Collection parameters. - */ - public function get_collection_params() { - return array( - 'context' => $this->get_context_param( array( 'default' => 'view' ) ), - ); - } -} diff --git a/lib/class-wp-rest-block-renderer-controller.php b/lib/class-wp-rest-block-renderer-controller.php deleted file mode 100644 index b9839f080376a..0000000000000 --- a/lib/class-wp-rest-block-renderer-controller.php +++ /dev/null @@ -1,178 +0,0 @@ -namespace = 'wp/v2'; - $this->rest_base = 'block-renderer'; - } - - /** - * Registers the necessary REST API routes, one for each dynamic block. - * - * @access public - */ - public function register_routes() { - $block_types = WP_Block_Type_Registry::get_instance()->get_all_registered(); - foreach ( $block_types as $block_type ) { - if ( ! $block_type->is_dynamic() ) { - continue; - } - - register_rest_route( - $this->namespace, - '/' . $this->rest_base . '/(?P' . $block_type->name . ')', - array( - 'args' => array( - 'name' => array( - 'description' => __( 'Unique registered name for the block.', 'gutenberg' ), - 'type' => 'string', - ), - ), - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => array( $this, 'get_item' ), - 'permission_callback' => array( $this, 'get_item_permissions_check' ), - 'args' => array( - 'context' => $this->get_context_param( array( 'default' => 'view' ) ), - 'attributes' => array( - /* translators: %s is the name of the block */ - 'description' => sprintf( __( 'Attributes for %s block', 'gutenberg' ), $block_type->name ), - 'type' => 'object', - 'additionalProperties' => false, - 'properties' => $block_type->get_attributes(), - 'default' => array(), - ), - 'post_id' => array( - 'description' => __( 'ID of the post context.', 'gutenberg' ), - 'type' => 'integer', - ), - ), - ), - 'schema' => array( $this, 'get_public_item_schema' ), - ) - ); - } - } - - /** - * Checks if a given request has access to read blocks. - * - * @since 2.8.0 - * @access public - * - * @param WP_REST_Request $request Request. - * @return true|WP_Error True if the request has read access, WP_Error object otherwise. - */ - public function get_item_permissions_check( $request ) { - global $post; - - $post_id = isset( $request['post_id'] ) ? intval( $request['post_id'] ) : 0; - - if ( 0 < $post_id ) { - $post = get_post( $post_id ); - if ( ! $post || ! current_user_can( 'edit_post', $post->ID ) ) { - return new WP_Error( - 'gutenberg_block_cannot_read', - __( 'Sorry, you are not allowed to read Gutenberg blocks of this post.', 'gutenberg' ), - array( - 'status' => rest_authorization_required_code(), - ) - ); - } - } else { - if ( ! current_user_can( 'edit_posts' ) ) { - return new WP_Error( - 'gutenberg_block_cannot_read', - __( 'Sorry, you are not allowed to read Gutenberg blocks as this user.', 'gutenberg' ), - array( - 'status' => rest_authorization_required_code(), - ) - ); - } - } - - return true; - } - - /** - * Returns block output from block's registered render_callback. - * - * @since 2.8.0 - * @access public - * - * @param WP_REST_Request $request Full details about the request. - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function get_item( $request ) { - global $post; - - $post_id = isset( $request['post_id'] ) ? intval( $request['post_id'] ) : 0; - - if ( 0 < $post_id ) { - $post = get_post( $post_id ); - - // Set up postdata since this will be needed if post_id was set. - setup_postdata( $post ); - } - $registry = WP_Block_Type_Registry::get_instance(); - $block = $registry->get_registered( $request['name'] ); - - if ( null === $block ) { - return new WP_Error( - 'gutenberg_block_invalid', - __( 'Invalid block.', 'gutenberg' ), - array( - 'status' => 404, - ) - ); - } - - $data = array( - 'rendered' => $block->render( $request->get_param( 'attributes' ) ), - ); - return rest_ensure_response( $data ); - } - - /** - * Retrieves block's output schema, conforming to JSON Schema. - * - * @since 2.8.0 - * @access public - * - * @return array Item schema data. - */ - public function get_item_schema() { - return array( - '$schema' => 'http://json-schema.org/schema#', - 'title' => 'rendered-block', - 'type' => 'object', - 'properties' => array( - 'rendered' => array( - 'description' => __( 'The rendered block.', 'gutenberg' ), - 'type' => 'string', - 'required' => true, - 'context' => array( 'edit' ), - ), - ), - ); - } -} diff --git a/lib/class-wp-rest-blocks-controller.php b/lib/class-wp-rest-blocks-controller.php deleted file mode 100644 index 47882fafbff04..0000000000000 --- a/lib/class-wp-rest-blocks-controller.php +++ /dev/null @@ -1,89 +0,0 @@ -post_type ); - if ( ! current_user_can( $post_type->cap->read_post, $post->ID ) ) { - return false; - } - - return parent::check_read_permission( $post ); - } - - /** - * Filters a response based on the context defined in the schema. - * - * @since 4.4.0 - * - * @param array $data Response data to fiter. - * @param string $context Context defined in the schema. - * @return array Filtered response. - */ - public function filter_response_by_context( $data, $context ) { - $data = parent::filter_response_by_context( $data, $context ); - - /* - * Remove `title.rendered` and `content.rendered` from the response. It - * doesn't make sense for a reusable block to have rendered content on its - * own, since rendering a block requires it to be inside a post or a page. - */ - unset( $data['title']['rendered'] ); - unset( $data['content']['rendered'] ); - - return $data; - } - - /** - * Retrieves the block's schema, conforming to JSON Schema. - * - * @since 4.4.0 - * - * @return array Item schema data. - */ - public function get_item_schema() { - $schema = parent::get_item_schema(); - - /* - * Allow all contexts to access `title.raw` and `content.raw`. Clients always - * need the raw markup of a reusable block to do anything useful, e.g. parse - * it or display it in an editor. - */ - $schema['properties']['title']['properties']['raw']['context'] = array( 'view', 'edit' ); - $schema['properties']['content']['properties']['raw']['context'] = array( 'view', 'edit' ); - - /* - * Remove `title.rendered` and `content.rendered` from the schema. It doesn’t - * make sense for a reusable block to have rendered content on its own, since - * rendering a block requires it to be inside a post or a page. - */ - unset( $schema['properties']['title']['properties']['rendered'] ); - unset( $schema['properties']['content']['properties']['rendered'] ); - - return $schema; - } - -} diff --git a/lib/class-wp-rest-post-search-handler.php b/lib/class-wp-rest-post-search-handler.php deleted file mode 100644 index 64d1917432012..0000000000000 --- a/lib/class-wp-rest-post-search-handler.php +++ /dev/null @@ -1,190 +0,0 @@ -type = 'post'; - - // Support all public post types except attachments. - $this->subtypes = array_diff( - array_values( - get_post_types( - array( - 'public' => true, - 'show_in_rest' => true, - ), - 'names' - ) - ), - array( 'attachment' ) - ); - } - - /** - * Searches the object type content for a given search request. - * - * @since 3.3.0 - * - * @param WP_REST_Request $request Full REST request. - * @return array Associative array containing an `WP_REST_Search_Handler::RESULT_IDS` containing - * an array of found IDs and `WP_REST_Search_Handler::RESULT_TOTAL` containing the - * total count for the matching search results. - */ - public function search_items( WP_REST_Request $request ) { - - // Get the post types to search for the current request. - $post_types = $request[ WP_REST_Search_Controller::PROP_SUBTYPE ]; - if ( in_array( WP_REST_Search_Controller::TYPE_ANY, $post_types, true ) ) { - $post_types = $this->subtypes; - } - - $query_args = array( - 'post_type' => $post_types, - 'post_status' => 'publish', - 'paged' => (int) $request['page'], - 'posts_per_page' => (int) $request['per_page'], - 'ignore_sticky_posts' => true, - 'fields' => 'ids', - ); - - if ( ! empty( $request['search'] ) ) { - $query_args['s'] = $request['search']; - } - - $query = new WP_Query(); - $found_ids = $query->query( $query_args ); - $total = $query->found_posts; - - return array( - self::RESULT_IDS => $found_ids, - self::RESULT_TOTAL => $total, - ); - } - - /** - * Prepares the search result for a given ID. - * - * @since 3.3.0 - * - * @param int $id Item ID. - * @param array $fields Fields to include for the item. - * @return array Associative array containing all fields for the item. - */ - public function prepare_item( $id, array $fields ) { - $post = get_post( $id ); - - $data = array(); - - if ( in_array( WP_REST_Search_Controller::PROP_ID, $fields, true ) ) { - $data[ WP_REST_Search_Controller::PROP_ID ] = (int) $post->ID; - } - - if ( in_array( WP_REST_Search_Controller::PROP_TITLE, $fields, true ) ) { - if ( post_type_supports( $post->post_type, 'title' ) ) { - add_filter( 'protected_title_format', array( $this, 'protected_title_format' ) ); - $data[ WP_REST_Search_Controller::PROP_TITLE ] = get_the_title( $post->ID ); - remove_filter( 'protected_title_format', array( $this, 'protected_title_format' ) ); - } else { - $data[ WP_REST_Search_Controller::PROP_TITLE ] = ''; - } - } - - if ( in_array( WP_REST_Search_Controller::PROP_URL, $fields, true ) ) { - $data[ WP_REST_Search_Controller::PROP_URL ] = get_permalink( $post->ID ); - } - - if ( in_array( WP_REST_Search_Controller::PROP_TYPE, $fields, true ) ) { - $data[ WP_REST_Search_Controller::PROP_TYPE ] = $this->type; - } - - if ( in_array( WP_REST_Search_Controller::PROP_SUBTYPE, $fields, true ) ) { - $data[ WP_REST_Search_Controller::PROP_SUBTYPE ] = $post->post_type; - } - - return $data; - } - - /** - * Prepares links for the search result of a given ID. - * - * @since 3.3.0 - * - * @param int $id Item ID. - * @return array Links for the given item. - */ - public function prepare_item_links( $id ) { - $post = get_post( $id ); - - $links = array(); - - $item_route = $this->detect_rest_item_route( $post ); - if ( ! empty( $item_route ) ) { - $links['self'] = array( - 'href' => rest_url( $item_route ), - 'embeddable' => true, - ); - } - - $links['about'] = array( - 'href' => rest_url( 'wp/v2/types/' . $post->post_type ), - ); - - return $links; - } - - /** - * Overwrites the default protected title format. - * - * By default, WordPress will show password protected posts with a title of - * "Protected: %s". As the REST API communicates the protected status of a post - * in a machine readable format, we remove the "Protected: " prefix. - * - * @since 3.3.0 - * - * @return string Protected title format. - */ - public function protected_title_format() { - return '%s'; - } - - /** - * Attempts to detect the route to access a single item. - * - * @since 3.3.0 - * - * @param WP_Post $post Post object. - * @return string REST route relative to the REST base URI, or empty string if unknown. - */ - protected function detect_rest_item_route( $post ) { - $post_type = get_post_type_object( $post->post_type ); - if ( ! $post_type ) { - return ''; - } - - // It's currently impossible to detect the REST URL from a custom controller. - if ( ! empty( $post_type->rest_controller_class ) && 'WP_REST_Posts_Controller' !== $post_type->rest_controller_class ) { - return ''; - } - - $namespace = 'wp/v2'; - $rest_base = ! empty( $post_type->rest_base ) ? $post_type->rest_base : $post_type->name; - - return sprintf( '%s/%s/%d', $namespace, $rest_base, $post->ID ); - } -} diff --git a/lib/class-wp-rest-search-controller.php b/lib/class-wp-rest-search-controller.php deleted file mode 100644 index 69776c5a7be34..0000000000000 --- a/lib/class-wp-rest-search-controller.php +++ /dev/null @@ -1,363 +0,0 @@ -namespace = 'wp/v2'; - $this->rest_base = 'search'; - - foreach ( $search_handlers as $search_handler ) { - if ( ! $search_handler instanceof WP_REST_Search_Handler ) { - - /* translators: %s: PHP class name */ - _doing_it_wrong( __METHOD__, sprintf( __( 'REST search handlers must extend the %s class.', 'gutenberg' ), 'WP_REST_Search_Handler' ), '3.3.0' ); - continue; - } - - $this->search_handlers[ $search_handler->get_type() ] = $search_handler; - } - } - - /** - * Registers the routes for the objects of the controller. - * - * @since 3.3.0 - * - * @see register_rest_route() - */ - public function register_routes() { - register_rest_route( - $this->namespace, - '/' . $this->rest_base, - array( - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => array( $this, 'get_items' ), - 'permission_callback' => array( $this, 'get_items_permission_check' ), - 'args' => $this->get_collection_params(), - ), - 'schema' => array( $this, 'get_public_item_schema' ), - ) - ); - } - - /** - * Checks if a given request has access to search content. - * - * @since 3.3.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return true|WP_Error True if the request has search access, WP_Error object otherwise. - */ - public function get_items_permission_check( $request ) { - return true; - } - - /** - * Retrieves a collection of search results. - * - * @since 3.3.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function get_items( $request ) { - $handler = $this->get_search_handler( $request ); - if ( is_wp_error( $handler ) ) { - return $handler; - } - - $result = $handler->search_items( $request ); - - if ( ! isset( $result[ WP_REST_Search_Handler::RESULT_IDS ] ) || ! is_array( $result[ WP_REST_Search_Handler::RESULT_IDS ] ) || ! isset( $result[ WP_REST_Search_Handler::RESULT_TOTAL ] ) ) { - return new WP_Error( 'rest_search_handler_error', __( 'Internal search handler error.', 'gutenberg' ), array( 'status' => 500 ) ); - } - - $ids = array_map( 'absint', $result[ WP_REST_Search_Handler::RESULT_IDS ] ); - - $results = array(); - foreach ( $ids as $id ) { - $data = $this->prepare_item_for_response( $id, $request ); - $results[] = $this->prepare_response_for_collection( $data ); - } - - $total = (int) $result[ WP_REST_Search_Handler::RESULT_TOTAL ]; - $page = (int) $request['page']; - $per_page = (int) $request['per_page']; - $max_pages = ceil( $total / $per_page ); - - if ( $page > $max_pages && $total > 0 ) { - return new WP_Error( 'rest_search_invalid_page_number', __( 'The page number requested is larger than the number of pages available.', 'gutenberg' ), array( 'status' => 400 ) ); - } - - $response = rest_ensure_response( $results ); - $response->header( 'X-WP-Total', $total ); - $response->header( 'X-WP-TotalPages', $max_pages ); - - $request_params = $request->get_query_params(); - $base = add_query_arg( $request_params, rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ) ); - - if ( $page > 1 ) { - $prev_link = add_query_arg( 'page', $page - 1, $base ); - $response->link_header( 'prev', $prev_link ); - } - if ( $page < $max_pages ) { - $next_link = add_query_arg( 'page', $page + 1, $base ); - $response->link_header( 'next', $next_link ); - } - - return $response; - } - - /** - * Prepares a single search result for response. - * - * @since 3.3.0 - * - * @param int $id ID of the item to prepare. - * @param WP_REST_Request $request Request object. - * @return WP_REST_Response Response object. - */ - public function prepare_item_for_response( $id, $request ) { - $handler = $this->get_search_handler( $request ); - if ( is_wp_error( $handler ) ) { - return new WP_REST_Response(); - } - - if ( method_exists( $this, 'get_fields_for_response' ) ) { - $fields = $this->get_fields_for_response( $request ); - } else { - $schema = $this->get_item_schema(); - $fields = array_keys( $schema['properties'] ); - } - - $data = $handler->prepare_item( $id, $fields ); - $data = $this->add_additional_fields_to_object( $data, $request ); - - $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; - $data = $this->filter_response_by_context( $data, $context ); - - $response = rest_ensure_response( $data ); - - $links = $handler->prepare_item_links( $id ); - $links['collection'] = array( - 'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ), - ); - $response->add_links( $links ); - - return $response; - } - - /** - * Retrieves the item schema, conforming to JSON Schema. - * - * @since 3.3.0 - * - * @return array Item schema data. - */ - public function get_item_schema() { - $types = array(); - $subtypes = array(); - foreach ( $this->search_handlers as $search_handler ) { - $types[] = $search_handler->get_type(); - $subtypes = array_merge( $subtypes, $search_handler->get_subtypes() ); - } - - $types = array_unique( $types ); - $subtypes = array_unique( $subtypes ); - - $schema = array( - '$schema' => 'http://json-schema.org/draft-04/schema#', - 'title' => 'search-result', - 'type' => 'object', - 'properties' => array( - self::PROP_ID => array( - 'description' => __( 'Unique identifier for the object.', 'gutenberg' ), - 'type' => 'integer', - 'context' => array( 'view', 'embed' ), - 'readonly' => true, - ), - self::PROP_TITLE => array( - 'description' => __( 'The title for the object.', 'gutenberg' ), - 'type' => 'string', - 'context' => array( 'view', 'embed' ), - 'readonly' => true, - ), - self::PROP_URL => array( - 'description' => __( 'URL to the object.', 'gutenberg' ), - 'type' => 'string', - 'format' => 'uri', - 'context' => array( 'view', 'embed' ), - 'readonly' => true, - ), - self::PROP_TYPE => array( - 'description' => __( 'Object type.', 'gutenberg' ), - 'type' => 'string', - 'enum' => $types, - 'context' => array( 'view', 'embed' ), - 'readonly' => true, - ), - self::PROP_SUBTYPE => array( - 'description' => __( 'Object subtype.', 'gutenberg' ), - 'type' => 'string', - 'enum' => $subtypes, - 'context' => array( 'view', 'embed' ), - 'readonly' => true, - ), - ), - ); - - return $this->add_additional_fields_schema( $schema ); - } - - /** - * Retrieves the query params for the search results collection. - * - * @since 3.3.0 - * - * @return array Collection parameters. - */ - public function get_collection_params() { - $types = array(); - $subtypes = array(); - foreach ( $this->search_handlers as $search_handler ) { - $types[] = $search_handler->get_type(); - $subtypes = array_merge( $subtypes, $search_handler->get_subtypes() ); - } - - $types = array_unique( $types ); - $subtypes = array_unique( $subtypes ); - - $query_params = parent::get_collection_params(); - - $query_params['context']['default'] = 'view'; - - $query_params[ self::PROP_TYPE ] = array( - 'default' => $types[0], - 'description' => __( 'Limit results to items of an object type.', 'gutenberg' ), - 'type' => 'string', - 'enum' => $types, - ); - - $query_params[ self::PROP_SUBTYPE ] = array( - 'default' => self::TYPE_ANY, - 'description' => __( 'Limit results to items of one or more object subtypes.', 'gutenberg' ), - 'type' => 'array', - 'items' => array( - 'enum' => array_merge( $subtypes, array( self::TYPE_ANY ) ), - 'type' => 'string', - ), - 'sanitize_callback' => array( $this, 'sanitize_subtypes' ), - ); - - return $query_params; - } - - /** - * Sanitizes the list of subtypes, to ensure only subtypes of the passed type are included. - * - * @since 3.3.0 - * - * @param string|array $subtypes One or more subtypes. - * @param WP_REST_Request $request Full details about the request. - * @param string $parameter Parameter name. - * @return array|WP_Error List of valid subtypes, or WP_Error object on failure. - */ - public function sanitize_subtypes( $subtypes, $request, $parameter ) { - $subtypes = wp_parse_slug_list( $subtypes ); - - $subtypes = rest_parse_request_arg( $subtypes, $request, $parameter ); - if ( is_wp_error( $subtypes ) ) { - return $subtypes; - } - - // 'any' overrides any other subtype. - if ( in_array( self::TYPE_ANY, $subtypes, true ) ) { - return array( self::TYPE_ANY ); - } - - $handler = $this->get_search_handler( $request ); - if ( is_wp_error( $handler ) ) { - return $handler; - } - - return array_intersect( $subtypes, $handler->get_subtypes() ); - } - - /** - * Gets the search handler to handle the current request. - * - * @since 3.3.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return WP_REST_Search_Handler|WP_Error Search handler for the request type, or WP_Error object on failure. - */ - protected function get_search_handler( $request ) { - $type = $request->get_param( self::PROP_TYPE ); - - if ( ! $type || ! isset( $this->search_handlers[ $type ] ) ) { - return new WP_Error( 'rest_search_invalid_type', __( 'Invalid type parameter.', 'gutenberg' ), array( 'status' => 400 ) ); - } - - return $this->search_handlers[ $type ]; - } -} diff --git a/lib/class-wp-rest-search-handler.php b/lib/class-wp-rest-search-handler.php deleted file mode 100644 index 6c5351d45b002..0000000000000 --- a/lib/class-wp-rest-search-handler.php +++ /dev/null @@ -1,96 +0,0 @@ -type; - } - - /** - * Gets the object subtypes managed by this search handler. - * - * @since 3.3.0 - * - * @return array Array of object subtype identifiers. - */ - public function get_subtypes() { - return $this->subtypes; - } - - /** - * Searches the object type content for a given search request. - * - * @since 3.3.0 - * - * @param WP_REST_Request $request Full REST request. - * @return array Associative array containing an `WP_REST_Search_Handler::RESULT_IDS` containing - * an array of found IDs and `WP_REST_Search_Handler::RESULT_TOTAL` containing the - * total count for the matching search results. - */ - abstract public function search_items( WP_REST_Request $request ); - - /** - * Prepares the search result for a given ID. - * - * @since 3.3.0 - * - * @param int $id Item ID. - * @param array $fields Fields to include for the item. - * @return array Associative array containing all fields for the item. - */ - abstract public function prepare_item( $id, array $fields ); - - /** - * Prepares links for the search result of a given ID. - * - * @since 3.3.0 - * - * @param int $id Item ID. - * @return array Links for the given item. - */ - abstract public function prepare_item_links( $id ); -} diff --git a/lib/class-wp-rest-themes-controller.php b/lib/class-wp-rest-themes-controller.php deleted file mode 100644 index b2ddf4e0e3910..0000000000000 --- a/lib/class-wp-rest-themes-controller.php +++ /dev/null @@ -1,237 +0,0 @@ -namespace = 'wp/v2'; - $this->rest_base = 'themes'; - } - - /** - * Registers the routes for the objects of the controller. - * - * @since 5.0.0 - * - * @see register_rest_route() - */ - public function register_routes() { - register_rest_route( - $this->namespace, - '/' . $this->rest_base, - array( - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => array( $this, 'get_items' ), - 'permission_callback' => array( $this, 'get_items_permissions_check' ), - 'args' => $this->get_collection_params(), - ), - 'schema' => array( $this, 'get_item_schema' ), - ) - ); - } - - /** - * Checks if a given request has access to read the theme. - * - * @since 5.0.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return true|WP_Error True if the request has read access for the item, otherwise WP_Error object. - */ - public function get_items_permissions_check( $request ) { - if ( ! is_user_logged_in() || ! current_user_can( 'edit_posts' ) ) { - return new WP_Error( 'rest_user_cannot_view', __( 'Sorry, you are not allowed to view themes.', 'gutenberg' ), array( 'status' => rest_authorization_required_code() ) ); - } - - return true; - } - - /** - * Retrieves a collection of themes. - * - * @since 5.0.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function get_items( $request ) { - // Retrieve the list of registered collection query parameters. - $registered = $this->get_collection_params(); - $themes = array(); - - if ( isset( $registered['status'], $request['status'] ) && in_array( 'active', $request['status'], true ) ) { - $active_theme = wp_get_theme(); - $active_theme = $this->prepare_item_for_response( $active_theme, $request ); - $themes[] = $this->prepare_response_for_collection( $active_theme ); - } - - $response = rest_ensure_response( $themes ); - - $response->header( 'X-WP-Total', count( $themes ) ); - $response->header( 'X-WP-TotalPages', count( $themes ) ); - - return $response; - } - - /** - * Prepares a single theme output for response. - * - * @since 5.0.0 - * - * @param WP_Theme $theme Theme object. - * @param WP_REST_Request $request Request object. - * @return WP_REST_Response Response object. - */ - public function prepare_item_for_response( $theme, $request ) { - $data = array(); - $fields = $this->get_fields_for_response( $request ); - - if ( in_array( 'theme_supports', $fields, true ) ) { - $formats = get_theme_support( 'post-formats' ); - $formats = is_array( $formats ) ? array_values( $formats[0] ) : array(); - $formats = array_merge( array( 'standard' ), $formats ); - $data['theme_supports']['formats'] = $formats; - - $data['theme_supports']['post-thumbnails'] = false; - $data['theme_supports']['responsive-embeds'] = (bool) get_theme_support( 'responsive-embeds' ); - $post_thumbnails = get_theme_support( 'post-thumbnails' ); - - if ( $post_thumbnails ) { - // $post_thumbnails can contain a nested array of post types. - // e.g. array( array( 'post', 'page' ) ). - $data['theme_supports']['post-thumbnails'] = is_array( $post_thumbnails ) ? $post_thumbnails[0] : true; - } - } - - $data = $this->add_additional_fields_to_object( $data, $request ); - - // Wrap the data in a response object. - $response = rest_ensure_response( $data ); - - /** - * Filters theme data returned from the REST API. - * - * @since 5.0.0 - * - * @param WP_REST_Response $response The response object. - * @param WP_Theme $theme Theme object used to create response. - * @param WP_REST_Request $request Request object. - */ - return apply_filters( 'rest_prepare_theme', $response, $theme, $request ); - } - - /** - * Retrieves the theme's schema, conforming to JSON Schema. - * - * @since 5.0.0 - * - * @return array Item schema data. - */ - public function get_item_schema() { - $schema = array( - '$schema' => 'http://json-schema.org/draft-04/schema#', - 'title' => 'theme', - 'type' => 'object', - 'properties' => array( - 'theme_supports' => array( - 'description' => __( 'Features supported by this theme.', 'gutenberg' ), - 'type' => 'array', - 'readonly' => true, - 'properties' => array( - 'formats' => array( - 'description' => __( 'Post formats supported.', 'gutenberg' ), - 'type' => 'array', - 'readonly' => true, - ), - 'post-thumbnails' => array( - 'description' => __( 'Whether the theme supports post thumbnails.', 'gutenberg' ), - 'type' => array( 'array', 'bool' ), - 'readonly' => true, - ), - 'responsive-embeds' => array( - 'description' => __( 'Whether the theme supports responsive embedded content.', 'gutenberg' ), - 'type' => 'bool', - 'readonly' => true, - ), - ), - ), - ), - ); - - return $this->add_additional_fields_schema( $schema ); - } - - /** - * Retrieves the search params for the themes collection. - * - * @since 5.0.0 - * - * @return array Collection parameters. - */ - public function get_collection_params() { - $query_params = parent::get_collection_params(); - - $query_params['status'] = array( - 'description' => __( 'Limit result set to themes assigned one or more statuses.', 'gutenberg' ), - 'type' => 'array', - 'items' => array( - 'enum' => array( 'active' ), - 'type' => 'string', - ), - 'required' => true, - 'sanitize_callback' => array( $this, 'sanitize_theme_status' ), - ); - - /** - * Filter collection parameters for the themes controller. - * - * @since 5.0.0 - * - * @param array $query_params JSON Schema-formatted collection parameters. - */ - return apply_filters( 'rest_themes_collection_params', $query_params ); - } - - /** - * Sanitizes and validates the list of theme status. - * - * @since 5.0.0 - * - * @param string|array $statuses One or more theme statuses. - * @param WP_REST_Request $request Full details about the request. - * @param string $parameter Additional parameter to pass to validation. - * @return array|WP_Error A list of valid statuses, otherwise WP_Error object. - */ - public function sanitize_theme_status( $statuses, $request, $parameter ) { - $statuses = wp_parse_slug_list( $statuses ); - - foreach ( $statuses as $status ) { - $result = rest_validate_request_arg( $status, $request, $parameter ); - - if ( is_wp_error( $result ) ) { - return $result; - } - } - - return $statuses; - } -} diff --git a/lib/load.php b/lib/load.php index 034b3c9e83ceb..8306f6f030f83 100644 --- a/lib/load.php +++ b/lib/load.php @@ -12,28 +12,6 @@ // These files only need to be loaded if within a rest server instance // which this class will exist if that is the case. if ( class_exists( 'WP_REST_Controller' ) ) { - if ( ! class_exists( 'WP_REST_Blocks_Controller' ) ) { - require dirname( __FILE__ ) . '/class-wp-rest-blocks-controller.php'; - } - if ( ! class_exists( 'WP_REST_Autosaves_Controller' ) ) { - require dirname( __FILE__ ) . '/class-wp-rest-autosaves-controller.php'; - } - if ( ! class_exists( 'WP_REST_Themes_Controller' ) ) { - require dirname( __FILE__ ) . '/class-wp-rest-themes-controller.php'; - } - if ( ! class_exists( 'WP_REST_Block_Renderer_Controller' ) ) { - require dirname( __FILE__ ) . '/class-wp-rest-block-renderer-controller.php'; - } - if ( ! class_exists( 'WP_REST_Search_Controller' ) ) { - require dirname( __FILE__ ) . '/class-wp-rest-search-controller.php'; - } - if ( ! class_exists( 'WP_REST_Search_Handler' ) ) { - require dirname( __FILE__ ) . '/class-wp-rest-search-handler.php'; - } - if ( ! class_exists( 'WP_REST_Post_Search_Handler' ) ) { - require dirname( __FILE__ ) . '/class-wp-rest-post-search-handler.php'; - } - require dirname( __FILE__ ) . '/rest-api.php'; } diff --git a/lib/rest-api.php b/lib/rest-api.php index 2baec1befdd19..616493a371219 100644 --- a/lib/rest-api.php +++ b/lib/rest-api.php @@ -14,42 +14,11 @@ * Registers the REST API routes needed by the Gutenberg editor. * * @since 2.8.0 + * @deprecated 5.0.0 */ function gutenberg_register_rest_routes() { - $controller = new WP_REST_Block_Renderer_Controller(); - $controller->register_routes(); - - /** - * Filters the search handlers to use in the REST search controller. - * - * @since 3.3.0 - * - * @param array $search_handlers List of search handlers to use in the controller. Each search - * handler instance must extend the `WP_REST_Search_Handler` class. - * Default is only a handler for posts. - */ - $search_handlers = apply_filters( 'wp_rest_search_handlers', array( new WP_REST_Post_Search_Handler() ) ); - - $controller = new WP_REST_Search_Controller( $search_handlers ); - $controller->register_routes(); - - foreach ( get_post_types( array( 'show_in_rest' => true ), 'objects' ) as $post_type ) { - $class = ! empty( $post_type->rest_controller_class ) ? $post_type->rest_controller_class : 'WP_REST_Posts_Controller'; - - // Check if the class exists and is a subclass of WP_REST_Controller. - if ( ! is_subclass_of( $class, 'WP_REST_Controller' ) ) { - continue; - } - - // Initialize the Autosaves controller. - $autosaves_controller = new WP_REST_Autosaves_Controller( $post_type->name ); - $autosaves_controller->register_routes(); - } - - $themes_controller = new WP_REST_Themes_Controller(); - $themes_controller->register_routes(); + _deprecated_function( __FUNCTION__, '5.0.0' ); } -add_action( 'rest_api_init', 'gutenberg_register_rest_routes' ); /** * Make sure oEmbed REST Requests apply the WP Embed security mechanism for WordPress embeds. @@ -120,105 +89,38 @@ function gutenberg_filter_oembed_result( $response, $handler, $request ) { * Used so private taxonomies are not displayed in the UI. * * @see https://core.trac.wordpress.org/ticket/42707 + * @deprecated 5.0.0 */ function gutenberg_add_taxonomy_visibility_field() { - register_rest_field( - 'taxonomy', - 'visibility', - array( - 'get_callback' => 'gutenberg_get_taxonomy_visibility_data', - 'schema' => array( - 'description' => __( 'The visibility settings for the taxonomy.', 'gutenberg' ), - 'type' => 'object', - 'context' => array( 'edit' ), - 'readonly' => true, - 'properties' => array( - 'public' => array( - 'description' => __( 'Whether a taxonomy is intended for use publicly either via the admin interface or by front-end users.', 'gutenberg' ), - 'type' => 'boolean', - ), - 'publicly_queryable' => array( - 'description' => __( 'Whether the taxonomy is publicly queryable.', 'gutenberg' ), - 'type' => 'boolean', - ), - 'show_ui' => array( - 'description' => __( 'Whether to generate a default UI for managing this taxonomy.', 'gutenberg' ), - 'type' => 'boolean', - ), - 'show_admin_column' => array( - 'description' => __( 'Whether to allow automatic creation of taxonomy columns on associated post-types table.', 'gutenberg' ), - 'type' => 'boolean', - ), - 'show_in_nav_menus' => array( - 'description' => __( 'Whether to make the taxonomy available for selection in navigation menus.', 'gutenberg' ), - 'type' => 'boolean', - ), - 'show_in_quick_edit' => array( - 'description' => __( 'Whether to show the taxonomy in the quick/bulk edit panel.', 'gutenberg' ), - 'type' => 'boolean', - ), - ), - ), - ) - ); + _deprecated_function( __FUNCTION__, '5.0.0' ); } /** * Gets taxonomy visibility property data. * * @see https://core.trac.wordpress.org/ticket/42707 + * @deprecated 5.0.0 * * @param array $object Taxonomy data from REST API. * @return array Array of taxonomy visibility data. */ function gutenberg_get_taxonomy_visibility_data( $object ) { - // Just return existing data for up-to-date Core. - if ( isset( $object['visibility'] ) ) { - return $object['visibility']; - } + _deprecated_function( __FUNCTION__, '5.0.0' ); - $taxonomy = get_taxonomy( $object['slug'] ); - - return array( - 'public' => $taxonomy->public, - 'publicly_queryable' => $taxonomy->publicly_queryable, - 'show_ui' => $taxonomy->show_ui, - 'show_admin_column' => $taxonomy->show_admin_column, - 'show_in_nav_menus' => $taxonomy->show_in_nav_menus, - 'show_in_quick_edit' => $taxonomy->show_ui, - ); + return isset( $object['visibility'] ) ? $object['visibility'] : array(); } -add_action( 'rest_api_init', 'gutenberg_add_taxonomy_visibility_field' ); - /** * Add a permalink template to posts in the post REST API response. * * @see https://core.trac.wordpress.org/ticket/45017 + * @deprecated 5.0.0 * * @param WP_REST_Response $response WP REST API response of a post. - * @param WP_Post $post The post being returned. - * @param WP_REST_Request $request WP REST API request. * @return WP_REST_Response Response containing the permalink_template. */ -function gutenberg_add_permalink_template_to_posts( $response, $post, $request ) { - if ( 'edit' !== $request['context'] ) { - return $response; - } - - $post_type_obj = get_post_type_object( $post->post_type ); - if ( ! is_post_type_viewable( $post_type_obj ) || ! $post_type_obj->public ) { - return $response; - } - - if ( ! function_exists( 'get_sample_permalink' ) ) { - require_once ABSPATH . '/wp-admin/includes/post.php'; - } - - $sample_permalink = get_sample_permalink( $post->ID, $post->post_title, '' ); - - $response->data['permalink_template'] = $sample_permalink[0]; - $response->data['generated_slug'] = $sample_permalink[1]; +function gutenberg_add_permalink_template_to_posts( $response ) { + _deprecated_function( __FUNCTION__, '5.0.0' ); return $response; } @@ -226,25 +128,14 @@ function gutenberg_add_permalink_template_to_posts( $response, $post, $request ) /** * Add the block format version to post content in the post REST API response. * - * @todo This will need to be registered to the schema too. - * * @see https://core.trac.wordpress.org/ticket/43887 + * @deprecated 5.0.0 * * @param WP_REST_Response $response WP REST API response of a post. - * @param WP_Post $post The post being returned. - * @param WP_REST_Request $request WP REST API request. * @return WP_REST_Response Response containing the block_format. */ -function gutenberg_add_block_format_to_post_content( $response, $post, $request ) { - if ( 'edit' !== $request['context'] ) { - return $response; - } - - $response_data = $response->get_data(); - if ( isset( $response_data['content'] ) && is_array( $response_data['content'] ) && isset( $response_data['content']['raw'] ) ) { - $response_data['content']['block_format'] = gutenberg_content_block_version( $response_data['content']['raw'] ); - $response->set_data( $response_data ); - } +function gutenberg_add_block_format_to_post_content( $response ) { + _deprecated_function( __FUNCTION__, '5.0.0' ); return $response; } @@ -253,100 +144,52 @@ function gutenberg_add_block_format_to_post_content( $response, $post, $request * Include target schema attributes to links, based on whether the user can. * * @see https://core.trac.wordpress.org/ticket/45014 + * @deprecated 5.0.0 * * @param WP_REST_Response $response WP REST API response of a post. - * @param WP_Post $post The post being returned. - * @param WP_REST_Request $request WP REST API request. * @return WP_REST_Response Response containing the new links. */ -function gutenberg_add_target_schema_to_links( $response, $post, $request ) { - $new_links = array(); - $orig_links = $response->get_links(); - $post_type = get_post_type_object( $post->post_type ); - $orig_href = ! empty( $orig_links['self'][0]['href'] ) ? $orig_links['self'][0]['href'] : null; - if ( 'edit' === $request['context'] && current_user_can( 'unfiltered_html' ) ) { - $new_links['https://api.w.org/action-unfiltered-html'] = array( - array( - 'title' => __( 'The current user can post HTML markup and JavaScript.', 'gutenberg' ), - 'href' => $orig_href, - 'targetSchema' => array( - 'type' => 'object', - 'properties' => array( - 'unfiltered_html' => array( - 'type' => 'boolean', - ), - ), - ), - ), - ); - } +function gutenberg_add_target_schema_to_links( $response ) { + _deprecated_function( __FUNCTION__, '5.0.0' ); - $response->add_links( $new_links ); return $response; } /** * Whenever a post type is registered, ensure we're hooked into it's WP REST API response. * + * @deprecated 5.0.0 + * * @param string $post_type The newly registered post type. * @return string That same post type. */ function gutenberg_register_post_prepare_functions( $post_type ) { - add_filter( "rest_prepare_{$post_type}", 'gutenberg_add_permalink_template_to_posts', 10, 3 ); - add_filter( "rest_prepare_{$post_type}", 'gutenberg_add_block_format_to_post_content', 10, 3 ); - add_filter( "rest_prepare_{$post_type}", 'gutenberg_add_target_schema_to_links', 10, 3 ); + _deprecated_function( __FUNCTION__, '5.0.0' ); + return $post_type; } -add_filter( 'registered_post_type', 'gutenberg_register_post_prepare_functions' ); - /** * Silence PHP Warnings and Errors in JSON requests * - * @todo This is a temporary measure until errors are properly silenced in REST API responses in core - * * @see https://core.trac.wordpress.org/ticket/44534 + * @deprecated 5.0.0 */ function gutenberg_silence_rest_errors() { - - if ( ( isset( $_SERVER['CONTENT_TYPE'] ) && 'application/json' === $_SERVER['CONTENT_TYPE'] ) || - ( isset( $_SERVER['HTTP_ACCEPT'] ) && strpos( $_SERVER['HTTP_ACCEPT'], 'application/json' ) !== false ) ) { - // @codingStandardsIgnoreStart - @ini_set( 'display_errors', 0 ); - // @codingStandardsIgnoreEnd - } - + _deprecated_function( __FUNCTION__, '5.0.0' ); } /** * Include additional labels for registered post types * * @see https://core.trac.wordpress.org/ticket/45101 + * @deprecated 5.0.0 * - * @param array $args Arguments supplied to register_post_type(). - * @param string $post_type Post type key. + * @param array $args Arguments supplied to register_post_type(). * @return array Arguments supplied to register_post_type() */ -function gutenberg_filter_post_type_labels( $args, $post_type ) { - $registered_labels = ( empty( $args['labels'] ) ) ? array() : $args['labels']; - if ( is_post_type_hierarchical( $post_type ) ) { - $labels = array( - 'item_published' => __( 'Page published.', 'gutenberg' ), - 'item_published_privately' => __( 'Page published privately.', 'gutenberg' ), - 'item_reverted_to_draft' => __( 'Page reverted to draft.', 'gutenberg' ), - 'item_scheduled' => __( 'Page scheduled.', 'gutenberg' ), - 'item_updated' => __( 'Page updated.', 'gutenberg' ), - ); - } else { - $labels = array( - 'item_published' => __( 'Post published.', 'gutenberg' ), - 'item_published_privately' => __( 'Post published privately.', 'gutenberg' ), - 'item_reverted_to_draft' => __( 'Post reverted to draft.', 'gutenberg' ), - 'item_scheduled' => __( 'Post scheduled.', 'gutenberg' ), - 'item_updated' => __( 'Post updated.', 'gutenberg' ), - ); - } - $args['labels'] = array_merge( $labels, $registered_labels ); +function gutenberg_filter_post_type_labels( $args ) { + _deprecated_function( __FUNCTION__, '5.0.0' ); + return $args; } -add_filter( 'register_post_type_args', 'gutenberg_filter_post_type_labels', 10, 2 ); diff --git a/phpunit/bootstrap.php b/phpunit/bootstrap.php index 80d806ee4452a..6043dd1bbd037 100644 --- a/phpunit/bootstrap.php +++ b/phpunit/bootstrap.php @@ -36,7 +36,6 @@ function _manually_load_plugin() { // Require dummy block type class for testing. require_once dirname( __FILE__ ) . '/class-wp-dummy-block-type.php'; - require_once dirname( __FILE__ ) . '/class-wp-rest-dummy-search-handler.php'; } tests_add_filter( 'muplugins_loaded', '_manually_load_plugin' ); diff --git a/phpunit/class-gutenberg-rest-api-test.php b/phpunit/class-gutenberg-rest-api-test.php deleted file mode 100644 index 293dc7fed3526..0000000000000 --- a/phpunit/class-gutenberg-rest-api-test.php +++ /dev/null @@ -1,427 +0,0 @@ -administrator = $this->factory->user->create( - array( - 'role' => 'administrator', - ) - ); - $this->author = $this->factory->user->create( - array( - 'role' => 'author', - ) - ); - $this->editor = $this->factory->user->create( - array( - 'role' => 'editor', - ) - ); - $this->contributor = $this->factory->user->create( - array( - 'role' => 'contributor', - ) - ); - $this->subscriber = $this->factory->user->create( - array( - 'role' => 'subscriber', - 'display_name' => 'subscriber', - 'user_email' => 'subscriber@example.com', - ) - ); - } - - function tearDown() { - parent::tearDown(); - } - - /** - * Should return an extra visibility field on response when in edit context. - */ - function test_visibility_field() { - $request = new WP_REST_Request( 'GET', '/wp/v2/taxonomies/category' ); - $request->set_param( 'context', 'edit' ); - - $permitted_users = array( - $this->administrator, - $this->editor, - $this->author, - ); - - foreach ( $permitted_users as $user ) { - wp_set_current_user( $user ); - - $response = rest_do_request( $request ); - $result = $response->get_data(); - - $this->assertTrue( isset( $result['visibility'] ) ); - $this->assertInternalType( 'array', $result['visibility'] ); - $this->assertArrayHasKey( 'public', $result['visibility'] ); - $this->assertArrayHasKey( 'publicly_queryable', $result['visibility'] ); - $this->assertArrayHasKey( 'show_ui', $result['visibility'] ); - $this->assertArrayHasKey( 'show_admin_column', $result['visibility'] ); - $this->assertArrayHasKey( 'show_in_nav_menus', $result['visibility'] ); - $this->assertArrayHasKey( 'show_in_quick_edit', $result['visibility'] ); - } - } - - /** - * Should not return an extra visibility field without context set. - */ - function test_visibility_field_without_context() { - $request = new WP_REST_Request( 'GET', '/wp/v2/taxonomies/category' ); - $response = rest_do_request( $request ); - - $result = $response->get_data(); - - $this->assertFalse( isset( $result['visibility'] ) ); - } - - /** - * Should return an extra viewable field on response when in edit context. - */ - function test_viewable_field() { - wp_set_current_user( $this->administrator ); - $request = new WP_REST_Request( 'GET', '/wp/v2/types/post' ); - $request->set_param( 'context', 'edit' ); - $response = rest_do_request( $request ); - $result = $response->get_data(); - $this->assertTrue( isset( $result['viewable'] ) ); - $this->assertTrue( $result['viewable'] ); - } - - /** - * Should not return viewable field without context set. - */ - function test_viewable_field_without_context() { - $request = new WP_REST_Request( 'GET', '/wp/v2/types/post' ); - $response = rest_do_request( $request ); - $result = $response->get_data(); - $this->assertFalse( isset( $result['viewable'] ) ); - } - - /** - * Only returns wp:action-unfiltered_html when current user can use unfiltered HTML. - * See https://codex.wordpress.org/Roles_and_Capabilities#Capability_vs._Role_Table - */ - function test_link_unfiltered_html() { - $post_id = $this->factory->post->create(); - $check_key = 'https://api.w.org/action-unfiltered-html'; - // admins can in a single site, but can't in a multisite. - wp_set_current_user( $this->administrator ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $post_id ); - $request->set_param( 'context', 'edit' ); - $response = rest_do_request( $request ); - $links = $response->get_links(); - if ( is_multisite() ) { - $this->assertFalse( isset( $links[ $check_key ] ) ); - } else { - $this->assertTrue( isset( $links[ $check_key ] ) ); - } - // authors can't. - wp_set_current_user( $this->author ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $post_id ); - $request->set_param( 'context', 'edit' ); - $response = rest_do_request( $request ); - $links = $response->get_links(); - $this->assertFalse( isset( $links[ $check_key ] ) ); - // editors can in a single site, but can't in a multisite. - wp_set_current_user( $this->editor ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $post_id ); - $request->set_param( 'context', 'edit' ); - $response = rest_do_request( $request ); - $links = $response->get_links(); - if ( is_multisite() ) { - $this->assertFalse( isset( $links[ $check_key ] ) ); - } else { - $this->assertTrue( isset( $links[ $check_key ] ) ); - } - // contributors can't. - wp_set_current_user( $this->contributor ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $post_id ); - $request->set_param( 'context', 'edit' ); - $response = rest_do_request( $request ); - $links = $response->get_links(); - $this->assertFalse( isset( $links[ $check_key ] ) ); - } - - /** - * Only returns wp:action-assign-author when current user can assign author. - */ - function test_link_assign_author_only_appears_for_editor() { - $post_id = $this->factory->post->create(); - $check_key = 'https://api.w.org/action-assign-author'; - // authors cannot assign author. - wp_set_current_user( $this->author ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $post_id ); - $request->set_param( 'context', 'edit' ); - $response = rest_do_request( $request ); - $links = $response->get_links(); - $this->assertFalse( isset( $links[ $check_key ] ) ); - // editors can assign author. - wp_set_current_user( $this->editor ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $post_id ); - $request->set_param( 'context', 'edit' ); - $response = rest_do_request( $request ); - $links = $response->get_links(); - $this->assertTrue( isset( $links[ $check_key ] ) ); - // editors can assign author but not included for context != edit. - wp_set_current_user( $this->editor ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $post_id ); - $request->set_param( 'context', 'view' ); - $response = rest_do_request( $request ); - $links = $response->get_links(); - $this->assertFalse( isset( $links[ $check_key ] ) ); - } - - /** - * Only returns wp:action-publish when current user can publish. - */ - function test_link_publish_only_appears_for_author() { - $post_id = $this->factory->post->create( - array( - 'post_author' => $this->author, - ) - ); - $check_key = 'https://api.w.org/action-publish'; - // contributors cannot sticky. - wp_set_current_user( $this->contributor ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $post_id ); - $request->set_param( 'context', 'edit' ); - $response = rest_do_request( $request ); - $links = $response->get_links(); - $this->assertFalse( isset( $links[ $check_key ] ) ); - // authors can publish. - wp_set_current_user( $this->author ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $post_id ); - $request->set_param( 'context', 'edit' ); - $response = rest_do_request( $request ); - $links = $response->get_links(); - $this->assertTrue( isset( $links[ $check_key ] ) ); - // authors can publish but not included for context != edit. - wp_set_current_user( $this->author ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $post_id ); - $request->set_param( 'context', 'view' ); - $response = rest_do_request( $request ); - $links = $response->get_links(); - $this->assertFalse( isset( $links[ $check_key ] ) ); - } - - /** - * Only returns wp:action-sticky when current user can sticky. - */ - function test_link_sticky_only_appears_for_editor() { - $post_id = $this->factory->post->create(); - $check_key = 'https://api.w.org/action-sticky'; - // authors cannot sticky. - wp_set_current_user( $this->author ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $post_id ); - $request->set_param( 'context', 'edit' ); - $response = rest_do_request( $request ); - $links = $response->get_links(); - $this->assertFalse( isset( $links[ $check_key ] ) ); - // editors can sticky. - wp_set_current_user( $this->editor ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $post_id ); - $request->set_param( 'context', 'edit' ); - $response = rest_do_request( $request ); - $links = $response->get_links(); - $this->assertTrue( isset( $links[ $check_key ] ) ); - // editors can sticky but not included for context != edit. - wp_set_current_user( $this->editor ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $post_id ); - $request->set_param( 'context', 'view' ); - $response = rest_do_request( $request ); - $links = $response->get_links(); - $this->assertFalse( isset( $links[ $check_key ] ) ); - } - - /** - * Only returns term-related actions when current user can do so. - */ - function test_link_term_management_per_user() { - $contributor_post = $this->factory->post->create( - array( - 'post_author' => $this->contributor, - 'post_status' => 'draft', - ) - ); - $author_post = $this->factory->post->create( - array( - 'post_author' => $this->author, - ) - ); - $create_tags = 'https://api.w.org/action-create-tags'; - $assign_tags = 'https://api.w.org/action-assign-tags'; - $create_categories = 'https://api.w.org/action-create-categories'; - $assign_categories = 'https://api.w.org/action-assign-categories'; - // Contributors can create and assign tags, but only assign categories. - wp_set_current_user( $this->contributor ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $contributor_post ); - $request->set_param( 'context', 'edit' ); - $response = rest_do_request( $request ); - $links = $response->get_links(); - $this->assertTrue( isset( $links[ $create_tags ] ) ); - $this->assertTrue( isset( $links[ $assign_tags ] ) ); - $this->assertFalse( isset( $links[ $create_categories ] ) ); - $this->assertTrue( isset( $links[ $assign_categories ] ) ); - // Authors can create and assign tags, but only assign categories. - wp_set_current_user( $this->author ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $author_post ); - $request->set_param( 'context', 'edit' ); - $response = rest_do_request( $request ); - $links = $response->get_links(); - $this->assertTrue( isset( $links[ $create_tags ] ) ); - $this->assertTrue( isset( $links[ $assign_tags ] ) ); - $this->assertFalse( isset( $links[ $create_categories ] ) ); - $this->assertTrue( isset( $links[ $assign_categories ] ) ); - // Editors can do everything. - wp_set_current_user( $this->editor ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $author_post ); - $request->set_param( 'context', 'edit' ); - $response = rest_do_request( $request ); - $links = $response->get_links(); - $this->assertTrue( isset( $links[ $create_tags ] ) ); - $this->assertTrue( isset( $links[ $assign_tags ] ) ); - $this->assertTrue( isset( $links[ $create_categories ] ) ); - $this->assertTrue( isset( $links[ $assign_categories ] ) ); - } - - public function test_get_taxonomies_context_edit() { - wp_set_current_user( $this->contributor ); - $request = new WP_REST_Request( 'GET', '/wp/v2/taxonomies' ); - $request->set_param( 'context', 'edit' ); - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( 200, $response->get_status() ); - $data = $response->get_data(); - $taxonomies = array(); - foreach ( get_taxonomies( '', 'objects' ) as $taxonomy ) { - if ( ! empty( $taxonomy->show_in_rest ) ) { - $taxonomies[] = $taxonomy; - } - } - $this->assertEquals( count( $taxonomies ), count( $data ) ); - $this->assertEquals( 'Categories', $data['category']['name'] ); - $this->assertEquals( 'category', $data['category']['slug'] ); - $this->assertEquals( true, $data['category']['hierarchical'] ); - $this->assertEquals( 'Tags', $data['post_tag']['name'] ); - $this->assertEquals( 'post_tag', $data['post_tag']['slug'] ); - $this->assertEquals( false, $data['post_tag']['hierarchical'] ); - $this->assertEquals( 'tags', $data['post_tag']['rest_base'] ); - } - - public function test_get_taxonomies_invalid_permission_for_context() { - wp_set_current_user( $this->subscriber ); - $request = new WP_REST_Request( 'GET', '/wp/v2/taxonomies' ); - $request->set_param( 'context', 'edit' ); - $response = rest_get_server()->dispatch( $request ); - $this->assertErrorResponse( 'rest_cannot_view', $response, 403 ); - } - - public function test_create_category_incorrect_permissions_author() { - wp_set_current_user( $this->author ); - $request = new WP_REST_Request( 'POST', '/wp/v2/categories' ); - $request->set_param( 'name', 'Incorrect permissions' ); - $response = rest_get_server()->dispatch( $request ); - $this->assertErrorResponse( 'rest_cannot_create', $response, 403 ); - } - - public function test_create_category_editor() { - wp_set_current_user( $this->editor ); - $request = new WP_REST_Request( 'POST', '/wp/v2/categories' ); - $request->set_param( 'name', 'My Awesome Term' ); - $request->set_param( 'description', 'This term is so awesome.' ); - $request->set_param( 'slug', 'so-awesome' ); - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( 201, $response->get_status() ); - $headers = $response->get_headers(); - $data = $response->get_data(); - $this->assertContains( '/wp/v2/categories/' . $data['id'], $headers['Location'] ); - $this->assertEquals( 'My Awesome Term', $data['name'] ); - $this->assertEquals( 'This term is so awesome.', $data['description'] ); - $this->assertEquals( 'so-awesome', $data['slug'] ); - } - - public function test_create_tag_incorrect_permissions_subscriber() { - wp_set_current_user( $this->subscriber ); - $request = new WP_REST_Request( 'POST', '/wp/v2/tags' ); - $request->set_param( 'name', 'Incorrect permissions' ); - $response = rest_get_server()->dispatch( $request ); - $this->assertErrorResponse( 'rest_cannot_create', $response, 403 ); - } - - public function test_create_tag_contributor() { - wp_set_current_user( $this->contributor ); - $request = new WP_REST_Request( 'POST', '/wp/v2/tags' ); - $request->set_param( 'name', 'My Awesome Term' ); - $request->set_param( 'description', 'This term is so awesome.' ); - $request->set_param( 'slug', 'so-awesome' ); - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( 201, $response->get_status() ); - $headers = $response->get_headers(); - $data = $response->get_data(); - $this->assertContains( '/wp/v2/tags/' . $data['id'], $headers['Location'] ); - $this->assertEquals( 'My Awesome Term', $data['name'] ); - $this->assertEquals( 'This term is so awesome.', $data['description'] ); - $this->assertEquals( 'so-awesome', $data['slug'] ); - } - - public function test_get_items_unbounded_per_page() { - wp_set_current_user( $this->author ); - $request = new WP_REST_Request( 'GET', '/wp/v2/users' ); - $request->set_param( 'per_page', '-1' ); - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( 400, $response->get_status() ); - } - - public function test_get_categories_unbounded_per_page() { - wp_set_current_user( $this->author ); - $this->factory->category->create(); - $request = new WP_REST_Request( 'GET', '/wp/v2/categories' ); - $request->set_param( 'per_page', '-1' ); - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( 400, $response->get_status() ); - } - - public function test_get_pages_unbounded_per_page() { - wp_set_current_user( $this->author ); - $this->factory->post->create( array( 'post_type' => 'page' ) ); - $request = new WP_REST_Request( 'GET', '/wp/v2/pages' ); - $request->set_param( 'per_page', '-1' ); - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( 400, $response->get_status() ); - } - - public function test_get_post_links_predecessor_version() { - $post_id = $this->factory->post->create(); - wp_update_post( - array( - 'post_content' => 'This content is marvelous.', - 'ID' => $post_id, - ) - ); - $revisions = wp_get_post_revisions( $post_id ); - $revision_1 = array_pop( $revisions ); - - $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d', $post_id ) ); - $response = rest_get_server()->dispatch( $request ); - - $links = $response->get_links(); - - $this->assertEquals( rest_url( '/wp/v2/posts/' . $post_id . '/revisions' ), $links['version-history'][0]['href'] ); - $this->assertEquals( 1, $links['version-history'][0]['attributes']['count'] ); - - $this->assertEquals( rest_url( '/wp/v2/posts/' . $post_id . '/revisions/' . $revision_1->ID ), $links['predecessor-version'][0]['href'] ); - $this->assertEquals( $revision_1->ID, $links['predecessor-version'][0]['attributes']['id'] ); - } -} diff --git a/phpunit/class-rest-autosaves-controller-test.php b/phpunit/class-rest-autosaves-controller-test.php deleted file mode 100644 index 10d2b23ef9706..0000000000000 --- a/phpunit/class-rest-autosaves-controller-test.php +++ /dev/null @@ -1,605 +0,0 @@ - 'Post Title', - 'content' => 'Post content', - 'excerpt' => 'Post excerpt', - 'name' => 'test', - 'author' => get_current_user_id(), - ); - - return wp_parse_args( $args, $defaults ); - } - - protected function check_create_autosave_response( $response ) { - $this->assertNotInstanceOf( 'WP_Error', $response ); - $response = rest_ensure_response( $response ); - $data = $response->get_data(); - - $this->assertArrayHasKey( 'content', $data ); - $this->assertArrayHasKey( 'excerpt', $data ); - $this->assertArrayHasKey( 'title', $data ); - } - - public static function wpSetUpBeforeClass( $factory ) { - self::$post_id = $factory->post->create(); - self::$page_id = $factory->post->create( array( 'post_type' => 'page' ) ); - - self::$editor_id = $factory->user->create( - array( - 'role' => 'editor', - ) - ); - self::$contributor_id = $factory->user->create( - array( - 'role' => 'contributor', - ) - ); - - wp_set_current_user( self::$editor_id ); - - // Create an autosave. - self::$autosave_post_id = wp_create_post_autosave( - array( - 'post_content' => 'This content is better.', - 'post_ID' => self::$post_id, - 'post_type' => 'post', - ) - ); - - self::$autosave_page_id = wp_create_post_autosave( - array( - 'post_content' => 'This content is better.', - 'post_ID' => self::$page_id, - 'post_type' => 'post', - ) - ); - - self::$draft_page_id = $factory->post->create( - array( - 'post_type' => 'page', - 'post_status' => 'draft', - ) - ); - self::$parent_page_id = $factory->post->create( - array( - 'post_type' => 'page', - ) - ); - self::$child_page_id = $factory->post->create( - array( - 'post_type' => 'page', - 'post_parent' => self::$parent_page_id, - ) - ); - self::$child_draft_page_id = $factory->post->create( - array( - 'post_type' => 'page', - 'post_parent' => self::$parent_page_id, - // The "update post" behavior of the autosave endpoint only occurs - // when saving a draft/auto-draft authored by the current user. - 'post_status' => 'draft', - 'post_author' => self::$editor_id, - ) - ); - } - - public static function wpTearDownAfterClass() { - // Also deletes revisions. - wp_delete_post( self::$post_id, true ); - wp_delete_post( self::$page_id, true ); - - self::delete_user( self::$editor_id ); - self::delete_user( self::$contributor_id ); - } - - public function setUp() { - parent::setUp(); - wp_set_current_user( self::$editor_id ); - - $this->post_autosave = wp_get_post_autosave( self::$post_id ); - } - - public function test_register_routes() { - $routes = rest_get_server()->get_routes(); - $this->assertArrayHasKey( '/wp/v2/posts/(?P[\d]+)/autosaves', $routes ); - $this->assertArrayHasKey( '/wp/v2/posts/(?P[\d]+)/autosaves/(?P[\d]+)', $routes ); - $this->assertArrayHasKey( '/wp/v2/pages/(?P[\d]+)/autosaves', $routes ); - $this->assertArrayHasKey( '/wp/v2/pages/(?P[\d]+)/autosaves/(?P[\d]+)', $routes ); - } - - public function test_context_param() { - - // Collection. - $request = new WP_REST_Request( 'OPTIONS', '/wp/v2/posts/' . self::$post_id . '/autosaves' ); - $response = rest_get_server()->dispatch( $request ); - $data = $response->get_data(); - $this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] ); - $this->assertEqualSets( array( 'view', 'edit', 'embed' ), $data['endpoints'][0]['args']['context']['enum'] ); - - // Single. - $request = new WP_REST_Request( 'OPTIONS', '/wp/v2/posts/' . self::$post_id . '/autosaves/' . self::$autosave_post_id ); - $response = rest_get_server()->dispatch( $request ); - $data = $response->get_data(); - $this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] ); - $this->assertEqualSets( array( 'view', 'edit', 'embed' ), $data['endpoints'][0]['args']['context']['enum'] ); - } - - public function test_registered_query_params() { - $request = new WP_REST_Request( 'OPTIONS', '/wp/v2/posts/' . self::$post_id . '/autosaves' ); - $response = $this->server->dispatch( $request ); - $data = $response->get_data(); - $keys = array_keys( $data['endpoints'][0]['args'] ); - sort( $keys ); - $this->assertEquals( - array( - 'context', - 'parent', - ), - $keys - ); - } - - public function test_get_items() { - wp_set_current_user( self::$editor_id ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/autosaves' ); - $response = rest_get_server()->dispatch( $request ); - $data = $response->get_data(); - $this->assertEquals( 200, $response->get_status() ); - $this->assertCount( 1, $data ); - - $this->assertEquals( self::$autosave_post_id, $data[0]['id'] ); - - $this->check_get_autosave_response( $data[0], $this->post_autosave ); - } - - public function test_get_items_no_permission() { - wp_set_current_user( 0 ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/autosaves' ); - $response = rest_get_server()->dispatch( $request ); - $this->assertErrorResponse( 'rest_cannot_read', $response, 401 ); - wp_set_current_user( self::$contributor_id ); - $response = rest_get_server()->dispatch( $request ); - $this->assertErrorResponse( 'rest_cannot_read', $response, 403 ); - } - - public function test_get_items_missing_parent() { - wp_set_current_user( self::$editor_id ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER . '/autosaves' ); - $response = rest_get_server()->dispatch( $request ); - $this->assertErrorResponse( 'rest_post_invalid_parent', $response, 404 ); - } - - public function test_get_items_invalid_parent_post_type() { - wp_set_current_user( self::$editor_id ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$page_id . '/autosaves' ); - $response = rest_get_server()->dispatch( $request ); - $this->assertErrorResponse( 'rest_post_invalid_parent', $response, 404 ); - } - - public function test_get_item() { - wp_set_current_user( self::$editor_id ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/autosaves/' . self::$autosave_post_id ); - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( 200, $response->get_status() ); - $data = $response->get_data(); - - $this->check_get_autosave_response( $response, $this->post_autosave ); - $fields = array( - 'author', - 'date', - 'date_gmt', - 'modified', - 'modified_gmt', - 'guid', - 'id', - 'parent', - 'slug', - 'title', - 'excerpt', - 'content', - ); - $this->assertEqualSets( $fields, array_keys( $data ) ); - $this->assertSame( self::$editor_id, $data['author'] ); - } - - public function test_get_item_embed_context() { - wp_set_current_user( self::$editor_id ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/autosaves/' . self::$autosave_post_id ); - $request->set_param( 'context', 'embed' ); - $response = rest_get_server()->dispatch( $request ); - $fields = array( - 'author', - 'date', - 'id', - 'parent', - 'slug', - 'title', - 'excerpt', - ); - $data = $response->get_data(); - $this->assertEqualSets( $fields, array_keys( $data ) ); - } - - public function test_get_item_no_permission() { - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/autosaves/' . self::$autosave_post_id ); - wp_set_current_user( self::$contributor_id ); - $response = rest_get_server()->dispatch( $request ); - $this->assertErrorResponse( 'rest_cannot_read', $response, 403 ); - } - - public function test_get_item_missing_parent() { - wp_set_current_user( self::$editor_id ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER . '/autosaves/' . self::$autosave_post_id ); - $response = rest_get_server()->dispatch( $request ); - $this->assertErrorResponse( 'rest_post_invalid_parent', $response, 404 ); - - } - - public function test_get_item_invalid_parent_post_type() { - wp_set_current_user( self::$editor_id ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$page_id . '/autosaves' ); - $response = rest_get_server()->dispatch( $request ); - $this->assertErrorResponse( 'rest_post_invalid_parent', $response, 404 ); - } - - public function test_delete_item() { - // Doesn't exist. - } - - public function test_prepare_item() { - wp_set_current_user( self::$editor_id ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/autosaves/' . self::$autosave_post_id ); - $response = rest_get_server()->dispatch( $request ); - $this->assertEquals( 200, $response->get_status() ); - $this->check_get_autosave_response( $response, $this->post_autosave ); - } - - public function test_get_item_schema() { - $request = new WP_REST_Request( 'OPTIONS', '/wp/v2/posts/' . self::$post_id . '/autosaves' ); - $response = rest_get_server()->dispatch( $request ); - $data = $response->get_data(); - $properties = $data['schema']['properties']; - $this->assertEquals( 13, count( $properties ) ); - $this->assertArrayHasKey( 'author', $properties ); - $this->assertArrayHasKey( 'content', $properties ); - $this->assertArrayHasKey( 'date', $properties ); - $this->assertArrayHasKey( 'date_gmt', $properties ); - $this->assertArrayHasKey( 'excerpt', $properties ); - $this->assertArrayHasKey( 'guid', $properties ); - $this->assertArrayHasKey( 'id', $properties ); - $this->assertArrayHasKey( 'modified', $properties ); - $this->assertArrayHasKey( 'modified_gmt', $properties ); - $this->assertArrayHasKey( 'parent', $properties ); - $this->assertArrayHasKey( 'slug', $properties ); - $this->assertArrayHasKey( 'title', $properties ); - $this->assertArrayHasKey( 'preview_link', $properties ); - } - - public function test_create_item() { - wp_set_current_user( self::$editor_id ); - - $request = new WP_REST_Request( 'POST', '/wp/v2/posts/' . self::$post_id . '/autosaves' ); - $request->add_header( 'content-type', 'application/x-www-form-urlencoded' ); - - $params = $this->set_post_data( - array( - 'id' => self::$post_id, - ) - ); - $request->set_body_params( $params ); - $response = rest_get_server()->dispatch( $request ); - - $this->check_create_autosave_response( $response ); - } - - public function test_update_item() { - wp_set_current_user( self::$editor_id ); - $request = new WP_REST_Request( 'POST', '/wp/v2/posts/' . self::$post_id . '/autosaves' ); - $request->add_header( 'content-type', 'application/x-www-form-urlencoded' ); - - $params = $this->set_post_data( - array( - 'id' => self::$post_id, - 'author' => self::$contributor_id, - ) - ); - - $request->set_body_params( $params ); - $response = rest_get_server()->dispatch( $request ); - - $this->check_create_autosave_response( $response ); - } - - public function test_update_item_nopriv() { - wp_set_current_user( self::$contributor_id ); - - $request = new WP_REST_Request( 'POST', '/wp/v2/posts/' . self::$post_id . '/autosaves' ); - $request->add_header( 'content-type', 'application/x-www-form-urlencoded' ); - - $params = $this->set_post_data( - array( - 'id' => self::$post_id, - 'author' => self::$editor_id, - ) - ); - - $request->set_body_params( $params ); - $response = rest_get_server()->dispatch( $request ); - - $this->assertErrorResponse( 'rest_cannot_edit', $response, 403 ); - } - - public function test_rest_autosave_published_post() { - wp_set_current_user( self::$editor_id ); - - $request = new WP_REST_Request( 'POST', '/wp/v2/posts/' . self::$post_id . '/autosaves' ); - $request->add_header( 'content-type', 'application/json' ); - - $current_post = get_post( self::$post_id ); - - $autosave_data = $this->set_post_data( - array( - 'id' => self::$post_id, - 'content' => 'Updated post \ content', - 'excerpt' => $current_post->post_excerpt, - 'title' => $current_post->post_title, - ) - ); - - $request->set_body( wp_json_encode( $autosave_data ) ); - $response = rest_get_server()->dispatch( $request ); - $new_data = $response->get_data(); - - $this->assertEquals( $current_post->ID, $new_data['parent'] ); - $this->assertEquals( $current_post->post_title, $new_data['title']['raw'] ); - $this->assertEquals( $current_post->post_excerpt, $new_data['excerpt']['raw'] ); - - // Updated post_content. - $this->assertNotEquals( $current_post->post_content, $new_data['content']['raw'] ); - - $autosave_post = wp_get_post_autosave( self::$post_id ); - $this->assertEquals( $autosave_data['title'], $autosave_post->post_title ); - $this->assertEquals( $autosave_data['content'], $autosave_post->post_content ); - $this->assertEquals( $autosave_data['excerpt'], $autosave_post->post_excerpt ); - } - - public function test_rest_autosave_draft_post_same_author() { - wp_set_current_user( self::$editor_id ); - - $post_data = array( - 'post_content' => 'Test post content', - 'post_title' => 'Test post title', - 'post_excerpt' => 'Test post excerpt', - ); - $post_id = wp_insert_post( $post_data ); - - $autosave_data = array( - 'id' => $post_id, - 'content' => 'Updated post \ content', - 'title' => 'Updated post title', - ); - - $request = new WP_REST_Request( 'POST', '/wp/v2/posts/' . self::$post_id . '/autosaves' ); - $request->add_header( 'content-type', 'application/json' ); - $request->set_body( wp_json_encode( $autosave_data ) ); - - $response = rest_get_server()->dispatch( $request ); - $new_data = $response->get_data(); - $post = get_post( $post_id ); - - $this->assertEquals( $post_id, $new_data['id'] ); - // The draft post should be updated. - $this->assertEquals( $autosave_data['content'], $new_data['content']['raw'] ); - $this->assertEquals( $autosave_data['title'], $new_data['title']['raw'] ); - $this->assertEquals( $autosave_data['content'], $post->post_content ); - $this->assertEquals( $autosave_data['title'], $post->post_title ); - - // Not updated. - $this->assertEquals( $post_data['post_excerpt'], $post->post_excerpt ); - - wp_delete_post( $post_id ); - } - - public function test_rest_autosave_draft_post_different_author() { - wp_set_current_user( self::$editor_id ); - - $post_data = array( - 'post_content' => 'Test post content', - 'post_title' => 'Test post title', - 'post_excerpt' => 'Test post excerpt', - 'post_author' => self::$editor_id + 1, - ); - $post_id = wp_insert_post( $post_data ); - - $autosave_data = array( - 'id' => $post_id, - 'content' => 'Updated post content', - 'excerpt' => $post_data['post_excerpt'], - 'title' => $post_data['post_title'], - ); - - $request = new WP_REST_Request( 'POST', '/wp/v2/posts/' . self::$post_id . '/autosaves' ); - $request->add_header( 'content-type', 'application/json' ); - $request->set_body( wp_json_encode( $autosave_data ) ); - - $response = rest_get_server()->dispatch( $request ); - $new_data = $response->get_data(); - $current_post = get_post( $post_id ); - - $this->assertEquals( $current_post->ID, $new_data['parent'] ); - - // The draft post shouldn't change. - $this->assertEquals( $current_post->post_title, $post_data['post_title'] ); - $this->assertEquals( $current_post->post_content, $post_data['post_content'] ); - $this->assertEquals( $current_post->post_excerpt, $post_data['post_excerpt'] ); - - $autosave_post = wp_get_post_autosave( $post_id ); - - // No changes. - $this->assertEquals( $current_post->post_title, $autosave_post->post_title ); - $this->assertEquals( $current_post->post_excerpt, $autosave_post->post_excerpt ); - - // Has changes. - $this->assertEquals( $autosave_data['content'], $autosave_post->post_content ); - - wp_delete_post( $post_id ); - } - - public function test_get_additional_field_registration() { - $schema = array( - 'type' => 'integer', - 'description' => 'Some integer of mine', - 'enum' => array( 1, 2, 3, 4 ), - 'context' => array( 'view', 'edit' ), - ); - - register_rest_field( - 'post-revision', - 'my_custom_int', - array( - 'schema' => $schema, - 'get_callback' => array( $this, 'additional_field_get_callback' ), - 'update_callback' => array( $this, 'additional_field_update_callback' ), - ) - ); - - $request = new WP_REST_Request( 'OPTIONS', '/wp/v2/posts/' . self::$post_id . '/autosaves' ); - - $response = rest_get_server()->dispatch( $request ); - $data = $response->get_data(); - - $this->assertArrayHasKey( 'my_custom_int', $data['schema']['properties'] ); - $this->assertEquals( $schema, $data['schema']['properties']['my_custom_int'] ); - - wp_set_current_user( 1 ); - - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/autosaves/' . self::$autosave_post_id ); - - $response = rest_get_server()->dispatch( $request ); - $this->assertArrayHasKey( 'my_custom_int', $response->data ); - - global $wp_rest_additional_fields; - $wp_rest_additional_fields = array(); - } - - public function additional_field_get_callback( $object ) { - return get_post_meta( $object['id'], 'my_custom_int', true ); - } - - public function additional_field_update_callback( $value, $post ) { - update_post_meta( $post->ID, 'my_custom_int', $value ); - } - - protected function check_get_autosave_response( $response, $autosave ) { - if ( $response instanceof WP_REST_Response ) { - $links = $response->get_links(); - $response = $response->get_data(); - } else { - $this->assertArrayHasKey( '_links', $response ); - $links = $response['_links']; - } - - $this->assertEquals( $autosave->post_author, $response['author'] ); - - $rendered_content = apply_filters( 'the_content', $autosave->post_content ); - $this->assertEquals( $rendered_content, $response['content']['rendered'] ); - - $this->assertEquals( mysql_to_rfc3339( $autosave->post_date ), $response['date'] ); //@codingStandardsIgnoreLine - $this->assertEquals( mysql_to_rfc3339( $autosave->post_date_gmt ), $response['date_gmt'] ); //@codingStandardsIgnoreLine - - $rendered_guid = apply_filters( 'get_the_guid', $autosave->guid, $autosave->ID ); - $this->assertEquals( $rendered_guid, $response['guid']['rendered'] ); - - $this->assertEquals( $autosave->ID, $response['id'] ); - $this->assertEquals( mysql_to_rfc3339( $autosave->post_modified ), $response['modified'] ); //@codingStandardsIgnoreLine - $this->assertEquals( mysql_to_rfc3339( $autosave->post_modified_gmt ), $response['modified_gmt'] ); //@codingStandardsIgnoreLine - $this->assertEquals( $autosave->post_name, $response['slug'] ); - - $rendered_title = get_the_title( $autosave->ID ); - $this->assertEquals( $rendered_title, $response['title']['rendered'] ); - - $parent = get_post( $autosave->post_parent ); - $parent_controller = new WP_REST_Posts_Controller( $parent->post_type ); - $parent_object = get_post_type_object( $parent->post_type ); - $parent_base = ! empty( $parent_object->rest_base ) ? $parent_object->rest_base : $parent_object->name; - $this->assertEquals( rest_url( '/wp/v2/' . $parent_base . '/' . $autosave->post_parent ), $links['parent'][0]['href'] ); - } - - public function test_get_item_sets_up_postdata() { - wp_set_current_user( self::$editor_id ); - $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/autosaves/' . self::$autosave_post_id ); - rest_get_server()->dispatch( $request ); - - $post = get_post(); - $parent_post_id = wp_is_post_revision( $post->ID ); - - $this->assertEquals( $post->ID, self::$autosave_post_id ); - $this->assertEquals( $parent_post_id, self::$post_id ); - } - - public function test_update_item_draft_page_with_parent() { - wp_set_current_user( self::$editor_id ); - $request = new WP_REST_Request( 'POST', '/wp/v2/pages/' . self::$child_draft_page_id . '/autosaves' ); - $request->add_header( 'content-type', 'application/x-www-form-urlencoded' ); - - $params = $this->set_post_data( - array( - 'id' => self::$child_draft_page_id, - 'author' => self::$editor_id, - ) - ); - - $request->set_body_params( $params ); - $response = rest_get_server()->dispatch( $request ); - $data = $response->get_data(); - - $this->assertEquals( self::$child_draft_page_id, $data['id'] ); - $this->assertEquals( self::$parent_page_id, $data['parent'] ); - } - - public function test_schema_validation_is_applied() { - wp_set_current_user( self::$editor_id ); - - $request = new WP_REST_Request( 'POST', '/wp/v2/pages/' . self::$draft_page_id . '/autosaves' ); - $request->add_header( 'content-type', 'application/x-www-form-urlencoded' ); - - $params = $this->set_post_data( - array( - 'id' => self::$draft_page_id, - 'comment_status' => 'garbage', - ) - ); - - $request->set_body_params( $params ); - - $response = rest_get_server()->dispatch( $request ); - $this->assertNotEquals( 'garbage', get_post( self::$draft_page_id )->comment_status ); - } -} diff --git a/phpunit/class-wp-rest-dummy-search-handler.php b/phpunit/class-wp-rest-dummy-search-handler.php deleted file mode 100644 index e6cc5b2f475f0..0000000000000 --- a/phpunit/class-wp-rest-dummy-search-handler.php +++ /dev/null @@ -1,90 +0,0 @@ -type = 'dummy'; - - $this->subtypes = array( 'dummy_first_type', 'dummy_second_type' ); - - $this->items = array(); - for ( $i = 1; $i <= $amount; $i++ ) { - $subtype = $i > $amount / 2 ? 'dummy_second_type' : 'dummy_first_type'; - - $this->items[ $i ] = (object) array( - 'dummy_id' => $i, - 'dummy_title' => sprintf( 'Title %d', $i ), - 'dummy_url' => sprintf( home_url( '/dummies/%d' ), $i ), - 'dummy_type' => $subtype, - ); - } - } - - public function search_items( WP_REST_Request $request ) { - $subtypes = $request[ WP_REST_Search_Controller::PROP_SUBTYPE ]; - if ( in_array( WP_REST_Search_Controller::TYPE_ANY, $subtypes, true ) ) { - $subtypes = $this->subtypes; - } - - $results = array(); - foreach ( $subtypes as $subtype ) { - $results = array_merge( $results, wp_list_filter( array_values( $this->items ), array( 'dummy_type' => $subtype ) ) ); - } - - $results = wp_list_sort( $results, 'dummy_id', 'DESC' ); - - $number = (int) $request['per_page']; - $offset = (int) $request['per_page'] * ( (int) $request['page'] - 1 ); - - $total = count( $results ); - - $results = array_slice( $results, $offset, $number ); - - return array( - self::RESULT_IDS => wp_list_pluck( $results, 'dummy_id' ), - self::RESULT_TOTAL => $total, - ); - } - - public function prepare_item( $id, array $fields ) { - $dummy = $this->items[ $id ]; - - $data = array(); - - if ( in_array( WP_REST_Search_Controller::PROP_ID, $fields, true ) ) { - $data[ WP_REST_Search_Controller::PROP_ID ] = (int) $dummy->dummy_id; - } - - if ( in_array( WP_REST_Search_Controller::PROP_TITLE, $fields, true ) ) { - $data[ WP_REST_Search_Controller::PROP_TITLE ] = $dummy->dummy_title; - } - - if ( in_array( WP_REST_Search_Controller::PROP_URL, $fields, true ) ) { - $data[ WP_REST_Search_Controller::PROP_URL ] = $dummy->dummy_url; - } - - if ( in_array( WP_REST_Search_Controller::PROP_TYPE, $fields, true ) ) { - $data[ WP_REST_Search_Controller::PROP_TYPE ] = $this->type; - } - - if ( in_array( WP_REST_Search_Controller::PROP_SUBTYPE, $fields, true ) ) { - $data[ WP_REST_Search_Controller::PROP_SUBTYPE ] = $dummy->dummy_type; - } - - return $data; - } - - public function prepare_item_links( $id ) { - return array(); - } -} diff --git a/phpunit/class-wp-rest-themes-controller-test.php b/phpunit/class-wp-rest-themes-controller-test.php deleted file mode 100644 index 553799a7beb0b..0000000000000 --- a/phpunit/class-wp-rest-themes-controller-test.php +++ /dev/null @@ -1,344 +0,0 @@ -set_param( 'status', 'active' ); - - return rest_get_server()->dispatch( $request ); - } - - /** - * Check that common properties are included in a response. - * - * @since 5.0.0 - * - * @param WP_REST_Response $response Current REST API response. - */ - protected function check_get_theme_response( $response ) { - if ( $response instanceof WP_REST_Response ) { - $headers = $response->get_headers(); - $response = $response->get_data(); - } else { - $headers = array(); - } - - $this->assertArrayHasKey( 'X-WP-Total', $headers ); - $this->assertEquals( 1, $headers['X-WP-Total'] ); - $this->assertArrayHasKey( 'X-WP-TotalPages', $headers ); - $this->assertEquals( 1, $headers['X-WP-TotalPages'] ); - } - - /** - * Set up class test fixtures. - * - * @since 5.0.0 - * - * @param WP_UnitTest_Factory $factory WordPress unit test factory. - */ - public static function wpSetUpBeforeClass( $factory ) { - self::$subscriber_id = $factory->user->create( - array( - 'role' => 'subscriber', - ) - ); - self::$contributor_id = $factory->user->create( - array( - 'role' => 'contributor', - ) - ); - self::$current_theme = wp_get_theme(); - - wp_set_current_user( self::$contributor_id ); - } - - /** - * Clean up test fixtures. - * - * @since 5.0.0 - */ - public static function wpTearDownAfterClass() { - self::delete_user( self::$subscriber_id ); - self::delete_user( self::$contributor_id ); - } - - /** - * Set up each test method. - * - * @since 5.0.0 - */ - public function setUp() { - parent::setUp(); - - wp_set_current_user( self::$contributor_id ); - } - - /** - * Theme routes should be registered correctly. - */ - public function test_register_routes() { - $routes = rest_get_server()->get_routes(); - $this->assertArrayHasKey( self::$themes_route, $routes ); - } - - /** - * Test retrieving a collection of themes. - */ - public function test_get_items() { - $response = self::perform_active_theme_request(); - - $this->assertEquals( 200, $response->get_status() ); - $data = $response->get_data(); - - $this->check_get_theme_response( $response ); - $fields = array( - 'theme_supports', - ); - $this->assertEqualSets( $fields, array_keys( $data[0] ) ); - } - - /** - * An error should be returned when the user does not have the edit_posts capability. - */ - public function test_get_items_no_permission() { - wp_set_current_user( self::$subscriber_id ); - $response = self::perform_active_theme_request(); - $this->assertErrorResponse( 'rest_user_cannot_view', $response, 403 ); - } - - /** - * Test an item is prepared for the response. - */ - public function test_prepare_item() { - $response = self::perform_active_theme_request(); - $this->assertEquals( 200, $response->get_status() ); - $this->check_get_theme_response( $response ); - } - - /** - * Verify the theme schema. - */ - public function test_get_item_schema() { - $response = self::perform_active_theme_request( 'OPTIONS' ); - $data = $response->get_data(); - $properties = $data['schema']['properties']; - $this->assertEquals( 1, count( $properties ) ); - $this->assertArrayHasKey( 'theme_supports', $properties ); - - $this->assertEquals( 3, count( $properties['theme_supports']['properties'] ) ); - $this->assertArrayHasKey( 'formats', $properties['theme_supports']['properties'] ); - $this->assertArrayHasKey( 'post-thumbnails', $properties['theme_supports']['properties'] ); - $this->assertArrayHasKey( 'responsive-embeds', $properties['theme_supports']['properties'] ); - } - - /** - * Should include relevant data in the 'theme_supports' key. - */ - public function test_theme_supports_formats() { - remove_theme_support( 'post-formats' ); - $response = self::perform_active_theme_request(); - $result = $response->get_data(); - $this->assertTrue( isset( $result[0]['theme_supports'] ) ); - $this->assertTrue( isset( $result[0]['theme_supports']['formats'] ) ); - $this->assertSame( array( 'standard' ), $result[0]['theme_supports']['formats'] ); - } - - /** - * Test when a theme only supports some post formats. - */ - public function test_theme_supports_formats_non_default() { - add_theme_support( 'post-formats', array( 'aside', 'video' ) ); - $response = self::perform_active_theme_request(); - $result = $response->get_data(); - $this->assertTrue( isset( $result[0]['theme_supports'] ) ); - $this->assertTrue( isset( $result[0]['theme_supports']['formats'] ) ); - $this->assertSame( array( 'standard', 'aside', 'video' ), $result[0]['theme_supports']['formats'] ); - } - - /** - * Test when a theme does not support responsive embeds. - */ - public function test_theme_supports_responsive_embeds_false() { - remove_theme_support( 'responsive-embeds' ); - $response = self::perform_active_theme_request(); - - $result = $response->get_data(); - $this->assertTrue( isset( $result[0]['theme_supports'] ) ); - $this->assertTrue( isset( $result[0]['theme_supports']['responsive-embeds'] ) ); - $this->assertFalse( $result[0]['theme_supports']['responsive-embeds'] ); - } - - /** - * Test when a theme supports responsive embeds. - */ - public function test_theme_supports_responsive_embeds_true() { - remove_theme_support( 'responsive-embeds' ); - add_theme_support( 'responsive-embeds' ); - $response = self::perform_active_theme_request(); - $result = $response->get_data(); - $this->assertTrue( isset( $result[0]['theme_supports'] ) ); - $this->assertTrue( $result[0]['theme_supports']['responsive-embeds'] ); - } - - /** - * Test when a theme does not support post thumbnails. - */ - public function test_theme_supports_post_thumbnails_false() { - remove_theme_support( 'post-thumbnails' ); - $response = self::perform_active_theme_request(); - - $result = $response->get_data(); - $this->assertTrue( isset( $result[0]['theme_supports'] ) ); - $this->assertTrue( isset( $result[0]['theme_supports']['post-thumbnails'] ) ); - $this->assertFalse( $result[0]['theme_supports']['post-thumbnails'] ); - } - - /** - * Test when a theme supports all post thumbnails. - */ - public function test_theme_supports_post_thumbnails_true() { - remove_theme_support( 'post-thumbnails' ); - add_theme_support( 'post-thumbnails' ); - $response = self::perform_active_theme_request(); - $result = $response->get_data(); - $this->assertTrue( isset( $result[0]['theme_supports'] ) ); - $this->assertTrue( $result[0]['theme_supports']['post-thumbnails'] ); - } - - /** - * Test when a theme only supports post thumbnails for certain post types. - */ - public function test_theme_supports_post_thumbnails_array() { - remove_theme_support( 'post-thumbnails' ); - add_theme_support( 'post-thumbnails', array( 'post' ) ); - $response = self::perform_active_theme_request(); - $result = $response->get_data(); - $this->assertTrue( isset( $result[0]['theme_supports'] ) ); - $this->assertEquals( array( 'post' ), $result[0]['theme_supports']['post-thumbnails'] ); - } - - /** - * It should be possible to register custom fields to the endpoint. - */ - public function test_get_additional_field_registration() { - $schema = array( - 'type' => 'integer', - 'description' => 'Some integer of mine', - 'enum' => array( 1, 2, 3, 4 ), - ); - - register_rest_field( - 'theme', - 'my_custom_int', - array( - 'schema' => $schema, - 'get_callback' => array( $this, 'additional_field_get_callback' ), - ) - ); - - $response = self::perform_active_theme_request( 'OPTIONS' ); - $data = $response->get_data(); - - $this->assertArrayHasKey( 'my_custom_int', $data['schema']['properties'] ); - $this->assertEquals( $schema, $data['schema']['properties']['my_custom_int'] ); - - $response = self::perform_active_theme_request( 'GET' ); - $data = $response->get_data(); - $this->assertArrayHasKey( 'my_custom_int', $data[0] ); - $this->assertSame( 2, $data[0]['my_custom_int'] ); - - global $wp_rest_additional_fields; - $wp_rest_additional_fields = array(); - } - - /** - * Return a value for the custom field. - * - * @since 5.0.0 - * - * @param array $theme Theme data array. - * @return int Additional field value. - */ - public function additional_field_get_callback( $theme ) { - return 2; - } - - /** - * The create_item() method does not exist for themes. - */ - public function test_create_item() {} - - /** - * The update_item() method does not exist for themes. - */ - public function test_update_item() {} - - /** - * The get_item() method does not exist for themes. - */ - public function test_get_item() {} - - /** - * The delete_item() method does not exist for themes. - */ - public function test_delete_item() {} - - /** - * Context is not supported for themes. - */ - public function test_context_param() {} -}