Ticket #43316: 43316.6.diff
File 43316.6.diff, 56.8 KB (added by , 7 years ago) |
---|
-
src/wp-includes/rest-api.php
diff --git a/src/wp-includes/rest-api.php b/src/wp-includes/rest-api.php index 0cce9fa62f..51e5e6f1a3 100644
a b function create_initial_rest_routes() { 192 192 if ( post_type_supports( $post_type->name, 'revisions' ) ) { 193 193 $revisions_controller = new WP_REST_Revisions_Controller( $post_type->name ); 194 194 $revisions_controller->register_routes(); 195 $controller = new WP_REST_Autosaves_Controller( $post_type->name ); 196 $controller->register_routes(); 195 197 } 196 198 } 197 199 -
new file src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php
diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php new file mode 100644 index 0000000000..4b9036415d
- + 1 <?php 2 /** 3 * REST API: WP_REST_Autosaves_Controller class. 4 * 5 * @package WordPress 6 * @subpackage REST_API 7 * @since 5.0.0 8 */ 9 10 /** 11 * Core class used to access autosaves via the REST API. 12 * 13 * @since 5.0.0 14 * 15 * @see WP_REST_Controller 16 */ 17 class WP_REST_Autosaves_Controller extends WP_REST_Revisions_Controller { 18 19 /** 20 * Parent post type. 21 * 22 * @since 5.0.0 23 * @var string 24 */ 25 private $parent_post_type; 26 27 /** 28 * Parent controller. 29 * 30 * @since 5.0.0 31 * @var WP_REST_Controller 32 */ 33 private $parent_controller; 34 35 /** 36 * Parent controller. 37 * 38 * @since 5.0.0 39 * @var WP_REST_Controller 40 */ 41 private $revision_controller; 42 43 /** 44 * The base of the parent controller's route. 45 * 46 * @since 5.0.0 47 * @var string 48 */ 49 private $parent_base; 50 51 /** 52 * Constructor. 53 * 54 * @since 5.0.0 55 * 56 * @param string $parent_post_type Post type of the parent. 57 */ 58 public function __construct( $parent_post_type ) { 59 $this->parent_post_type = $parent_post_type; 60 $this->parent_controller = new WP_REST_Posts_Controller( $parent_post_type ); 61 $this->revision_controller = new WP_REST_Revisions_Controller( $parent_post_type ); 62 $this->rest_namespace = 'wp/v2'; 63 $this->rest_base = 'autosaves'; 64 $post_type_object = get_post_type_object( $parent_post_type ); 65 $this->parent_base = ! empty( $post_type_object->rest_base ) ? $post_type_object->rest_base : $post_type_object->name; 66 } 67 68 /**o 69 * Registers routes for autosaves. 70 * 71 * @since 5.0.0 72 * 73 * @see register_rest_route() 74 */ 75 public function register_routes() { 76 register_rest_route( 77 $this->rest_namespace, '/' . $this->parent_base . '/(?P<parent>[\d]+)/' . $this->rest_base, array( 78 'args' => array( 79 'parent' => array( 80 'description' => __( 'The ID for the parent of the object.', 'gutenberg' ), 81 'type' => 'integer', 82 ), 83 ), 84 array( 85 'methods' => WP_REST_Server::READABLE, 86 'callback' => array( $this, 'get_items' ), 87 'permission_callback' => array( $this->revision_controller, 'get_items_permissions_check' ), 88 'args' => $this->get_collection_params(), 89 ), 90 array( 91 'methods' => WP_REST_Server::CREATABLE, 92 'callback' => array( $this, 'create_item' ), 93 'permission_callback' => array( $this->parent_controller, 'create_item_permissions_check' ), 94 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ), 95 ), 96 'schema' => array( $this, 'get_public_item_schema' ), 97 ) 98 ); 99 100 register_rest_route( 101 $this->rest_namespace, '/' . $this->parent_base . '/(?P<parent>[\d]+)/' . $this->rest_base . '/(?P<id>[\d]+)', array( 102 'args' => array( 103 'parent' => array( 104 'description' => __( 'The ID for the parent of the object.', 'gutenberg' ), 105 'type' => 'integer', 106 ), 107 'id' => array( 108 'description' => __( 'Unique identifier for the object.', 'gutenberg' ), 109 'type' => 'integer', 110 ), 111 ), 112 array( 113 'methods' => WP_REST_Server::READABLE, 114 'callback' => array( $this, 'get_item' ), 115 'permission_callback' => array( $this->revision_controller, 'get_item_permissions_check' ), 116 'args' => array( 117 'context' => $this->get_context_param( array( 'default' => 'view' ) ), 118 ), 119 ), 120 array( 121 'methods' => WP_REST_Server::DELETABLE, 122 'callback' => array( $this, 'delete_item' ), 123 'permission_callback' => array( $this->revision_controller, 'delete_item_permissions_check' ), 124 'args' => array( 125 'force' => array( 126 'type' => 'boolean', 127 'default' => false, 128 'description' => __( 'Required to be true, as autosaves do not support trashing.', 'gutenberg' ), 129 ), 130 ), 131 ), 132 array( 133 'methods' => WP_REST_Server::CREATABLE, 134 'callback' => array( $this, 'create_item' ), 135 'permission_callback' => array( $this->parent_controller, 'create_item_permissions_check' ), 136 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ), 137 ), 138 'schema' => array( $this, 'get_public_item_schema' ), 139 ) 140 ); 141 142 } 143 144 /** 145 * Get the parent post, if the ID is valid. 146 * 147 * @since 4.7.2 148 * 149 * @param int $id Supplied ID. 150 * @return WP_Post|WP_Error Post object if ID is valid, WP_Error otherwise. 151 */ 152 protected function get_parent( $parent ) { 153 return $this->revision_controller->get_parent( $parent ); 154 } 155 /** 156 * Creates a single autosave. 157 * 158 * @since 5.0.0 159 * 160 * @param WP_REST_Request $request Full details about the request. 161 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. 162 */ 163 public function create_item( $request ) { 164 165 // Map new fields onto the existing post data. 166 $parent = $this->get_parent( $request->get_param( 'parent' ) ); 167 $prepared_post = $this->parent_controller->prepare_item_for_database( $request ); 168 $prepared_post->ID = $parent->ID; 169 170 // If the parent post a draft, autosaving updates it and does not create a revision. 171 if ( 'draft' === $parent->post_status ) { 172 173 define( 'DOING_AUTOSAVE', true ); 174 $autosave_id = wp_update_post( (array) $prepared_post, true ); 175 176 if ( ! is_wp_error( $autosave_id ) ) { 177 $post = get_post( $autosave_id ); 178 } 179 } else { 180 181 // Non-draft posts - update the post, creating an autosave. 182 $autosave_id = $this->create_post_autosave( (array) $prepared_post ); 183 $post = get_post( $autosave_id ); 184 } 185 186 $request->set_param( 'context', 'edit' ); 187 188 $response = $this->prepare_item_for_response( $post, $request ); 189 $response = rest_ensure_response( $response ); 190 191 $response->set_status( 201 ); 192 $response->header( 'Location', rest_url( sprintf( '%s/%s/%d', $this->rest_namespace, $this->rest_base, $autosave_id ) ) ); 193 194 return $response; 195 } 196 197 /** 198 * Update an autosave, if the ID is valid. 199 * 200 * @since 5.0.0 201 * 202 * @param WP_REST_Request $request Full data about the request. 203 * @return WP_Post|WP_Error Revision post object if ID is valid, WP_Error otherwise. 204 */ 205 public function update_item( $request ) { 206 $parent = $request->get_param( 'parent' ); 207 $id = $request->get_param( 'id' ); 208 $error = new WP_Error( 'rest_post_invalid_id', __( 'Invalid autosave ID.', 'gutenberg' ), array( 'status' => 404 ) ); 209 if ( (int) $parent <= 0 ) { 210 return $error; 211 } 212 213 $prepared_post = $this->parent_controller->prepare_item_for_database( $request ); 214 $prepared_post->ID = $id; 215 $post_id = wp_update_post( (array) $prepared_post ); 216 $post = get_post( $post_id ); 217 $fields_update = $this->update_additional_fields_for_object( $post, $request ); 218 219 if ( is_wp_error( $fields_update ) ) { 220 return $fields_update; 221 } 222 223 $request->set_param( 'context', 'edit' ); 224 225 $response = $this->prepare_item_for_response( $post, $request ); 226 227 return rest_ensure_response( $response ); 228 } 229 /** 230 * Get the autosave, if the ID is valid. 231 * 232 * @since 5.0.0 233 * 234 * @param WP_REST_Request $request Full data about the request. 235 * @return WP_Post|WP_Error Revision post object if ID is valid, WP_Error otherwise. 236 */ 237 public function get_item( $request ) { 238 $parent = $request->get_param( 'parent' ); 239 $error = new WP_Error( 'rest_post_invalid_id', __( 'Invalid autosave ID.', 'gutenberg' ), array( 'status' => 404 ) ); 240 if ( (int) $parent <= 0 ) { 241 return $error; 242 } 243 $autosave = wp_get_post_autosave( (int) $parent ); 244 245 if ( empty( $autosave ) || empty( $autosave->ID ) || 'revision' !== $autosave->post_type ) { 246 return $error; 247 } 248 $autosave->post_parent = $parent; 249 $response = $this->prepare_item_for_response( $autosave, $request ); 250 251 return $response; 252 } 253 254 /** 255 * Gets a collection of autosaves using wp_get_post_autosave. 256 * 257 * Contains the user's autosave, for empty if it doesn't exist. 258 * 259 * @since 5.0.0 260 * 261 * @param WP_REST_Request $request Full data about the request. 262 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. 263 */ 264 public function get_items( $request ) { 265 $parent = $this->get_parent( $request->get_param( 'parent' ) ); 266 if ( is_wp_error( $parent ) ) { 267 return $parent; 268 } 269 270 $autosave = wp_get_post_autosave( $request->get_param( 'parent' ) ); 271 272 if ( ! $autosave ) { 273 return array(); 274 } 275 276 $response = array(); 277 $data = $this->prepare_item_for_response( $autosave, $request ); 278 $response[] = $this->prepare_response_for_collection( $data ); 279 280 return rest_ensure_response( $response ); 281 } 282 283 284 /** 285 * Retrieves the autosave's schema, conforming to JSON Schema. 286 * 287 * @since 5.0.0 288 * 289 * @return array Item schema data. 290 */ 291 public function get_item_schema() { 292 return $this->revision_controller->get_item_schema(); 293 } 294 295 /** 296 * Creates autosave data for the specified post from $_POST data. 297 * 298 * From wp-admin/post.php. 299 * 300 * @since 2.6.0 301 * 302 * @param mixed $post_data Associative array containing the post data or int post ID. 303 * @return mixed The autosave revision ID. WP_Error or 0 on error. 304 */ 305 public function create_post_autosave( $post_data ) { 306 307 $post_id = (int) $post_data['ID']; 308 $post_author = get_current_user_id(); 309 310 // Store one autosave per author. If there is already an autosave, overwrite it. 311 $old_autosave = wp_get_post_autosave( $post_id, $post_author ); 312 if ( $old_autosave ) { 313 $new_autosave = _wp_post_revision_data( $post_data, true ); 314 $new_autosave['ID'] = $old_autosave->ID; 315 $new_autosave['post_author'] = $post_author; 316 317 // If the new autosave has the same content as the post, delete the autosave. 318 $post = get_post( $post_id ); 319 $autosave_is_different = false; 320 foreach ( array_intersect( array_keys( $new_autosave ), array_keys( _wp_post_revision_fields( $post ) ) ) as $field ) { 321 if ( normalize_whitespace( $new_autosave[ $field ] ) != normalize_whitespace( $post->$field ) ) { 322 $autosave_is_different = true; 323 break; 324 } 325 } 326 327 if ( ! $autosave_is_different ) { 328 wp_delete_post_revision( $old_autosave->ID ); 329 return 0; 330 } 331 332 /** 333 * This filter is documented in wp-admin/post.php. 334 */ 335 do_action( 'wp_creating_autosave', $new_autosave ); 336 337 return wp_update_post( $new_autosave ); 338 } 339 340 // _wp_put_post_revision() expects unescaped. 341 $post_data = wp_unslash( $post_data ); 342 343 // Otherwise create the new autosave as a special post revision. 344 return _wp_put_post_revision( $post_data, true ); 345 } 346 347 /** 348 * Prepares the revision for the REST response. 349 * 350 * @since 5.0.0 351 * 352 * @param WP_Post $post Post revision object. 353 * @param WP_REST_Request $request Request object. 354 * 355 * @return WP_REST_Response Response object. 356 */ 357 public function prepare_item_for_response( $post, $request ) { 358 $data = array(); 359 $response = $this->revision_controller->prepare_item_for_response( $post, $request ); 360 361 /** 362 * Filters a revision returned from the API. 363 * 364 * Allows modification of the revision right before it is returned. 365 * 366 * @since 5.0.0 367 * 368 * @param WP_REST_Response $response The response object. 369 * @param WP_Post $post The original revision object. 370 * @param WP_REST_Request $request Request used to generate the response. 371 */ 372 return apply_filters( 'rest_prepare_autosave', $response, $post, $request ); 373 374 } 375 376 } -
src/wp-settings.php
diff --git a/src/wp-settings.php b/src/wp-settings.php index 6edd3c98ca..b2c4189c64 100644
a b require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-attachments-contro 230 230 require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-post-types-controller.php' ); 231 231 require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-post-statuses-controller.php' ); 232 232 require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-revisions-controller.php' ); 233 require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-autosaves-controller.php' ); 233 234 require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-taxonomies-controller.php' ); 234 235 require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-terms-controller.php' ); 235 236 require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-users-controller.php' ); -
new file tests/phpunit/tests/rest-api/rest-autosaves-controller.php
diff --git a/tests/phpunit/tests/rest-api/rest-autosaves-controller.php b/tests/phpunit/tests/rest-api/rest-autosaves-controller.php new file mode 100644 index 0000000000..9824c29321
- + 1 <?php 2 /** 3 * Unit tests covering WP_REST_Autosaves_Controller functionality. 4 * 5 * @package WordPress 6 * @subpackage REST API 7 */ 8 9 /** 10 * @group restapi-autosaves 11 * @group restapi 12 */ 13 class WP_Test_REST_Autosaves_Controller extends WP_Test_REST_Controller_Testcase { 14 protected static $post_id; 15 protected static $page_id; 16 17 protected static $autosave_post_id; 18 protected static $autosave_page_id; 19 20 protected static $editor_id; 21 protected static $contributor_id; 22 23 protected function set_post_data( $args = array() ) { 24 $defaults = array( 25 'title' => 'Post Title', 26 'content' => 'Post content', 27 'excerpt' => 'Post excerpt', 28 'name' => 'test', 29 'author' => get_current_user_id(), 30 ); 31 32 return wp_parse_args( $args, $defaults ); 33 } 34 35 protected function check_create_autosave_response( $response ) { 36 $this->assertNotInstanceOf( 'WP_Error', $response ); 37 $response = rest_ensure_response( $response ); 38 39 $this->assertEquals( 201, $response->get_status() ); 40 $headers = $response->get_headers(); 41 $this->assertArrayHasKey( 'Location', $headers ); 42 } 43 44 public static function wpSetUpBeforeClass( $factory ) { 45 self::$post_id = $factory->post->create(); 46 self::$page_id = $factory->post->create( array( 'post_type' => 'page' ) ); 47 48 self::$editor_id = $factory->user->create( 49 array( 50 'role' => 'editor', 51 ) 52 ); 53 self::$contributor_id = $factory->user->create( 54 array( 55 'role' => 'contributor', 56 ) 57 ); 58 59 wp_set_current_user( self::$editor_id ); 60 61 // Create an autosave. 62 self::$autosave_post_id = wp_create_post_autosave( 63 array( 64 'post_content' => 'This content is better.', 65 'post_ID' => self::$post_id, 66 'post_type' => 'post', 67 ) 68 ); 69 70 self::$autosave_page_id = wp_create_post_autosave( 71 array( 72 'post_content' => 'This content is better.', 73 'post_ID' => self::$page_id, 74 'post_type' => 'post', 75 ) 76 ); 77 78 } 79 80 public static function wpTearDownAfterClass() { 81 // Also deletes revisions. 82 wp_delete_post( self::$post_id, true ); 83 wp_delete_post( self::$page_id, true ); 84 85 self::delete_user( self::$editor_id ); 86 self::delete_user( self::$contributor_id ); 87 } 88 89 public function setUp() { 90 parent::setUp(); 91 wp_set_current_user( self::$editor_id ); 92 93 $this->post_autosave = wp_get_post_autosave( self::$post_id ); 94 } 95 96 public function test_register_routes() { 97 $routes = rest_get_server()->get_routes(); 98 $this->assertArrayHasKey( '/wp/v2/posts/(?P<parent>[\d]+)/autosaves', $routes ); 99 $this->assertArrayHasKey( '/wp/v2/posts/(?P<parent>[\d]+)/autosaves/(?P<id>[\d]+)', $routes ); 100 $this->assertArrayHasKey( '/wp/v2/pages/(?P<parent>[\d]+)/autosaves', $routes ); 101 $this->assertArrayHasKey( '/wp/v2/pages/(?P<parent>[\d]+)/autosaves/(?P<id>[\d]+)', $routes ); 102 } 103 104 public function test_context_param() { 105 // Collection 106 $request = new WP_REST_Request( 'OPTIONS', '/wp/v2/posts/' . self::$post_id . '/autosaves' ); 107 $response = rest_get_server()->dispatch( $request ); 108 $data = $response->get_data(); 109 $this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] ); 110 $this->assertEqualSets( array( 'view', 'edit', 'embed' ), $data['endpoints'][0]['args']['context']['enum'] ); 111 // Single 112 $request = new WP_REST_Request( 'OPTIONS', '/wp/v2/posts/' . self::$post_id . '/autosaves/' . self::$autosave_post_id ); 113 $response = rest_get_server()->dispatch( $request ); 114 $data = $response->get_data(); 115 $this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] ); 116 $this->assertEqualSets( array( 'view', 'edit', 'embed' ), $data['endpoints'][0]['args']['context']['enum'] ); } 117 118 public function test_get_items() { 119 wp_set_current_user( self::$editor_id ); 120 $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/autosaves' ); 121 $response = rest_get_server()->dispatch( $request ); 122 $data = $response->get_data(); 123 $this->assertEquals( 200, $response->get_status() ); 124 $this->assertCount( 1, $data ); 125 126 $this->assertEquals( self::$autosave_post_id, $data[0]['id'] ); 127 128 $this->check_get_autosave_response( $data[0], $this->post_autosave ); 129 } 130 131 public function test_get_items_no_permission() { 132 wp_set_current_user( 0 ); 133 $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/autosaves' ); 134 $response = rest_get_server()->dispatch( $request ); 135 $this->assertErrorResponse( 'rest_cannot_read', $response, 401 ); 136 wp_set_current_user( self::$contributor_id ); 137 $response = rest_get_server()->dispatch( $request ); 138 $this->assertErrorResponse( 'rest_cannot_read', $response, 403 ); 139 } 140 141 public function test_get_items_missing_parent() { 142 wp_set_current_user( self::$editor_id ); 143 $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER . '/autosaves' ); 144 $response = rest_get_server()->dispatch( $request ); 145 $this->assertErrorResponse( 'rest_post_invalid_parent', $response, 404 ); 146 } 147 148 public function test_get_items_invalid_parent_post_type() { 149 wp_set_current_user( self::$editor_id ); 150 $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$page_id . '/autosaves' ); 151 $response = rest_get_server()->dispatch( $request ); 152 $this->assertErrorResponse( 'rest_post_invalid_parent', $response, 404 ); 153 } 154 155 public function test_get_item() { 156 wp_set_current_user( self::$editor_id ); 157 $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/autosaves/' . self::$autosave_post_id ); 158 $response = rest_get_server()->dispatch( $request ); 159 $this->assertEquals( 200, $response->get_status() ); 160 $data = $response->get_data(); 161 162 $this->check_get_autosave_response( $response, $this->post_autosave ); 163 $fields = array( 164 'author', 165 'date', 166 'date_gmt', 167 'modified', 168 'modified_gmt', 169 'guid', 170 'id', 171 'parent', 172 'slug', 173 'title', 174 'excerpt', 175 'content', 176 ); 177 $this->assertEqualSets( $fields, array_keys( $data ) ); 178 $this->assertSame( self::$editor_id, $data['author'] ); 179 } 180 181 public function test_get_item_embed_context() { 182 wp_set_current_user( self::$editor_id ); 183 $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/autosaves/' . self::$autosave_post_id ); 184 $request->set_param( 'context', 'embed' ); 185 $response = rest_get_server()->dispatch( $request ); 186 $fields = array( 187 'author', 188 'date', 189 'id', 190 'parent', 191 'slug', 192 'title', 193 'excerpt', 194 ); 195 $data = $response->get_data(); 196 $this->assertEqualSets( $fields, array_keys( $data ) ); 197 } 198 199 public function test_get_item_no_permission() { 200 $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/autosaves/' . self::$autosave_post_id ); 201 wp_set_current_user( self::$contributor_id ); 202 $response = rest_get_server()->dispatch( $request ); 203 $this->assertErrorResponse( 'rest_cannot_read', $response, 403 ); 204 } 205 206 public function test_get_item_missing_parent() { 207 wp_set_current_user( self::$editor_id ); 208 $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER . '/autosaves/' . self::$autosave_post_id ); 209 $response = rest_get_server()->dispatch( $request ); 210 $this->assertErrorResponse( 'rest_post_invalid_parent', $response, 404 ); 211 212 } 213 214 public function test_get_item_invalid_parent_post_type() { 215 wp_set_current_user( self::$editor_id ); 216 $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$page_id . '/autosaves' ); 217 $response = rest_get_server()->dispatch( $request ); 218 $this->assertErrorResponse( 'rest_post_invalid_parent', $response, 404 ); 219 } 220 221 public function test_delete_item() { 222 wp_set_current_user( self::$editor_id ); 223 $request = new WP_REST_Request( 'DELETE', '/wp/v2/posts/' . self::$post_id . '/autosaves/' . self::$autosave_post_id ); 224 $request->set_param( 'force', true ); 225 $response = rest_get_server()->dispatch( $request ); 226 $this->assertEquals( 200, $response->get_status() ); 227 $this->assertNull( get_post( self::$autosave_post_id ) ); 228 } 229 230 public function test_delete_item_no_trash() { 231 wp_set_current_user( self::$editor_id ); 232 233 $request = new WP_REST_Request( 'DELETE', '/wp/v2/posts/' . self::$post_id . '/autosaves/' . self::$autosave_post_id ); 234 $response = rest_get_server()->dispatch( $request ); 235 $this->assertErrorResponse( 'rest_trash_not_supported', $response, 501 ); 236 237 $request->set_param( 'force', 'false' ); 238 $response = rest_get_server()->dispatch( $request ); 239 $this->assertErrorResponse( 'rest_trash_not_supported', $response, 501 ); 240 241 // Ensure the revision still exists 242 $this->assertNotNull( get_post( self::$autosave_post_id ) ); 243 } 244 245 public function test_delete_item_no_permission() { 246 wp_set_current_user( self::$contributor_id ); 247 $request = new WP_REST_Request( 'DELETE', '/wp/v2/posts/' . self::$post_id . '/autosaves/' . self::$autosave_post_id ); 248 $response = rest_get_server()->dispatch( $request ); 249 $this->assertErrorResponse( 'rest_cannot_read', $response, 403 ); 250 } 251 252 public function test_prepare_item() { 253 wp_set_current_user( self::$editor_id ); 254 $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/autosaves/' . self::$autosave_post_id ); 255 $response = rest_get_server()->dispatch( $request ); 256 $this->assertEquals( 200, $response->get_status() ); 257 $this->check_get_autosave_response( $response, $this->post_autosave ); 258 } 259 260 public function test_get_item_schema() { 261 $request = new WP_REST_Request( 'OPTIONS', '/wp/v2/posts/' . self::$post_id . '/autosaves' ); 262 $response = rest_get_server()->dispatch( $request ); 263 $data = $response->get_data(); 264 $properties = $data['schema']['properties']; 265 $this->assertEquals( 12, count( $properties ) ); 266 $this->assertArrayHasKey( 'author', $properties ); 267 $this->assertArrayHasKey( 'content', $properties ); 268 $this->assertArrayHasKey( 'date', $properties ); 269 $this->assertArrayHasKey( 'date_gmt', $properties ); 270 $this->assertArrayHasKey( 'excerpt', $properties ); 271 $this->assertArrayHasKey( 'guid', $properties ); 272 $this->assertArrayHasKey( 'id', $properties ); 273 $this->assertArrayHasKey( 'modified', $properties ); 274 $this->assertArrayHasKey( 'modified_gmt', $properties ); 275 $this->assertArrayHasKey( 'parent', $properties ); 276 $this->assertArrayHasKey( 'slug', $properties ); 277 $this->assertArrayHasKey( 'title', $properties ); 278 } 279 280 public function test_create_item() { 281 282 wp_set_current_user( self::$editor_id ); 283 284 $request = new WP_REST_Request( 'POST', '/wp/v2/posts/' . self::$post_id . '/autosaves' ); 285 $request->add_header( 'content-type', 'application/x-www-form-urlencoded' ); 286 $params = $this->set_post_data(); 287 $request->set_body_params( $params ); 288 $response = rest_get_server()->dispatch( $request ); 289 290 $this->check_create_autosave_response( $response ); 291 } 292 293 public function test_update_item() { 294 wp_set_current_user( self::$editor_id ); 295 $request = new WP_REST_Request( 'POST', '/wp/v2/posts/' . self::$post_id . '/autosaves/' . self::$autosave_post_id ); 296 $request->add_header( 'content-type', 'application/x-www-form-urlencoded' ); 297 $params = $this->set_post_data(); 298 $request->set_body_params( $params ); 299 $response = rest_get_server()->dispatch( $request ); 300 $this->assertErrorResponse( 'rest_post_exists', $response, 400 ); 301 } 302 303 public function test_get_additional_field_registration() { 304 $schema = array( 305 'type' => 'integer', 306 'description' => 'Some integer of mine', 307 'enum' => array( 1, 2, 3, 4 ), 308 'context' => array( 'view', 'edit' ), 309 ); 310 311 register_rest_field( 312 'post-revision', 'my_custom_int', array( 313 'schema' => $schema, 314 'get_callback' => array( $this, 'additional_field_get_callback' ), 315 'update_callback' => array( $this, 'additional_field_update_callback' ), 316 ) 317 ); 318 319 $request = new WP_REST_Request( 'OPTIONS', '/wp/v2/posts/' . self::$post_id . '/autosaves' ); 320 321 $response = rest_get_server()->dispatch( $request ); 322 $data = $response->get_data(); 323 324 $this->assertArrayHasKey( 'my_custom_int', $data['schema']['properties'] ); 325 $this->assertEquals( $schema, $data['schema']['properties']['my_custom_int'] ); 326 327 wp_set_current_user( 1 ); 328 329 $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/autosaves/' . self::$autosave_post_id ); 330 331 $response = rest_get_server()->dispatch( $request ); 332 $this->assertArrayHasKey( 'my_custom_int', $response->data ); 333 334 global $wp_rest_additional_fields; 335 $wp_rest_additional_fields = array(); 336 } 337 338 public function additional_field_get_callback( $object ) { 339 return get_post_meta( $object['id'], 'my_custom_int', true ); 340 } 341 342 public function additional_field_update_callback( $value, $post ) { 343 update_post_meta( $post->ID, 'my_custom_int', $value ); 344 } 345 346 protected function check_get_autosave_response( $response, $autosave ) { 347 if ( $response instanceof WP_REST_Response ) { 348 $links = $response->get_links(); 349 $response = $response->get_data(); 350 } else { 351 $this->assertArrayHasKey( '_links', $response ); 352 $links = $response['_links']; 353 } 354 355 $this->assertEquals( $autosave->post_author, $response['author'] ); 356 357 $rendered_content = apply_filters( 'the_content', $autosave->post_content ); 358 $this->assertEquals( $rendered_content, $response['content']['rendered'] ); 359 360 $this->assertEquals( mysql_to_rfc3339( $autosave->post_date ), $response['date'] ); 361 $this->assertEquals( mysql_to_rfc3339( $autosave->post_date_gmt ), $response['date_gmt'] ); 362 363 $rendered_guid = apply_filters( 'get_the_guid', $autosave->guid, $autosave->ID ); 364 $this->assertEquals( $rendered_guid, $response['guid']['rendered'] ); 365 366 $this->assertEquals( $autosave->ID, $response['id'] ); 367 $this->assertEquals( mysql_to_rfc3339( $autosave->post_modified ), $response['modified'] ); 368 $this->assertEquals( mysql_to_rfc3339( $autosave->post_modified_gmt ), $response['modified_gmt'] ); 369 $this->assertEquals( $autosave->post_name, $response['slug'] ); 370 371 $rendered_title = get_the_title( $autosave->ID ); 372 $this->assertEquals( $rendered_title, $response['title']['rendered'] ); 373 374 $parent = get_post( $autosave->post_parent ); 375 $parent_controller = new WP_REST_Posts_Controller( $parent->post_type ); 376 $parent_object = get_post_type_object( $parent->post_type ); 377 $parent_base = ! empty( $parent_object->rest_base ) ? $parent_object->rest_base : $parent_object->name; 378 $this->assertEquals( rest_url( '/wp/v2/' . $parent_base . '/' . $autosave->post_parent ), $links['parent'][0]['href'] ); 379 } 380 381 public function test_get_item_sets_up_postdata() { 382 wp_set_current_user( self::$editor_id ); 383 $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/autosaves/' . self::$autosave_post_id ); 384 rest_get_server()->dispatch( $request ); 385 386 $post = get_post(); 387 $parent_post_id = wp_is_post_revision( $post->ID ); 388 389 $this->assertEquals( $post->ID, self::$autosave_post_id ); 390 $this->assertEquals( $parent_post_id, self::$post_id ); 391 } 392 393 } -
tests/phpunit/tests/rest-api/rest-schema-setup.php
diff --git a/tests/phpunit/tests/rest-api/rest-schema-setup.php b/tests/phpunit/tests/rest-api/rest-schema-setup.php index e5b3460122..e3271318b6 100644
a b class WP_Test_REST_Schema_Initialization extends WP_Test_REST_TestCase { 89 89 '/wp/v2/posts/(?P<id>[\\d]+)', 90 90 '/wp/v2/posts/(?P<parent>[\\d]+)/revisions', 91 91 '/wp/v2/posts/(?P<parent>[\\d]+)/revisions/(?P<id>[\\d]+)', 92 '/wp/v2/posts/(?P<parent>[\\d]+)/autosaves', 93 '/wp/v2/posts/(?P<parent>[\\d]+)/autosaves/(?P<id>[\\d]+)', 92 94 '/wp/v2/pages', 93 95 '/wp/v2/pages/(?P<id>[\\d]+)', 94 96 '/wp/v2/pages/(?P<parent>[\\d]+)/revisions', 95 97 '/wp/v2/pages/(?P<parent>[\\d]+)/revisions/(?P<id>[\\d]+)', 98 '/wp/v2/pages/(?P<parent>[\\d]+)/autosaves', 99 '/wp/v2/pages/(?P<parent>[\\d]+)/autosaves/(?P<id>[\\d]+)', 96 100 '/wp/v2/media', 97 101 '/wp/v2/media/(?P<id>[\\d]+)', 98 102 '/wp/v2/types', … … class WP_Test_REST_Schema_Initialization extends WP_Test_REST_TestCase { 159 163 $post_revisions = array_values( wp_get_post_revisions( $post_id ) ); 160 164 $post_revision_id = $post_revisions[ count( $post_revisions ) - 1 ]->ID; 161 165 166 // Create an autosave. 167 wp_create_post_autosave( 168 array( 169 'post_ID' => $post_id, 170 'post_content' => 'Autosave post content.', 171 'post_type' => 'post', 172 ) 173 ); 174 162 175 $page_id = $this->factory->post->create( 163 176 array( 164 177 'post_type' => 'page', … … class WP_Test_REST_Schema_Initialization extends WP_Test_REST_TestCase { 180 193 $page_revisions = array_values( wp_get_post_revisions( $page_id ) ); 181 194 $page_revision_id = $page_revisions[ count( $page_revisions ) - 1 ]->ID; 182 195 196 // Create an autosave. 197 wp_create_post_autosave( 198 array( 199 'post_ID' => $page_id, 200 'post_content' => 'Autosave page content.', 201 'post_type' => 'page', 202 ) 203 ); 204 183 205 $tag_id = $this->factory->tag->create( 184 206 array( 185 207 'name' => 'REST API Client Fixture: Tag', … … class WP_Test_REST_Schema_Initialization extends WP_Test_REST_TestCase { 271 293 'route' => '/wp/v2/posts/' . $post_id . '/revisions/' . $post_revision_id, 272 294 'name' => 'revision', 273 295 ), 296 array( 297 'route' => '/wp/v2/posts/' . $post_id . '/autosaves', 298 'name' => 'postAutosaves', 299 ), 300 array( 301 'route' => '/wp/v2/posts/' . $post_id . '/autosaves/' . $post_revision_id, 302 'name' => 'autosave', 303 ), 274 304 array( 275 305 'route' => '/wp/v2/pages', 276 306 'name' => 'PagesCollection', … … class WP_Test_REST_Schema_Initialization extends WP_Test_REST_TestCase { 287 317 'route' => '/wp/v2/pages/' . $page_id . '/revisions/' . $page_revision_id, 288 318 'name' => 'pageRevision', 289 319 ), 320 array( 321 'route' => '/wp/v2/pages/' . $page_id . '/autosaves', 322 'name' => 'pageAutosaves', 323 ), 324 array( 325 'route' => '/wp/v2/pages/' . $page_id . '/autosaves/' . $page_revision_id, 326 'name' => 'pageAutosave', 327 ), 290 328 array( 291 329 'route' => '/wp/v2/media', 292 330 'name' => 'MediaCollection', -
tests/qunit/fixtures/wp-api-generated.js
diff --git a/tests/qunit/fixtures/wp-api-generated.js b/tests/qunit/fixtures/wp-api-generated.js index 583843fbc1..c70451fee5 100644
a b mockedApiResponse.Schema = { 783 783 } 784 784 ] 785 785 }, 786 "/wp/v2/posts/(?P<parent>[\\d]+)/autosaves": { 787 "namespace": "wp/v2", 788 "methods": [ 789 "GET", 790 "POST" 791 ], 792 "endpoints": [ 793 { 794 "methods": [ 795 "GET" 796 ], 797 "args": { 798 "parent": { 799 "required": false, 800 "description": "The ID for the parent of the object.", 801 "type": "integer" 802 }, 803 "context": { 804 "required": false, 805 "default": "view", 806 "enum": [ 807 "view", 808 "embed", 809 "edit" 810 ], 811 "description": "Scope under which the request is made; determines fields present in response.", 812 "type": "string" 813 } 814 } 815 }, 816 { 817 "methods": [ 818 "POST" 819 ], 820 "args": { 821 "parent": { 822 "required": false, 823 "description": "The ID for the parent of the object.", 824 "type": "integer" 825 }, 826 "author": { 827 "required": false, 828 "description": "The ID for the author of the object.", 829 "type": "integer" 830 }, 831 "date": { 832 "required": false, 833 "description": "The date the object was published, in the site's timezone.", 834 "type": "string" 835 }, 836 "date_gmt": { 837 "required": false, 838 "description": "The date the object was published, as GMT.", 839 "type": "string" 840 }, 841 "id": { 842 "required": false, 843 "description": "Unique identifier for the object.", 844 "type": "integer" 845 }, 846 "modified": { 847 "required": false, 848 "description": "The date the object was last modified, in the site's timezone.", 849 "type": "string" 850 }, 851 "modified_gmt": { 852 "required": false, 853 "description": "The date the object was last modified, as GMT.", 854 "type": "string" 855 }, 856 "slug": { 857 "required": false, 858 "description": "An alphanumeric identifier for the object unique to its type.", 859 "type": "string" 860 }, 861 "title": { 862 "required": false, 863 "description": "The title for the object.", 864 "type": "object" 865 }, 866 "content": { 867 "required": false, 868 "description": "The content for the object.", 869 "type": "object" 870 }, 871 "excerpt": { 872 "required": false, 873 "description": "The excerpt for the object.", 874 "type": "object" 875 } 876 } 877 } 878 ] 879 }, 880 "/wp/v2/posts/(?P<parent>[\\d]+)/autosaves/(?P<id>[\\d]+)": { 881 "namespace": "wp/v2", 882 "methods": [ 883 "GET", 884 "DELETE", 885 "POST" 886 ], 887 "endpoints": [ 888 { 889 "methods": [ 890 "GET" 891 ], 892 "args": { 893 "parent": { 894 "required": false, 895 "description": "The ID for the parent of the object.", 896 "type": "integer" 897 }, 898 "id": { 899 "required": false, 900 "description": "Unique identifier for the object.", 901 "type": "integer" 902 }, 903 "context": { 904 "required": false, 905 "default": "view", 906 "enum": [ 907 "view", 908 "embed", 909 "edit" 910 ], 911 "description": "Scope under which the request is made; determines fields present in response.", 912 "type": "string" 913 } 914 } 915 }, 916 { 917 "methods": [ 918 "DELETE" 919 ], 920 "args": { 921 "parent": { 922 "required": false, 923 "description": "The ID for the parent of the object.", 924 "type": "integer" 925 }, 926 "id": { 927 "required": false, 928 "description": "Unique identifier for the object.", 929 "type": "integer" 930 }, 931 "force": { 932 "required": false, 933 "default": false, 934 "description": "Required to be true, as autosaves do not support trashing.", 935 "type": "boolean" 936 } 937 } 938 }, 939 { 940 "methods": [ 941 "POST" 942 ], 943 "args": { 944 "parent": { 945 "required": false, 946 "description": "The ID for the parent of the object.", 947 "type": "integer" 948 }, 949 "id": { 950 "required": false, 951 "description": "Unique identifier for the object.", 952 "type": "integer" 953 }, 954 "author": { 955 "required": false, 956 "description": "The ID for the author of the object.", 957 "type": "integer" 958 }, 959 "date": { 960 "required": false, 961 "description": "The date the object was published, in the site's timezone.", 962 "type": "string" 963 }, 964 "date_gmt": { 965 "required": false, 966 "description": "The date the object was published, as GMT.", 967 "type": "string" 968 }, 969 "modified": { 970 "required": false, 971 "description": "The date the object was last modified, in the site's timezone.", 972 "type": "string" 973 }, 974 "modified_gmt": { 975 "required": false, 976 "description": "The date the object was last modified, as GMT.", 977 "type": "string" 978 }, 979 "slug": { 980 "required": false, 981 "description": "An alphanumeric identifier for the object unique to its type.", 982 "type": "string" 983 }, 984 "title": { 985 "required": false, 986 "description": "The title for the object.", 987 "type": "object" 988 }, 989 "content": { 990 "required": false, 991 "description": "The content for the object.", 992 "type": "object" 993 }, 994 "excerpt": { 995 "required": false, 996 "description": "The excerpt for the object.", 997 "type": "object" 998 } 999 } 1000 } 1001 ] 1002 }, 786 1003 "/wp/v2/pages": { 787 1004 "namespace": "wp/v2", 788 1005 "methods": [ … … mockedApiResponse.Schema = { 1321 1538 } 1322 1539 ] 1323 1540 }, 1541 "/wp/v2/pages/(?P<parent>[\\d]+)/autosaves": { 1542 "namespace": "wp/v2", 1543 "methods": [ 1544 "GET", 1545 "POST" 1546 ], 1547 "endpoints": [ 1548 { 1549 "methods": [ 1550 "GET" 1551 ], 1552 "args": { 1553 "parent": { 1554 "required": false, 1555 "description": "The ID for the parent of the object.", 1556 "type": "integer" 1557 }, 1558 "context": { 1559 "required": false, 1560 "default": "view", 1561 "enum": [ 1562 "view", 1563 "embed", 1564 "edit" 1565 ], 1566 "description": "Scope under which the request is made; determines fields present in response.", 1567 "type": "string" 1568 } 1569 } 1570 }, 1571 { 1572 "methods": [ 1573 "POST" 1574 ], 1575 "args": { 1576 "parent": { 1577 "required": false, 1578 "description": "The ID for the parent of the object.", 1579 "type": "integer" 1580 }, 1581 "author": { 1582 "required": false, 1583 "description": "The ID for the author of the object.", 1584 "type": "integer" 1585 }, 1586 "date": { 1587 "required": false, 1588 "description": "The date the object was published, in the site's timezone.", 1589 "type": "string" 1590 }, 1591 "date_gmt": { 1592 "required": false, 1593 "description": "The date the object was published, as GMT.", 1594 "type": "string" 1595 }, 1596 "id": { 1597 "required": false, 1598 "description": "Unique identifier for the object.", 1599 "type": "integer" 1600 }, 1601 "modified": { 1602 "required": false, 1603 "description": "The date the object was last modified, in the site's timezone.", 1604 "type": "string" 1605 }, 1606 "modified_gmt": { 1607 "required": false, 1608 "description": "The date the object was last modified, as GMT.", 1609 "type": "string" 1610 }, 1611 "slug": { 1612 "required": false, 1613 "description": "An alphanumeric identifier for the object unique to its type.", 1614 "type": "string" 1615 }, 1616 "title": { 1617 "required": false, 1618 "description": "The title for the object.", 1619 "type": "object" 1620 }, 1621 "content": { 1622 "required": false, 1623 "description": "The content for the object.", 1624 "type": "object" 1625 }, 1626 "excerpt": { 1627 "required": false, 1628 "description": "The excerpt for the object.", 1629 "type": "object" 1630 } 1631 } 1632 } 1633 ] 1634 }, 1635 "/wp/v2/pages/(?P<parent>[\\d]+)/autosaves/(?P<id>[\\d]+)": { 1636 "namespace": "wp/v2", 1637 "methods": [ 1638 "GET", 1639 "DELETE", 1640 "POST" 1641 ], 1642 "endpoints": [ 1643 { 1644 "methods": [ 1645 "GET" 1646 ], 1647 "args": { 1648 "parent": { 1649 "required": false, 1650 "description": "The ID for the parent of the object.", 1651 "type": "integer" 1652 }, 1653 "id": { 1654 "required": false, 1655 "description": "Unique identifier for the object.", 1656 "type": "integer" 1657 }, 1658 "context": { 1659 "required": false, 1660 "default": "view", 1661 "enum": [ 1662 "view", 1663 "embed", 1664 "edit" 1665 ], 1666 "description": "Scope under which the request is made; determines fields present in response.", 1667 "type": "string" 1668 } 1669 } 1670 }, 1671 { 1672 "methods": [ 1673 "DELETE" 1674 ], 1675 "args": { 1676 "parent": { 1677 "required": false, 1678 "description": "The ID for the parent of the object.", 1679 "type": "integer" 1680 }, 1681 "id": { 1682 "required": false, 1683 "description": "Unique identifier for the object.", 1684 "type": "integer" 1685 }, 1686 "force": { 1687 "required": false, 1688 "default": false, 1689 "description": "Required to be true, as autosaves do not support trashing.", 1690 "type": "boolean" 1691 } 1692 } 1693 }, 1694 { 1695 "methods": [ 1696 "POST" 1697 ], 1698 "args": { 1699 "parent": { 1700 "required": false, 1701 "description": "The ID for the parent of the object.", 1702 "type": "integer" 1703 }, 1704 "id": { 1705 "required": false, 1706 "description": "Unique identifier for the object.", 1707 "type": "integer" 1708 }, 1709 "author": { 1710 "required": false, 1711 "description": "The ID for the author of the object.", 1712 "type": "integer" 1713 }, 1714 "date": { 1715 "required": false, 1716 "description": "The date the object was published, in the site's timezone.", 1717 "type": "string" 1718 }, 1719 "date_gmt": { 1720 "required": false, 1721 "description": "The date the object was published, as GMT.", 1722 "type": "string" 1723 }, 1724 "modified": { 1725 "required": false, 1726 "description": "The date the object was last modified, in the site's timezone.", 1727 "type": "string" 1728 }, 1729 "modified_gmt": { 1730 "required": false, 1731 "description": "The date the object was last modified, as GMT.", 1732 "type": "string" 1733 }, 1734 "slug": { 1735 "required": false, 1736 "description": "An alphanumeric identifier for the object unique to its type.", 1737 "type": "string" 1738 }, 1739 "title": { 1740 "required": false, 1741 "description": "The title for the object.", 1742 "type": "object" 1743 }, 1744 "content": { 1745 "required": false, 1746 "description": "The content for the object.", 1747 "type": "object" 1748 }, 1749 "excerpt": { 1750 "required": false, 1751 "description": "The excerpt for the object.", 1752 "type": "object" 1753 } 1754 } 1755 } 1756 ] 1757 }, 1324 1758 "/wp/v2/media": { 1325 1759 "namespace": "wp/v2", 1326 1760 "methods": [ … … mockedApiResponse.postRevisions = [ 3669 4103 "guid": { 3670 4104 "rendered": "http://example.org/?p=4" 3671 4105 }, 4106 "title": { 4107 "rendered": "" 4108 }, 4109 "content": { 4110 "rendered": "<p>Autosave post content.</p>\n" 4111 }, 4112 "excerpt": { 4113 "rendered": "" 4114 }, 4115 "_links": { 4116 "parent": [ 4117 { 4118 "href": "http://example.org/index.php?rest_route=/wp/v2/posts/3" 4119 } 4120 ] 4121 } 4122 }, 4123 { 4124 "author": 59, 4125 "date": "2017-02-14T00:00:00", 4126 "date_gmt": "2017-02-14T00:00:00", 4127 "id": 427, 4128 "modified": "2017-02-14T00:00:00", 4129 "modified_gmt": "2017-02-14T00:00:00", 4130 "parent": 426, 4131 "slug": "426-revision-v1", 4132 "guid": { 4133 "rendered": "http://example.org/?p=427" 4134 }, 3672 4135 "title": { 3673 4136 "rendered": "REST API Client Fixture: Post" 3674 4137 }, … … mockedApiResponse.postRevisions = [ 3681 4144 "_links": { 3682 4145 "parent": [ 3683 4146 { 3684 "href": "http://example.org/index.php?rest_route=/wp/v2/posts/ 3"4147 "href": "http://example.org/index.php?rest_route=/wp/v2/posts/426" 3685 4148 } 3686 4149 ] 3687 4150 } … … mockedApiResponse.revision = { 3711 4174 } 3712 4175 }; 3713 4176 4177 mockedApiResponse.postAutosaves = [ 4178 { 4179 "author": 59, 4180 "date": "2017-02-14T00:00:00", 4181 "date_gmt": "2017-02-14T00:00:00", 4182 "id": 428, 4183 "modified": "2017-02-14T00:00:00", 4184 "modified_gmt": "2017-02-14T00:00:00", 4185 "parent": 426, 4186 "slug": "426-autosave-v1", 4187 "guid": { 4188 "rendered": "http://example.org/?p=428" 4189 }, 4190 "title": { 4191 "rendered": "" 4192 }, 4193 "content": { 4194 "rendered": "<p>Autosave post content.</p>\n" 4195 }, 4196 "excerpt": { 4197 "rendered": "" 4198 }, 4199 "_links": { 4200 "parent": [ 4201 { 4202 "href": "http://example.org/index.php?rest_route=/426" 4203 } 4204 ] 4205 } 4206 } 4207 ]; 4208 4209 mockedApiResponse.autosave = { 4210 "ID": 427, 4211 "post_author": "59", 4212 "post_date": "2018-03-10 16:46:38", 4213 "post_date_gmt": "2018-03-10 16:46:38", 4214 "post_content": "Updated post content.", 4215 "post_title": "REST API Client Fixture: Post", 4216 "post_excerpt": "REST API Client Fixture: Post", 4217 "post_status": "inherit", 4218 "comment_status": "closed", 4219 "ping_status": "closed", 4220 "post_password": "", 4221 "post_name": "426-revision-v1", 4222 "to_ping": "", 4223 "pinged": "", 4224 "post_modified": "2018-03-10 16:46:38", 4225 "post_modified_gmt": "2018-03-10 16:46:38", 4226 "post_content_filtered": "", 4227 "post_parent": 426, 4228 "guid": "http://example.org/?p=427", 4229 "menu_order": 0, 4230 "post_type": "revision", 4231 "post_mime_type": "", 4232 "comment_count": "0", 4233 "filter": "raw" 4234 }; 4235 3714 4236 mockedApiResponse.PagesCollection = [ 3715 4237 { 3716 4238 "id": 5, … … mockedApiResponse.pageRevisions = [ 3838 4360 "guid": { 3839 4361 "rendered": "http://example.org/?p=6" 3840 4362 }, 4363 "title": { 4364 "rendered": "" 4365 }, 4366 "content": { 4367 "rendered": "<p>Autosave page content.</p>\n" 4368 }, 4369 "excerpt": { 4370 "rendered": "" 4371 }, 4372 "_links": { 4373 "parent": [ 4374 { 4375 "href": "http://example.org/index.php?rest_route=/wp/v2/pages/5" 4376 } 4377 ] 4378 } 4379 }, 4380 { 4381 "author": 59, 4382 "date": "2017-02-14T00:00:00", 4383 "date_gmt": "2017-02-14T00:00:00", 4384 "id": 430, 4385 "modified": "2017-02-14T00:00:00", 4386 "modified_gmt": "2017-02-14T00:00:00", 4387 "parent": 429, 4388 "slug": "429-revision-v1", 4389 "guid": { 4390 "rendered": "http://example.org/?p=430" 4391 }, 3841 4392 "title": { 3842 4393 "rendered": "REST API Client Fixture: Page" 3843 4394 }, … … mockedApiResponse.pageRevisions = [ 3850 4401 "_links": { 3851 4402 "parent": [ 3852 4403 { 3853 "href": "http://example.org/index.php?rest_route=/wp/v2/pages/ 5"4404 "href": "http://example.org/index.php?rest_route=/wp/v2/pages/429" 3854 4405 } 3855 4406 ] 3856 4407 } … … mockedApiResponse.pageRevision = { 3880 4431 } 3881 4432 }; 3882 4433 4434 mockedApiResponse.pageAutosaves = [ 4435 { 4436 "author": 59, 4437 "date": "2017-02-14T00:00:00", 4438 "date_gmt": "2017-02-14T00:00:00", 4439 "id": 431, 4440 "modified": "2017-02-14T00:00:00", 4441 "modified_gmt": "2017-02-14T00:00:00", 4442 "parent": 429, 4443 "slug": "429-autosave-v1", 4444 "guid": { 4445 "rendered": "http://example.org/?p=431" 4446 }, 4447 "title": { 4448 "rendered": "" 4449 }, 4450 "content": { 4451 "rendered": "<p>Autosave page content.</p>\n" 4452 }, 4453 "excerpt": { 4454 "rendered": "" 4455 }, 4456 "_links": { 4457 "parent": [ 4458 { 4459 "href": "http://example.org/index.php?rest_route=/429" 4460 } 4461 ] 4462 } 4463 } 4464 ]; 4465 4466 mockedApiResponse.pageAutosave = { 4467 "ID": 430, 4468 "post_author": "59", 4469 "post_date": "2018-03-10 16:46:38", 4470 "post_date_gmt": "2018-03-10 16:46:38", 4471 "post_content": "Updated page content.", 4472 "post_title": "REST API Client Fixture: Page", 4473 "post_excerpt": "REST API Client Fixture: Page", 4474 "post_status": "inherit", 4475 "comment_status": "closed", 4476 "ping_status": "closed", 4477 "post_password": "", 4478 "post_name": "429-revision-v1", 4479 "to_ping": "", 4480 "pinged": "", 4481 "post_modified": "2018-03-10 16:46:38", 4482 "post_modified_gmt": "2018-03-10 16:46:38", 4483 "post_content_filtered": "", 4484 "post_parent": 429, 4485 "guid": "http://example.org/?p=430", 4486 "menu_order": 0, 4487 "post_type": "revision", 4488 "post_mime_type": "", 4489 "comment_count": "0", 4490 "filter": "raw" 4491 }; 4492 3883 4493 mockedApiResponse.MediaCollection = [ 3884 4494 { 3885 4495 "id": 7,