From e606bc36c1f175d51e5784e1a966ede78200b63d Mon Sep 17 00:00:00 2001 From: Joe Hoyle Date: Wed, 23 Nov 2016 02:46:42 +0000 Subject: [PATCH] REST API: Allow unsetting of page templates in update requests. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sending a request to update a page with the template property set to an empty string resulted in an error because “” was not a valid value in the enum. Props lucasstark, swissspidy. Fixes #38877. git-svn-id: https://develop.svn.wordpress.org/trunk@39343 602fd350-edb4-49c9-b593-d223f7449a82 --- .../class-wp-rest-posts-controller.php | 2 +- tests/phpunit/includes/spy-rest-server.php | 15 ++++ .../tests/rest-api/rest-pages-controller.php | 5 ++ .../tests/rest-api/rest-posts-controller.php | 80 +++++++++++++++++++ 4 files changed, 101 insertions(+), 1 deletion(-) diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php index ac463e6313..162c56bf84 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php @@ -1928,7 +1928,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller { $schema['properties']['template'] = array( 'description' => __( 'The theme file to use to display the object.' ), 'type' => 'string', - 'enum' => array_keys( wp_get_theme()->get_page_templates( null, $this->post_type ) ), + 'enum' => array_merge( array_keys( wp_get_theme()->get_page_templates( null, $this->post_type ) ), array( '' ) ), 'context' => array( 'view', 'edit' ), ); diff --git a/tests/phpunit/includes/spy-rest-server.php b/tests/phpunit/includes/spy-rest-server.php index 4ba9017c0f..58e3c3b521 100644 --- a/tests/phpunit/includes/spy-rest-server.php +++ b/tests/phpunit/includes/spy-rest-server.php @@ -5,6 +5,7 @@ class Spy_REST_Server extends WP_REST_Server { public $sent_headers = array(); public $sent_body = ''; public $last_request = null; + public $override_by_default = false; /** * Get the raw $endpoints data from the server @@ -41,6 +42,20 @@ class Spy_REST_Server extends WP_REST_Server { return parent::dispatch( $request ); } + /** + * Override the register_route method so we can re-register routes internally if needed. + * + * @param string $namespace Namespace. + * @param string $route The REST route. + * @param array $route_args Route arguments. + * @param bool $override Optional. Whether the route should be overridden if it already exists. + * Default false. Also set $GLOBALS['wp_rest_server']->override_by_default = true + * to set overrides when you don't have access to the caller context. + */ + public function register_route( $namespace, $route, $route_args, $override = false ) { + parent::register_route( $namespace, $route, $route_args, $override || $this->override_by_default ); + } + public function serve_request( $path = null ) { ob_start(); diff --git a/tests/phpunit/tests/rest-api/rest-pages-controller.php b/tests/phpunit/tests/rest-api/rest-pages-controller.php index b74d01c716..450cd5eb00 100644 --- a/tests/phpunit/tests/rest-api/rest-pages-controller.php +++ b/tests/phpunit/tests/rest-api/rest-pages-controller.php @@ -27,6 +27,11 @@ class WP_Test_REST_Pages_Controller extends WP_Test_REST_Post_Type_Controller_Te parent::setUp(); $this->has_setup_template = false; add_filter( 'theme_page_templates', array( $this, 'filter_theme_page_templates' ) ); + // reregister the route as we now have a template available. + $GLOBALS['wp_rest_server']->override_by_default = true; + $controller = new WP_REST_Posts_Controller( 'page' ); + $controller->register_routes(); + $GLOBALS['wp_rest_server']->override_by_default = false; } public function test_register_routes() { diff --git a/tests/phpunit/tests/rest-api/rest-posts-controller.php b/tests/phpunit/tests/rest-api/rest-posts-controller.php index 26af946a5a..526c3906c1 100644 --- a/tests/phpunit/tests/rest-api/rest-posts-controller.php +++ b/tests/phpunit/tests/rest-api/rest-posts-controller.php @@ -1032,6 +1032,12 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te wp_set_current_user( self::$editor_id ); add_filter( 'theme_post_templates', array( $this, 'filter_theme_post_templates' ) ); + // reregister the route as we now have a template available. + $GLOBALS['wp_rest_server']->override_by_default = true; + $controller = new WP_REST_Posts_Controller( 'post' ); + $controller->register_routes(); + $GLOBALS['wp_rest_server']->override_by_default = false; + $request = new WP_REST_Request( 'POST', '/wp/v2/posts' ); $params = $this->set_post_data( array( 'template' => 'post-my-test-template.php', @@ -1061,6 +1067,24 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te $request->set_body_params( $params ); $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); + } + + /** + * @ticket 38877 + */ + public function test_create_item_with_template_none() { + wp_set_current_user( self::$editor_id ); + add_filter( 'theme_post_templates', array( $this, 'filter_theme_post_templates' ) ); + update_post_meta( self::$post_id, '_wp_page_template', 'post-my-test-template.php' ); + + $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', self::$post_id ) ); + $params = $this->set_post_data( array( + 'template' => '', + ) ); + $request->set_body_params( $params ); + $response = $this->server->dispatch( $request ); + $data = $response->get_data(); $post_template = get_page_template_slug( get_post( $data['id'] ) ); @@ -2055,6 +2079,62 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te $this->assertErrorResponse( 'rest_cannot_assign_term', $response, 403 ); } + /** + * @ticket 38698 + */ + public function test_update_item_with_template() { + wp_set_current_user( self::$editor_id ); + add_filter( 'theme_post_templates', array( $this, 'filter_theme_post_templates' ) ); + + // reregister the route as we now have a template available. + $GLOBALS['wp_rest_server']->override_by_default = true; + $controller = new WP_REST_Posts_Controller( 'post' ); + $controller->register_routes(); + $GLOBALS['wp_rest_server']->override_by_default = false; + + $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', self::$post_id ) ); + $params = $this->set_post_data( array( + 'template' => 'post-my-test-template.php', + ) ); + $request->set_body_params( $params ); + $response = $this->server->dispatch( $request ); + + $data = $response->get_data(); + $post_template = get_page_template_slug( get_post( $data['id'] ) ); + + $this->assertEquals( 'post-my-test-template.php', $data['template'] ); + $this->assertEquals( 'post-my-test-template.php', $post_template ); + } + + /** + * @ticket 38877 + */ + public function test_update_item_with_template_none() { + wp_set_current_user( self::$editor_id ); + add_filter( 'theme_post_templates', array( $this, 'filter_theme_post_templates' ) ); + update_post_meta( self::$post_id, '_wp_page_template', 'post-my-test-template.php' ); + + // reregister the route as we now have a template available. + $GLOBALS['wp_rest_server']->override_by_default = true; + $controller = new WP_REST_Posts_Controller( 'post' ); + $controller->register_routes(); + $GLOBALS['wp_rest_server']->override_by_default = false; + + $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', self::$post_id ) ); + $params = $this->set_post_data( array( + 'template' => '', + ) ); + $request->set_body_params( $params ); + $response = $this->server->dispatch( $request ); + + $data = $response->get_data(); + $post_template = get_page_template_slug( get_post( $data['id'] ) ); + + $this->assertEquals( '', $data['template'] ); + $this->assertEquals( '', $post_template ); + } + + public function verify_post_roundtrip( $input = array(), $expected_output = array() ) { // Create the post $request = new WP_REST_Request( 'POST', '/wp/v2/posts' );