Ticket #43316: 43316.8.diff
File 43316.8.diff, 57.9 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..cb8d1c3167
- + 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 $response = array(); 271 $post_id = $request->get_param( 'parent' ); 272 $revisions = wp_get_post_revisions( $post_id, array( 'check_enabled' => false ) ); 273 274 foreach ( $revisions as $revision ) { 275 if ( false !== strpos( $revision->post_name, "{$post_id}-autosave" ) ) { 276 $data = $this->prepare_item_for_response( $revision, $request ); 277 $response[] = $this->prepare_response_for_collection( $data ); 278 } 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 // If the autosave content is significantly different, create a revision. 338 $autosave_sizediff = strlen( $new_autosave['content'] ) - strlen( $old_autosave['content'] ); 339 $create_revision = $autosave_sizediff > 250; 340 341 /** 342 * Filter whether a revision is created when an autosave is made via the REST API. 343 * 344 * @since 5.0.0 345 * 346 * @param bool $create_revision Create a revision? 347 * @param array $post_data The autosave post data. 348 * @param int $autosave_sizediff The calculated autosave difference. 349 */ 350 if ( apply_filters( 'wp_create_revision_for_api_autosave', $create_revision, $post_data, $autosave_sizediff 351 ) ) { 352 _wp_put_post_revision( $new_autosave ); 353 } 354 355 return wp_update_post( $new_autosave ); 356 } 357 358 // _wp_put_post_revision() expects unescaped. 359 $post_data = wp_unslash( $post_data ); 360 361 // Otherwise create the new autosave as a special post revision. 362 return _wp_put_post_revision( $post_data, true ); 363 } 364 365 /** 366 * Prepares the revision for the REST response. 367 * 368 * @since 5.0.0 369 * 370 * @param WP_Post $post Post revision object. 371 * @param WP_REST_Request $request Request object. 372 * 373 * @return WP_REST_Response Response object. 374 */ 375 public function prepare_item_for_response( $post, $request ) { 376 $data = array(); 377 $response = $this->revision_controller->prepare_item_for_response( $post, $request ); 378 379 /** 380 * Filters a revision returned from the API. 381 * 382 * Allows modification of the revision right before it is returned. 383 * 384 * @since 5.0.0 385 * 386 * @param WP_REST_Response $response The response object. 387 * @param WP_Post $post The original revision object. 388 * @param WP_REST_Request $request Request used to generate the response. 389 */ 390 return apply_filters( 'rest_prepare_autosave', $response, $post, $request ); 391 392 } 393 394 } -
src/wp-settings.php
diff --git a/src/wp-settings.php b/src/wp-settings.php index 6b1f32bbff..767b9ddf73 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..2714b480ce 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 = { 1230 1447 } 1231 1448 ] 1232 1449 }, 1233 "/wp/v2/pages/(?P<parent>[\\d]+)/revisions": { 1450 "/wp/v2/pages/(?P<parent>[\\d]+)/revisions": { 1451 "namespace": "wp/v2", 1452 "methods": [ 1453 "GET" 1454 ], 1455 "endpoints": [ 1456 { 1457 "methods": [ 1458 "GET" 1459 ], 1460 "args": { 1461 "parent": { 1462 "required": false, 1463 "description": "The ID for the parent of the object.", 1464 "type": "integer" 1465 }, 1466 "context": { 1467 "required": false, 1468 "default": "view", 1469 "enum": [ 1470 "view", 1471 "embed", 1472 "edit" 1473 ], 1474 "description": "Scope under which the request is made; determines fields present in response.", 1475 "type": "string" 1476 } 1477 } 1478 } 1479 ] 1480 }, 1481 "/wp/v2/pages/(?P<parent>[\\d]+)/revisions/(?P<id>[\\d]+)": { 1482 "namespace": "wp/v2", 1483 "methods": [ 1484 "GET", 1485 "DELETE" 1486 ], 1487 "endpoints": [ 1488 { 1489 "methods": [ 1490 "GET" 1491 ], 1492 "args": { 1493 "parent": { 1494 "required": false, 1495 "description": "The ID for the parent of the object.", 1496 "type": "integer" 1497 }, 1498 "id": { 1499 "required": false, 1500 "description": "Unique identifier for the object.", 1501 "type": "integer" 1502 }, 1503 "context": { 1504 "required": false, 1505 "default": "view", 1506 "enum": [ 1507 "view", 1508 "embed", 1509 "edit" 1510 ], 1511 "description": "Scope under which the request is made; determines fields present in response.", 1512 "type": "string" 1513 } 1514 } 1515 }, 1516 { 1517 "methods": [ 1518 "DELETE" 1519 ], 1520 "args": { 1521 "parent": { 1522 "required": false, 1523 "description": "The ID for the parent of the object.", 1524 "type": "integer" 1525 }, 1526 "id": { 1527 "required": false, 1528 "description": "Unique identifier for the object.", 1529 "type": "integer" 1530 }, 1531 "force": { 1532 "required": false, 1533 "default": false, 1534 "description": "Required to be true, as revisions do not support trashing.", 1535 "type": "boolean" 1536 } 1537 } 1538 } 1539 ] 1540 }, 1541 "/wp/v2/pages/(?P<parent>[\\d]+)/autosaves": { 1234 1542 "namespace": "wp/v2", 1235 1543 "methods": [ 1236 "GET" 1544 "GET", 1545 "POST" 1237 1546 ], 1238 1547 "endpoints": [ 1239 1548 { … … mockedApiResponse.Schema = { 1258 1567 "type": "string" 1259 1568 } 1260 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 } 1261 1632 } 1262 1633 ] 1263 1634 }, 1264 "/wp/v2/pages/(?P<parent>[\\d]+)/ revisions/(?P<id>[\\d]+)": {1635 "/wp/v2/pages/(?P<parent>[\\d]+)/autosaves/(?P<id>[\\d]+)": { 1265 1636 "namespace": "wp/v2", 1266 1637 "methods": [ 1267 1638 "GET", 1268 "DELETE" 1639 "DELETE", 1640 "POST" 1269 1641 ], 1270 1642 "endpoints": [ 1271 1643 { … … mockedApiResponse.Schema = { 1314 1686 "force": { 1315 1687 "required": false, 1316 1688 "default": false, 1317 "description": "Required to be true, as revisions do not support trashing.",1689 "description": "Required to be true, as autosaves do not support trashing.", 1318 1690 "type": "boolean" 1319 1691 } 1320 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 } 1321 1755 } 1322 1756 ] 1323 1757 }, … … mockedApiResponse.PostModel = { 3657 4091 }; 3658 4092 3659 4093 mockedApiResponse.postRevisions = [ 4094 { 4095 "author": 2, 4096 "date": "2017-02-14T00:00:00", 4097 "date_gmt": "2017-02-14T00:00:00", 4098 "id": 4, 4099 "modified": "2017-02-14T00:00:00", 4100 "modified_gmt": "2017-02-14T00:00:00", 4101 "parent": 3, 4102 "slug": "3-revision-v1", 4103 "guid": { 4104 "rendered": "http://example.org/?p=4" 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 }, 3660 4123 { 3661 4124 "author": 2, 3662 4125 "date": "2017-02-14T00:00:00", … … mockedApiResponse.revision = { 3711 4174 } 3712 4175 }; 3713 4176 4177 mockedApiResponse.postAutosaves = [ 4178 { 4179 "author": 2, 4180 "date": "2017-02-14T00:00:00", 4181 "date_gmt": "2017-02-14T00:00:00", 4182 "id": 5, 4183 "modified": "2017-02-14T00:00:00", 4184 "modified_gmt": "2017-02-14T00:00:00", 4185 "parent": 3, 4186 "slug": "3-autosave-v1", 4187 "guid": { 4188 "rendered": "http://example.org/?p=5" 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=/wp/v2/posts/3" 4203 } 4204 ] 4205 } 4206 } 4207 ]; 4208 4209 mockedApiResponse.autosave = { 4210 "author": 2, 4211 "date": "2017-02-14T00:00:00", 4212 "date_gmt": "2017-02-14T00:00:00", 4213 "id": 5, 4214 "modified": "2017-02-14T00:00:00", 4215 "modified_gmt": "2017-02-14T00:00:00", 4216 "parent": 3, 4217 "slug": "3-autosave-v1", 4218 "guid": { 4219 "rendered": "http://example.org/?p=5" 4220 }, 4221 "title": { 4222 "rendered": "" 4223 }, 4224 "content": { 4225 "rendered": "<p>Autosave post content.</p>\n" 4226 }, 4227 "excerpt": { 4228 "rendered": "" 4229 } 4230 }; 4231 3714 4232 mockedApiResponse.PagesCollection = [ 3715 4233 { 3716 4234 "id": 5, … … mockedApiResponse.pageRevisions = [ 3838 4356 "guid": { 3839 4357 "rendered": "http://example.org/?p=6" 3840 4358 }, 4359 "title": { 4360 "rendered": "" 4361 }, 4362 "content": { 4363 "rendered": "<p>Autosave page content.</p>\n" 4364 }, 4365 "excerpt": { 4366 "rendered": "" 4367 }, 4368 "_links": { 4369 "parent": [ 4370 { 4371 "href": "http://example.org/index.php?rest_route=/wp/v2/pages/5" 4372 } 4373 ] 4374 } 4375 }, 4376 { 4377 "author": 2, 4378 "date": "2017-02-14T00:00:00", 4379 "date_gmt": "2017-02-14T00:00:00", 4380 "id": 7, 4381 "modified": "2017-02-14T00:00:00", 4382 "modified_gmt": "2017-02-14T00:00:00", 4383 "parent": 6, 4384 "slug": "6-revision-v1", 4385 "guid": { 4386 "rendered": "http://example.org/?p=7" 4387 }, 3841 4388 "title": { 3842 4389 "rendered": "REST API Client Fixture: Page" 3843 4390 }, … … mockedApiResponse.pageRevisions = [ 3850 4397 "_links": { 3851 4398 "parent": [ 3852 4399 { 3853 "href": "http://example.org/index.php?rest_route=/wp/v2/pages/ 5"4400 "href": "http://example.org/index.php?rest_route=/wp/v2/pages/6" 3854 4401 } 3855 4402 ] 3856 4403 } … … mockedApiResponse.pageRevision = { 3880 4427 } 3881 4428 }; 3882 4429 4430 mockedApiResponse.pageAutosaves = [ 4431 { 4432 "author": 2, 4433 "date": "2017-02-14T00:00:00", 4434 "date_gmt": "2017-02-14T00:00:00", 4435 "id": 8, 4436 "modified": "2017-02-14T00:00:00", 4437 "modified_gmt": "2017-02-14T00:00:00", 4438 "parent": 6, 4439 "slug": "6-autosave-v1", 4440 "guid": { 4441 "rendered": "http://example.org/?p=8" 4442 }, 4443 "title": { 4444 "rendered": "" 4445 }, 4446 "content": { 4447 "rendered": "<p>Autosave page content.</p>\n" 4448 }, 4449 "excerpt": { 4450 "rendered": "" 4451 }, 4452 "_links": { 4453 "parent": [ 4454 { 4455 "href": "http://example.org/index.php?rest_route=/wp/v2/pages/6" 4456 } 4457 ] 4458 } 4459 } 4460 ]; 4461 4462 mockedApiResponse.pageAutosave = { 4463 "author": 2, 4464 "date": "2017-02-14T00:00:00", 4465 "date_gmt": "2017-02-14T00:00:00", 4466 "id": 8, 4467 "modified": "2017-02-14T00:00:00", 4468 "modified_gmt": "2017-02-14T00:00:00", 4469 "parent": 6, 4470 "slug": "6-autosave-v1", 4471 "guid": { 4472 "rendered": "http://example.org/?p=8" 4473 }, 4474 "title": { 4475 "rendered": "" 4476 }, 4477 "content": { 4478 "rendered": "<p>Autosave page content.</p>\n" 4479 }, 4480 "excerpt": { 4481 "rendered": "" 4482 } 4483 }; 4484 3883 4485 mockedApiResponse.MediaCollection = [ 3884 4486 { 3885 4487 "id": 7,