Ticket #20564: 20564.27.diff
File 20564.27.diff, 58.0 KB (added by , 17 months ago) |
---|
-
src/wp-admin/includes/post.php
diff --git src/wp-admin/includes/post.php src/wp-admin/includes/post.php index 3709ded67f..8ec2c322ee 100644
function wp_create_post_autosave( $post_data ) { 1961 1961 * @param array $new_autosave Post array - the autosave that is about to be saved. 1962 1962 */ 1963 1963 do_action( 'wp_creating_autosave', $new_autosave ); 1964 1964 wp_autosave_post_revisioned_meta_fields( $new_autosave ); 1965 1965 return wp_update_post( $new_autosave ); 1966 1966 } 1967 1967 … … function wp_create_post_autosave( $post_data ) { 1969 1969 $post_data = wp_unslash( $post_data ); 1970 1970 1971 1971 // Otherwise create the new autosave as a special post revision. 1972 return _wp_put_post_revision( $post_data, true ); 1972 $revision = _wp_put_post_revision( $post_data, true ); 1973 1974 // Update the revisioned meta data as well. 1975 wp_autosave_post_revisioned_meta_fields( get_post( $revision, ARRAY_A ) ); 1976 return $revision; 1977 } 1978 1979 /** 1980 * Autosave the revisioned meta fields. 1981 * 1982 * Iterates thru the revisioned meta fields and checks each to see if they are set, 1983 * and have a changed value. If so, the meta value is saved and attached to the autosave. 1984 * 1985 * @since 6.4.0 1986 * 1987 * @param array $new_autosave The new post data being autosaved. 1988 */ 1989 function wp_autosave_post_revisioned_meta_fields( $new_autosave ) { 1990 /* 1991 * The post data arrives as either $_POST['data']['wp_autosave'] or the $_POST 1992 * itself. This sets $posted_data to the correct variable. 1993 * 1994 * Ignoring sanitization to avoid altering meta. Ignoring the nonce check because 1995 * this is hooked on inner core hooks where a valid nonce was already checked. 1996 * 1997 * @phpcs:disable WordPress.Security 1998 */ 1999 $posted_data = isset( $_POST['data']['wp_autosave'] ) ? $_POST['data']['wp_autosave'] : $_POST; 2000 // phpcs:enable 2001 2002 $post_type = get_post_type( $new_autosave['post_parent'] ); 2003 2004 /* 2005 * Go thru the revisioned meta keys and save them as part of the autosave, if 2006 * the meta key is part of the posted data, the meta value is not blank and 2007 * the the meta value has changes from the last autosaved value. 2008 */ 2009 foreach ( wp_post_revision_meta_keys( $post_type ) as $meta_key ) { 2010 2011 if ( 2012 isset( $posted_data[ $meta_key ] ) && 2013 get_post_meta( $new_autosave['ID'], $meta_key, true ) !== wp_unslash( $posted_data[ $meta_key ] ) 2014 ) { 2015 /* 2016 * Use the underlying delete_metadata() and add_metadata() functions 2017 * vs delete_post_meta() and add_post_meta() to make sure we're working 2018 * with the actual revision meta. 2019 */ 2020 delete_metadata( 'post', $new_autosave['ID'], $meta_key ); 2021 2022 /* 2023 * One last check to ensure meta value not empty(). 2024 */ 2025 if ( ! empty( $posted_data[ $meta_key ] ) ) { 2026 /* 2027 * Add the revisions meta data to the autosave. 2028 */ 2029 add_metadata( 'post', $new_autosave['ID'], $meta_key, $posted_data[ $meta_key ] ); 2030 } 2031 } 2032 } 1973 2033 } 1974 2034 1975 2035 /** -
src/wp-includes/default-filters.php
diff --git src/wp-includes/default-filters.php src/wp-includes/default-filters.php index 5add466889..541410bdce 100644
add_action( 'plugins_loaded', 'wp_maybe_load_widgets', 0 ); 409 409 add_action( 'plugins_loaded', 'wp_maybe_load_embeds', 0 ); 410 410 add_action( 'shutdown', 'wp_ob_end_flush_all', 1 ); 411 411 // Create a revision whenever a post is updated. 412 add_action( 'wp_after_insert_post', 'wp_save_post_revision_on_insert', 9, 3 ); 412 413 add_action( 'post_updated', 'wp_save_post_revision', 10, 1 ); 413 414 add_action( 'publish_post', '_publish_post_hook', 5, 1 ); 414 415 add_action( 'transition_post_status', '_transition_post_status', 5, 3 ); … … add_action( 'init', 'wp_register_persisted_preferences_meta' ); 716 717 // CPT wp_block custom postmeta field. 717 718 add_action( 'init', 'wp_create_initial_post_meta' ); 718 719 720 // Include revisioned meta when considering whether a post revision has changed. 721 add_filter( 'wp_save_post_revision_post_has_changed', 'wp_check_revisioned_meta_fields_have_changed', 10, 3 ); 722 723 // Save revisioned post meta immediately after a revision is saved 724 add_action( '_wp_put_post_revision', 'wp_save_revisioned_meta_fields', 10, 2 ); 725 719 726 // Font management. 720 727 add_action( 'wp_head', 'wp_print_font_faces', 50 ); 721 728 -
src/wp-includes/meta.php
diff --git src/wp-includes/meta.php src/wp-includes/meta.php index 0b9f08544e..99e6920f9a 100644
function sanitize_meta( $meta_key, $meta_value, $object_type, $object_subtype = 1367 1367 * @since 4.9.8 The `$object_subtype` argument was added to the arguments array. 1368 1368 * @since 5.3.0 Valid meta types expanded to include "array" and "object". 1369 1369 * @since 5.5.0 The `$default` argument was added to the arguments array. 1370 * @since 6.4.0 The `$revisions_enabled` argument was added to the arguments array. 1370 1371 * 1371 1372 * @param string $object_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', 1372 1373 * or any other object type with an associated meta table. … … function sanitize_meta( $meta_key, $meta_value, $object_type, $object_subtype = 1392 1393 * support for custom fields for registered meta to be accessible via REST. 1393 1394 * When registering complex meta values this argument may optionally be an 1394 1395 * array with 'schema' or 'prepare_callback' keys instead of a boolean. 1396 * @type bool $revisions_enabled Whether to enable revisions support for this meta_key. Can only be used when the 1397 * object type is 'post'. 1395 1398 * } 1396 1399 * @param string|array $deprecated Deprecated. Use `$args` instead. 1397 1400 * @return bool True if the meta key was successfully registered in the global array, false if not. … … function register_meta( $object_type, $meta_key, $args, $deprecated = null ) { 1414 1417 'sanitize_callback' => null, 1415 1418 'auth_callback' => null, 1416 1419 'show_in_rest' => false, 1420 'revisions_enabled' => false, 1417 1421 ); 1418 1422 1419 1423 // There used to be individual args for sanitize and auth callbacks. -
src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php
diff --git src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php index d2dc249615..5ff367320a 100644
class WP_REST_Autosaves_Controller extends WP_REST_Revisions_Controller { 234 234 */ 235 235 $autosave_id = wp_update_post( wp_slash( (array) $prepared_post ), true ); 236 236 } else { 237 // Non-draft posts: create or update the post autosave. 238 $autosave_id = $this->create_post_autosave( (array) $prepared_post );237 // Non-draft posts: create or update the post autosave. Pass the meta data. 238 $autosave_id = $this->create_post_autosave( (array) $prepared_post, $request->get_param( 'meta' ) ); 239 239 } 240 240 241 241 if ( is_wp_error( $autosave_id ) ) { … … class WP_REST_Autosaves_Controller extends WP_REST_Revisions_Controller { 348 348 * From wp-admin/post.php. 349 349 * 350 350 * @since 5.0.0 351 * @since 6.4.0 The `$meta` parameter was added. 351 352 * 352 353 * @param array $post_data Associative array containing the post data. 354 * @param array $meta Associative array containing the post meta data. 353 355 * @return mixed The autosave revision ID or WP_Error. 354 356 */ 355 public function create_post_autosave( $post_data ) {357 public function create_post_autosave( $post_data, $meta = array() ) { 356 358 357 359 $post_id = (int) $post_data['ID']; 358 360 $post = get_post( $post_id ); … … class WP_REST_Autosaves_Controller extends WP_REST_Revisions_Controller { 372 374 } 373 375 } 374 376 377 // Check if meta values have changed. 378 if ( ! empty( $meta ) ) { 379 $revisioned_meta_keys = wp_post_revision_meta_keys( $post->post_type ); 380 foreach ( $revisioned_meta_keys as $meta_key ) { 381 $old_meta = get_post_meta( $post_id, $meta_key, true ); 382 $new_meta = isset( $meta[ $meta_key ] ) ? $meta[ $meta_key ] : ''; 383 384 if ( $new_meta !== $old_meta ) { 385 $autosave_is_different = true; 386 break; 387 } 388 } 389 } 390 375 391 $user_id = get_current_user_id(); 376 392 377 393 // Store one autosave per author. If there is already an autosave, overwrite it. … … class WP_REST_Autosaves_Controller extends WP_REST_Revisions_Controller { 390 406 do_action( 'wp_creating_autosave', $new_autosave ); 391 407 392 408 // wp_update_post() expects escaped array. 393 return wp_update_post( wp_slash( $new_autosave ) ); 409 $revision_id = wp_update_post( wp_slash( $new_autosave ) ); 410 } else { 411 // Create the new autosave as a special post revision. 412 $revision_id = _wp_put_post_revision( $post_data, true ); 394 413 } 395 414 396 // Create the new autosave as a special post revision. 397 return _wp_put_post_revision( $post_data, true ); 415 // Attached any passed meta values that have revisions enabled. 416 if ( ! empty( $meta ) && $revision_id ) { 417 foreach ( $revisioned_meta_keys as $meta_key ) { 418 if ( isset( $meta[ $meta_key ] ) ) { 419 update_metadata( 'post', $revision_id, $meta_key, $meta[ $meta_key ] ); 420 } 421 } 422 } 423 return $revision_id; 398 424 } 399 425 400 426 /** -
src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php
diff --git src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php index 16aceb0d74..a1d10d2ae0 100644
class WP_REST_Revisions_Controller extends WP_REST_Controller { 24 24 */ 25 25 private $parent_post_type; 26 26 27 /** 28 * Instance of a revision meta fields object. 29 * 30 * @since 4.7.0 31 * @var WP_REST_Post_Meta_Fields 32 */ 33 protected $meta; 34 27 35 /** 28 36 * Parent controller. 29 37 * … … class WP_REST_Revisions_Controller extends WP_REST_Controller { 60 68 $this->rest_base = 'revisions'; 61 69 $this->parent_base = ! empty( $post_type_object->rest_base ) ? $post_type_object->rest_base : $post_type_object->name; 62 70 $this->namespace = ! empty( $post_type_object->rest_namespace ) ? $post_type_object->rest_namespace : 'wp/v2'; 71 $this->meta = new WP_REST_Post_Meta_Fields( $parent_post_type ); 63 72 } 64 73 65 74 /** … … class WP_REST_Revisions_Controller extends WP_REST_Controller { 619 628 ); 620 629 } 621 630 631 if ( rest_is_field_included( 'meta', $fields ) ) { 632 $data['meta'] = $this->meta->get_value( $post->ID, $request ); 633 } 634 622 635 $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; 623 636 $data = $this->add_additional_fields_to_object( $data, $request ); 624 637 $data = $this->filter_response_by_context( $data, $context ); … … class WP_REST_Revisions_Controller extends WP_REST_Controller { 752 765 $schema['properties']['guid'] = $parent_schema['properties']['guid']; 753 766 } 754 767 768 $schema['properties']['meta'] = $this->meta->get_field_schema(); 769 755 770 $this->schema = $schema; 756 771 757 772 return $this->add_additional_fields_schema( $this->schema ); -
src/wp-includes/revision.php
diff --git src/wp-includes/revision.php src/wp-includes/revision.php index d5a5829d7e..609ce4b532 100644
function _wp_post_revision_data( $post = array(), $autosave = false ) { 95 95 return $revision_data; 96 96 } 97 97 98 /** 99 * Saves revisions for a post after all changes have been made. 100 * 101 * @since 6.4.0 102 * 103 * @param int $post_id The post id that was inserted. 104 * @param WP_Post $post The post object that was inserted. 105 * @param bool $update Whether this insert is updating an existing post. 106 */ 107 function wp_save_post_revision_on_insert( $post_id, $post, $update ) { 108 if ( ! $update ) { 109 return; 110 } 111 112 if ( ! has_action( 'post_updated', 'wp_save_post_revision' ) ) { 113 return; 114 } 115 116 wp_save_post_revision( $post_id ); 117 } 118 98 119 /** 99 120 * Creates a revision for the current version of a post. 100 121 * … … function wp_save_post_revision( $post_id ) { 111 132 return; 112 133 } 113 134 135 // Prevent saving post revisions if revisions should be saved on wp_after_insert_post. 136 if ( doing_action( 'post_updated' ) && has_action( 'wp_after_insert_post', 'wp_save_post_revision_on_insert' ) ) { 137 return; 138 } 139 114 140 $post = get_post( $post_id ); 115 141 116 142 if ( ! $post ) { … … function _wp_put_post_revision( $post = null, $autosave = false ) { 361 387 * Fires once a revision has been saved. 362 388 * 363 389 * @since 2.6.0 390 * @since 6.4.0 The post_id parameter was added. 364 391 * 365 392 * @param int $revision_id Post revision ID. 393 * @param int $post_id Post ID. 366 394 */ 367 do_action( '_wp_put_post_revision', $revision_id );395 do_action( '_wp_put_post_revision', $revision_id, $post['post_parent'] ); 368 396 } 369 397 370 398 return $revision_id; 371 399 } 372 400 401 402 /** 403 * Save the revisioned meta fields. 404 * 405 * @param int $revision_id The ID of the revision to save the meta to. 406 * @param int $post_id The ID of the post the revision is associated with. 407 * 408 * @since 6.4.0 409 */ 410 function wp_save_revisioned_meta_fields( $revision_id, $post_id ) { 411 412 // Save revisioned meta fields. 413 foreach ( wp_post_revision_meta_keys( get_post_type( $post_id ) ) as $meta_key ) { 414 if ( metadata_exists( 'post', $post_id, $meta_key ) ) { 415 _wp_copy_post_meta( $post_id, $revision_id, $meta_key ); 416 } 417 } 418 } 419 373 420 /** 374 421 * Gets a post revision. 375 422 * … … function wp_restore_post_revision( $revision, $fields = null ) { 450 497 // Update last edit user. 451 498 update_post_meta( $post_id, '_edit_last', get_current_user_id() ); 452 499 500 // Restore any revisioned meta fields. 501 wp_restore_post_revision_meta( $post_id, $revision['ID'] ); 502 453 503 /** 454 504 * Fires after a post revision has been restored. 455 505 * … … function wp_restore_post_revision( $revision, $fields = null ) { 463 513 return $post_id; 464 514 } 465 515 516 /** 517 * Restore the revisioned meta values for a post. 518 * 519 * @param int $post_id The ID of the post to restore the meta to. 520 * @param int $revision_id The ID of the revision to restore the meta from. 521 * 522 * @since 6.4.0 523 */ 524 function wp_restore_post_revision_meta( $post_id, $revision_id ) { 525 526 // Restore revisioned meta fields. 527 foreach ( wp_post_revision_meta_keys( get_post_type( $post_id ) ) as $meta_key ) { 528 529 // Clear any existing meta. 530 delete_post_meta( $post_id, $meta_key ); 531 532 _wp_copy_post_meta( $revision_id, $post_id, $meta_key ); 533 } 534 } 535 536 /** 537 * Copy post meta for the given key from one post to another. 538 * 539 * @param int $source_post_id Post ID to copy meta value(s) from. 540 * @param int $target_post_id Post ID to copy meta value(s) to. 541 * @param string $meta_key Meta key to copy. 542 * 543 * @since 6.4.0 544 */ 545 function _wp_copy_post_meta( $source_post_id, $target_post_id, $meta_key ) { 546 547 foreach ( get_post_meta( $source_post_id, $meta_key ) as $meta_value ) { 548 /** 549 * We use add_metadata() function vs add_post_meta() here 550 * to allow for a revision post target OR regular post. 551 */ 552 add_metadata( 'post', $target_post_id, $meta_key, wp_slash( $meta_value ) ); 553 } 554 } 555 556 /** 557 * Determine which post meta fields should be revisioned. 558 * 559 * @since 6.4.0 560 * 561 * @param string $post_type The post type being revisioned. 562 * 563 * @return array An array of meta keys to be revisioned. 564 */ 565 function wp_post_revision_meta_keys( $post_type ) { 566 $registered_meta = array_merge( 567 get_registered_meta_keys( 'post' ), 568 get_registered_meta_keys( 'post', $post_type ) 569 ); 570 571 $wp_revisioned_meta_keys = array(); 572 573 foreach ( $registered_meta as $name => $args ) { 574 if ( $args['revisions_enabled'] ) { 575 $wp_revisioned_meta_keys[ $name ] = true; 576 } 577 } 578 579 $wp_revisioned_meta_keys = array_keys( $wp_revisioned_meta_keys ); 580 581 /** 582 * Filter the list of post meta keys to be revisioned. 583 * 584 * @since 6.4.0 585 * 586 * @param array $keys An array of meta fields to be revisioned. 587 * @param string $post_type The post type being revisioned. 588 */ 589 return apply_filters( 'wp_post_revision_meta_keys', $wp_revisioned_meta_keys, $post_type ); 590 } 591 592 /** 593 * Check whether revisioned post meta fields have changed. 594 * 595 * @param bool $post_has_changed Whether the post has changed. 596 * @param WP_Post $last_revision The last revision post object. 597 * @param WP_Post $post The post object. 598 * 599 * @since 6.4.0 600 */ 601 function wp_check_revisioned_meta_fields_have_changed( $post_has_changed, WP_Post $last_revision, WP_Post $post ) { 602 foreach ( wp_post_revision_meta_keys( $post->post_type ) as $meta_key ) { 603 if ( get_post_meta( $post->ID, $meta_key ) !== get_post_meta( $last_revision->ID, $meta_key ) ) { 604 $post_has_changed = true; 605 break; 606 } 607 } 608 return $post_has_changed; 609 } 610 466 611 /** 467 612 * Deletes a revision. 468 613 * … … function _set_preview( $post ) { 728 873 729 874 add_filter( 'get_the_terms', '_wp_preview_terms_filter', 10, 3 ); 730 875 add_filter( 'get_post_metadata', '_wp_preview_post_thumbnail_filter', 10, 3 ); 876 add_filter( 'get_post_metadata', '_wp_preview_meta_filter', 10, 4 ); 731 877 732 878 return $post; 733 879 } … … function _wp_upgrade_revisions_of_post( $post, $revisions ) { 946 1092 947 1093 return true; 948 1094 } 1095 1096 /** 1097 * Filters preview post meta retrieval to get values from the autosave. 1098 * 1099 * Filters revisioned meta keys only. 1100 * 1101 * @since 6.4.0 1102 * 1103 * @param mixed $value Meta value to filter. 1104 * @param int $object_id Object ID. 1105 * @param string $meta_key Meta key to filter a value for. 1106 * @param bool $single Whether to return a single value. Default false. 1107 * @return mixed Original meta value if the meta key isn't revisioned, the object doesn't exist, 1108 * the post type is a revision or the post ID doesn't match the object ID. 1109 * Otherwise, the revisioned meta value is returned for the preview. 1110 */ 1111 function _wp_preview_meta_filter( $value, $object_id, $meta_key, $single ) { 1112 1113 $post = get_post(); 1114 if ( 1115 empty( $post ) || 1116 $post->ID !== $object_id || 1117 ! in_array( $meta_key, wp_post_revision_meta_keys( $post->post_type ), true ) || 1118 'revision' === $post->post_type 1119 ) { 1120 return $value; 1121 } 1122 1123 $preview = wp_get_post_autosave( $post->ID ); 1124 if ( ! is_object( $preview ) ) { 1125 return $value; 1126 } 1127 1128 return get_post_meta( $preview->ID, $meta_key, $single ); 1129 } -
tests/phpunit/tests/meta/registerMeta.php
diff --git tests/phpunit/tests/meta/registerMeta.php tests/phpunit/tests/meta/registerMeta.php index 4b08e4d82b..2699c636a8 100644
class Tests_Meta_Register_Meta extends WP_UnitTestCase { 97 97 'sanitize_callback' => null, 98 98 'auth_callback' => '__return_true', 99 99 'show_in_rest' => false, 100 'revisions_enabled' => false, 100 101 ), 101 102 ), 102 103 ), … … class Tests_Meta_Register_Meta extends WP_UnitTestCase { 121 122 'sanitize_callback' => null, 122 123 'auth_callback' => '__return_true', 123 124 'show_in_rest' => false, 125 'revisions_enabled' => false, 124 126 ), 125 127 ), 126 128 ), … … class Tests_Meta_Register_Meta extends WP_UnitTestCase { 175 177 'sanitize_callback' => array( $this, '_new_sanitize_meta_cb' ), 176 178 'auth_callback' => '__return_true', 177 179 'show_in_rest' => false, 180 'revisions_enabled' => false, 178 181 ), 179 182 ), 180 183 ), … … class Tests_Meta_Register_Meta extends WP_UnitTestCase { 342 345 'sanitize_callback' => null, 343 346 'auth_callback' => '__return_true', 344 347 'show_in_rest' => false, 348 'revisions_enabled' => false, 345 349 ), 346 350 ), 347 351 ), … … class Tests_Meta_Register_Meta extends WP_UnitTestCase { 395 399 'sanitize_callback' => null, 396 400 'auth_callback' => '__return_true', 397 401 'show_in_rest' => false, 402 'revisions_enabled' => false, 398 403 ), 399 404 ), 400 405 ), -
new file tests/phpunit/tests/post/metaRevisions.php
diff --git tests/phpunit/tests/post/metaRevisions.php tests/phpunit/tests/post/metaRevisions.php new file mode 100644 index 0000000000..596ff4b094
- + 1 <?php 2 3 /** 4 * 5 * Tests for post meta revisioning. 6 * 7 * @group post 8 * @group revision 9 * @group meta 10 * @group meta-revisions 11 */ 12 class MetaRevisionTests extends WP_UnitTestCase { 13 14 /** 15 * Callback function to add the revisioned keys. 16 * 17 * @param array $keys The array of revisioned keys. 18 * 19 * @return array 20 */ 21 public function add_revisioned_keys( $keys ) { 22 $keys[] = 'meta_revision_test'; 23 $keys[] = 'meta_multiples_test'; 24 return $keys; 25 } 26 27 /** 28 * Test the revisions system for storage of meta values with slashes. 29 * 30 * @param string $passed The passed data for testing. 31 * 32 * @param string $expected The expected value after storing & retrieving. 33 * 34 * @group revision 35 * @group slashed 36 * @dataProvider slashed_data_provider 37 */ 38 public function test_revisions_stores_meta_values_with_slashes( $passed, $expected ) { 39 // Set up a new post. 40 $post_id = $this->factory->post->create(); 41 42 // And update to store an initial revision. 43 wp_update_post( 44 array( 45 'post_content' => 'some initial content', 46 'ID' => $post_id, 47 ) 48 ); 49 add_filter( 'wp_post_revision_meta_keys', array( $this, 'add_revisioned_keys' ) ); 50 51 // Store a custom meta value, which is not revisioned by default. 52 update_post_meta( $post_id, 'meta_revision_test', wp_slash( $passed ) ); 53 $this->assertEquals( $expected, get_post_meta( $post_id, 'meta_revision_test', true ) ); 54 55 // Update the post, storing a revision. 56 wp_update_post( 57 array( 58 'post_content' => 'some more content', 59 'ID' => $post_id, 60 ) 61 ); 62 63 // Overwrite. 64 update_post_meta( $post_id, 'meta_revision_test', 'original' ); 65 // Update the post, storing a revision. 66 wp_update_post( 67 array( 68 'post_content' => 'some more content again', 69 'ID' => $post_id, 70 ) 71 ); 72 73 // Restore the previous revision. 74 $revisions = (array) wp_get_post_revisions( $post_id ); 75 76 // Go back to load the previous revision. 77 array_shift( $revisions ); 78 $last_revision = array_shift( $revisions ); 79 80 // Restore! 81 wp_restore_post_revision( $last_revision->ID ); 82 83 $this->assertEquals( $expected, get_post_meta( $post_id, 'meta_revision_test', true ) ); 84 } 85 86 /** 87 * Provide data for the slashed data tests. 88 */ 89 public function slashed_data_provider() { 90 return array( 91 array( 92 'some\text', 93 'some\text', 94 ), 95 array( 96 'test some\ \\extra \\\slashed \\\\text ', 97 'test some\ \\extra \\\slashed \\\\text ', 98 ), 99 array( 100 "This \'is\' an example \n of a \"quoted\" string", 101 "This \'is\' an example \n of a \"quoted\" string", 102 ), 103 array( 104 'some unslashed text just to test! % & * ( ) #', 105 'some unslashed text just to test! % & * ( ) #', 106 ), 107 ); 108 } 109 110 /** 111 * Test the revisions system for storage of meta values. 112 * 113 * @group revision 114 */ 115 public function test_revisions_stores_meta_values() { 116 /* 117 * Set Up. 118 */ 119 120 // Set up a new post. 121 $post_id = $this->factory->post->create(); 122 $original_post_id = $post_id; 123 124 // And update to store an initial revision. 125 wp_update_post( 126 array( 127 'post_content' => 'some initial content', 128 'ID' => $post_id, 129 ) 130 ); 131 132 // One revision so far. 133 $revisions = wp_get_post_revisions( $post_id ); 134 $this->assertCount( 1, $revisions ); 135 136 /* 137 * First set up a meta value. 138 */ 139 140 // Store a custom meta value, which is not revisioned by default. 141 update_post_meta( $post_id, 'meta_revision_test', 'original' ); 142 143 // Update the post, storing a revision. 144 wp_update_post( 145 array( 146 'post_content' => 'some more content', 147 'ID' => $post_id, 148 ) 149 ); 150 151 $revisions = wp_get_post_revisions( $post_id ); 152 $this->assertCount( 2, $revisions ); 153 154 // Next, store some updated meta values for the same key. 155 update_post_meta( $post_id, 'meta_revision_test', 'update1' ); 156 157 // Save the post, changing content to force a revision. 158 wp_update_post( 159 array( 160 'post_content' => 'some updated content', 161 'ID' => $post_id, 162 ) 163 ); 164 165 $revisions = wp_get_post_revisions( $post_id ); 166 $this->assertCount( 3, $revisions ); 167 168 /* 169 * Now restore the original revision. 170 */ 171 172 // Restore the previous revision. 173 $revisions = (array) wp_get_post_revisions( $post_id ); 174 175 // Go back two to load the previous revision. 176 array_shift( $revisions ); 177 $last_revision = array_shift( $revisions ); 178 179 // Restore! 180 wp_restore_post_revision( $last_revision->ID ); 181 182 wp_update_post( array( 'ID' => $post_id ) ); 183 $revisions = wp_get_post_revisions( $post_id ); 184 $this->assertCount( 4, $revisions ); 185 186 /* 187 * Check the meta values to verify they are NOT revisioned - they are not revisioned by default. 188 */ 189 190 // Custom post meta should NOT be restored, orignal value should not be restored, value still 'update1'. 191 $this->assertEquals( 'update1', get_post_meta( $post_id, 'meta_revision_test', true ) ); 192 193 update_post_meta( $post_id, 'meta_revision_test', 'update2' ); 194 195 /* 196 * Test the revisioning of custom meta when enabled by the wp_post_revision_meta_keys filter. 197 */ 198 199 // Add the custom field to be revised via the wp_post_revision_meta_keys filter. 200 add_filter( 'wp_post_revision_meta_keys', array( $this, 'add_revisioned_keys' ) ); 201 202 // Save the post, changing content to force a revision. 203 wp_update_post( 204 array( 205 'post_content' => 'more updated content', 206 'ID' => $post_id, 207 ) 208 ); 209 210 $revisions = array_values( wp_get_post_revisions( $post_id ) ); 211 $this->assertCount( 5, $revisions ); 212 $this->assertEquals( 'update2', get_post_meta( $revisions[0]->ID, 'meta_revision_test', true ) ); 213 214 // Store custom meta values, which should now be revisioned. 215 update_post_meta( $post_id, 'meta_revision_test', 'update3' ); 216 217 /* 218 * Save the post again, custom meta should now be revisioned. 219 * 220 * Note that a revision is saved even though there is no change 221 * in post content, because the revisioned post_meta has changed. 222 */ 223 wp_update_post( 224 array( 225 'ID' => $post_id, 226 ) 227 ); 228 229 // This revision contains the existing post meta ('update3'). 230 $revisions = wp_get_post_revisions( $post_id ); 231 $this->assertCount( 6, $revisions ); 232 233 // Verify that previous post meta is set. 234 $this->assertEquals( 'update3', get_post_meta( $post_id, 'meta_revision_test', true ) ); 235 236 // Restore the previous revision. 237 $revisions = wp_get_post_revisions( $post_id ); 238 239 // Go back two to load the previous revision. 240 array_shift( $revisions ); 241 $last_revision = array_shift( $revisions ); 242 wp_restore_post_revision( $last_revision->ID ); 243 244 /* 245 * Verify that previous post meta is restored. 246 */ 247 $this->assertEquals( 'update2', get_post_meta( $post_id, 'meta_revision_test', true ) ); 248 249 // Try storing a blank meta. 250 update_post_meta( $post_id, 'meta_revision_test', '' ); 251 wp_update_post( 252 array( 253 'ID' => $post_id, 254 ) 255 ); 256 257 update_post_meta( $post_id, 'meta_revision_test', 'update 4' ); 258 wp_update_post( 259 array( 260 'ID' => $post_id, 261 ) 262 ); 263 264 // Restore the previous revision. 265 $revisions = wp_get_post_revisions( $post_id ); 266 array_shift( $revisions ); 267 $last_revision = array_shift( $revisions ); 268 wp_restore_post_revision( $last_revision->ID ); 269 270 /* 271 * Verify that previous blank post meta is restored. 272 */ 273 $this->assertEquals( '', get_post_meta( $post_id, 'meta_revision_test', true ) ); 274 275 /* 276 * Test not tracking a key - remove the key from the revisioned meta. 277 */ 278 remove_all_filters( 'wp_post_revision_meta_keys' ); 279 280 // Meta should no longer be revisioned. 281 update_post_meta( $post_id, 'meta_revision_test', 'update 5' ); 282 wp_update_post( 283 array( 284 'ID' => $post_id, 285 'post_content' => 'changed content', 286 ) 287 ); 288 update_post_meta( $post_id, 'meta_revision_test', 'update 6' ); 289 wp_update_post( 290 array( 291 'ID' => $post_id, 292 'post_content' => 'go updated content', 293 ) 294 ); 295 296 // Restore the previous revision. 297 $revisions = wp_get_post_revisions( $post_id ); 298 array_shift( $revisions ); 299 $last_revision = array_shift( $revisions ); 300 wp_restore_post_revision( $last_revision->ID ); 301 302 /* 303 * Verify that previous post meta is NOT restored. 304 */ 305 $this->assertEquals( 'update 6', get_post_meta( $post_id, 'meta_revision_test', true ) ); 306 307 // Add the custom field to be revised via the wp_post_revision_meta_keys filter. 308 add_filter( 'wp_post_revision_meta_keys', array( $this, 'add_revisioned_keys' ) ); 309 310 /* 311 * Test the revisioning of multiple meta keys. 312 */ 313 314 // Add three values for meta. 315 update_post_meta( $post_id, 'meta_revision_test', 'update 7' ); 316 add_post_meta( $post_id, 'meta_revision_test', 'update 7 number 2' ); 317 add_post_meta( $post_id, 'meta_revision_test', 'update 7 number 3' ); 318 wp_update_post( array( 'ID' => $post_id ) ); 319 320 // Update all three values. 321 update_post_meta( $post_id, 'meta_revision_test', 'update 8', 'update 7' ); 322 update_post_meta( $post_id, 'meta_revision_test', 'update 8 number 2', 'update 7 number 2' ); 323 update_post_meta( $post_id, 'meta_revision_test', 'update 8 number 3', 'update 7 number 3' ); 324 325 // Restore the previous revision. 326 $revisions = wp_get_post_revisions( $post_id ); 327 $last_revision = array_shift( $revisions ); 328 wp_restore_post_revision( $last_revision->ID ); 329 330 /* 331 * Verify that multiple metas stored correctly. 332 */ 333 $this->assertEquals( array( 'update 7', 'update 7 number 2', 'update 7 number 3' ), get_post_meta( $post_id, 'meta_revision_test' ) ); 334 335 /* 336 * Test the revisioning of a multidimensional array. 337 */ 338 $test_array = array( 339 'a' => array( 340 '1', 341 '2', 342 '3', 343 ), 344 'b' => 'ok', 345 'c' => array( 346 'multi' => array( 347 'a', 348 'b', 349 'c', 350 ), 351 'not' => 'ok', 352 ), 353 ); 354 355 // Clear any old value. 356 delete_post_meta( $post_id, 'meta_revision_test' ); 357 358 // Set the test meta to the array. 359 update_post_meta( $post_id, 'meta_revision_test', $test_array ); 360 361 // Update to save. 362 wp_update_post( array( 'ID' => $post_id ) ); 363 364 // Set the test meta blank. 365 update_post_meta( $post_id, 'meta_revision_test', '' ); 366 367 // Restore the previous revision. 368 $revisions = wp_get_post_revisions( $post_id ); 369 $last_revision = array_shift( $revisions ); 370 wp_restore_post_revision( $last_revision->ID ); 371 372 /* 373 * Verify multidimensional array stored correctly. 374 */ 375 $stored_array = get_post_meta( $post_id, 'meta_revision_test' ); 376 $this->assertEquals( $test_array, $stored_array[0] ); 377 /* 378 379 * Test multiple revisions on the same key. 380 */ 381 382 // Set the test meta to the array. 383 add_post_meta( $post_id, 'meta_multiples_test', 'test1' ); 384 add_post_meta( $post_id, 'meta_multiples_test', 'test2' ); 385 add_post_meta( $post_id, 'meta_multiples_test', 'test3' ); 386 387 // Update to save. 388 wp_update_post( array( 'ID' => $post_id ) ); 389 390 $stored_array = get_post_meta( $post_id, 'meta_multiples_test' ); 391 $expect = array( 'test1', 'test2', 'test3' ); 392 393 $this->assertEquals( $expect, $stored_array ); 394 395 // Restore the previous revision. 396 $revisions = wp_get_post_revisions( $post_id ); 397 $last_revision = array_shift( $revisions ); 398 wp_restore_post_revision( $last_revision->ID ); 399 400 $stored_array = get_post_meta( $post_id, 'meta_multiples_test' ); 401 $expect = array( 'test1', 'test2', 'test3' ); 402 403 $this->assertEquals( $expect, $stored_array ); 404 405 // Cleanup! 406 wp_delete_post( $original_post_id ); 407 } 408 409 /** 410 * Verify that only existing meta is revisioned. 411 */ 412 public function only_existing_meta_is_revisioned() { 413 add_filter( 'wp_post_revision_meta_keys', array( $this, 'add_revisioned_keys' ) ); 414 415 // Set up a new post. 416 $post_id = $this->factory->post->create( 417 array( 418 'post_content' => 'initial content', 419 ) 420 ); 421 422 // Revision v1. 423 wp_update_post( 424 array( 425 'ID' => $post_id, 426 'post_content' => 'updated content v1', 427 ) 428 ); 429 430 $this->assertPostNotHasMetaKey( $post_id, 'foo' ); 431 $this->assertPostNotHasMetaKey( $post_id, 'bar' ); 432 433 $revisions = wp_get_post_revisions( $post_id ); 434 $revision = array_shift( $revisions ); 435 $this->assertEmpty( get_metadata( 'post', $revision->ID ) ); 436 437 // Revision v2. 438 wp_update_post( 439 array( 440 'ID' => $post_id, 441 'post_content' => 'updated content v2', 442 'meta_input' => array( 443 'foo' => 'foo v2', 444 ), 445 ) 446 ); 447 448 $this->assertPostHasMetaKey( $post_id, 'foo' ); 449 $this->assertPostNotHasMetaKey( $post_id, 'bar' ); 450 $this->assertPostNotHasMetaKey( $post_id, 'meta_revision_test' ); 451 452 $revisions = wp_get_post_revisions( $post_id ); 453 $revision = array_shift( $revisions ); 454 $this->assertPostHasMetaKey( $revision->ID, 'foo' ); 455 $this->assertPostNotHasMetaKey( $revision->ID, 'bar' ); 456 $this->assertPostNotHasMetaKey( $revision->ID, 'meta_revision_test' ); 457 } 458 459 /** 460 * Verify that blank strings are revisioned correctly. 461 */ 462 public function blank_meta_is_revisioned() { 463 464 add_filter( 'wp_post_revision_meta_keys', array( $this, 'add_revisioned_keys' ) ); 465 466 // Set up a new post. 467 $post_id = $this->factory->post->create( 468 array( 469 'post_content' => 'initial content', 470 'meta_input' => array( 471 'foo' => 'foo', 472 ), 473 ) 474 ); 475 476 // Set the test meta to an empty string. 477 update_post_meta( $post_id, 'foo', '' ); 478 479 // Update to save. 480 wp_update_post( array( 'ID' => $post_id ) ); 481 482 $stored_array = get_post_meta( $post_id, 'meta_multiples_test' ); 483 $expect = array( 'test1', 'test2', 'test3' ); 484 485 $this->assertEquals( $expect, $stored_array ); 486 487 // Restore the previous revision. 488 $revisions = wp_get_post_revisions( $post_id ); 489 $last_revision = array_shift( $revisions ); 490 wp_restore_post_revision( $last_revision->ID ); 491 $stored_data = get_post_meta( $post_id, 'foo' ); 492 $this->assertEquals( '', $stored_data[0] ); 493 } 494 495 496 /** 497 * @dataProvider data_register_post_meta_supports_revisions 498 */ 499 public function test_register_post_meta_supports_revisions( $post_type, $meta_key, $args, $expected_is_revisioned ) { 500 register_post_meta( $post_type, $meta_key, $args ); 501 502 // Set up a new post. 503 $post_id = $this->factory->post->create( 504 array( 505 'post_content' => 'initial content', 506 'post_type' => $post_type, 507 'meta_input' => array( 508 $meta_key => 'foo', 509 ), 510 ) 511 ); 512 513 // Update the post meta and post to save. 514 update_post_meta( $post_id, $meta_key, 'bar' ); 515 wp_update_post( 516 array( 517 'ID' => $post_id, 518 'post_title' => 'updated title', 519 ) 520 ); 521 522 // Check the last revision for the post to see if the meta key was revisioned 523 $revisions = wp_get_post_revisions( $post_id ); 524 $revision = array_shift( $revisions ); 525 $revisioned_meta = get_post_meta( $revision->ID, $meta_key, true ); 526 $this->assertEquals( $expected_is_revisioned, 'bar' === $revisioned_meta ); 527 528 // Reset global so subsequent data tests do not get polluted. 529 $GLOBALS['wp_meta_keys'] = array(); 530 } 531 532 public function data_register_post_meta_supports_revisions() { 533 return array( 534 array( 'post', 'registered_key1', array( 'single' => true ), false ), 535 array( 536 'post', 537 'registered_key1', 538 array( 539 'single' => true, 540 'revisions_enabled' => true, 541 ), 542 true, 543 ), 544 array( 'page', 'registered_key2', array( 'revisions_enabled' => false ), false ), 545 array( 'page', 'registered_key2', array( 'revisions_enabled' => true ), true ), 546 array( '', 'registered_key3', array( 'revisions_enabled' => false ), false ), 547 array( '', 'registered_key3', array( 'revisions_enabled' => true ), true ), 548 ); 549 } 550 551 /** 552 * Assert the a post has a meta key. 553 * 554 * @param int $post_id The ID of the post to check. 555 * @param string $meta_key The meta key to check for. 556 */ 557 protected function assertPostHasMetaKey( $post_id, $meta_key ) { 558 $this->assertArrayHasKey( $meta_key, get_metadata( 'post', $post_id ) ); 559 } 560 561 /** 562 * Assert that post does not have a meta key. 563 * 564 * @param int $post_id The ID of the post to check. 565 * @param string $meta_key The meta key to check for. 566 */ 567 protected function assertPostNotHasMetaKey( $post_id, $meta_key ) { 568 $this->assertArrayNotHasKey( $meta_key, get_metadata( 'post', $post_id ) ); 569 } 570 571 /** 572 * Test post meta revisioning with a custom post type, as well as the "page" post type. 573 * 574 * @dataProvider page_post_type_data_provider 575 */ 576 public function test_revisions_stores_meta_values_page_and_cpt( $passed, $expected, $post_type, $supports_revisions = false ) { 577 578 // If the post type doesn't exist, create it, potentially supporting revisions. 579 if ( ! post_type_exists( $post_type ) ) { 580 register_post_type( 581 $post_type, 582 array( 583 'public' => true, 584 'supports' => $supports_revisions ? array( 'revisions' ) : array(), 585 ) 586 ); 587 } 588 589 // Create a test post. 590 $page_id = $this->factory->post->create( 591 array( 592 'post_type' => $post_type, 593 'post_content' => 'some initial content', 594 ) 595 ); 596 597 // Add the revisioning filter. 598 add_filter( 'wp_post_revision_meta_keys', array( $this, 'add_revisioned_keys' ) ); 599 600 // Test revisioning. 601 update_post_meta( $page_id, 'meta_revision_test', wp_slash( $passed ) ); 602 603 // Update the post, storing a revision. 604 wp_update_post( 605 array( 606 'post_content' => 'some more content', 607 'ID' => $page_id, 608 ) 609 ); 610 611 // Retrieve the created revision. 612 $revisions = (array) wp_get_post_revisions( $page_id ); 613 614 if ( $expected ) { 615 // Go back to load the previous revision. 616 $last_revision = array_shift( $revisions ); 617 wp_restore_post_revision( $last_revision->ID ); 618 $this->assertEquals( $expected, get_post_meta( $page_id, 'meta_revision_test', true ) ); 619 } else { 620 $this->assertEmpty( $revisions ); 621 } 622 } 623 624 /** 625 * Provide data for the page post type tests. 626 */ 627 public function page_post_type_data_provider() { 628 return array( 629 array( 630 'Test string', 631 'Test string', 632 'page', 633 ), 634 array( 635 'Test string', 636 false, 637 'custom_type', 638 ), 639 array( 640 'Test string', 641 'Test string', 642 'custom_type', 643 true, 644 ), 645 ); 646 } 647 } -
tests/phpunit/tests/rest-api/rest-autosaves-controller.php
diff --git tests/phpunit/tests/rest-api/rest-autosaves-controller.php tests/phpunit/tests/rest-api/rest-autosaves-controller.php index fd8f92f7b0..4108d05efc 100644
class WP_Test_REST_Autosaves_Controller extends WP_Test_REST_Post_Type_Controlle 215 215 'author', 216 216 'date', 217 217 'date_gmt', 218 'id', 219 'meta', 218 220 'modified', 219 221 'modified_gmt', 220 'guid',221 'id',222 222 'parent', 223 223 'slug', 224 'guid', 224 225 'title', 225 226 'excerpt', 226 227 'content', … … class WP_Test_REST_Autosaves_Controller extends WP_Test_REST_Post_Type_Controlle 288 289 $response = rest_get_server()->dispatch( $request ); 289 290 $data = $response->get_data(); 290 291 $properties = $data['schema']['properties']; 291 $this->assertCount( 1 3, $properties );292 $this->assertCount( 14, $properties ); 292 293 $this->assertArrayHasKey( 'author', $properties ); 293 294 $this->assertArrayHasKey( 'content', $properties ); 294 295 $this->assertArrayHasKey( 'date', $properties ); … … class WP_Test_REST_Autosaves_Controller extends WP_Test_REST_Post_Type_Controlle 302 303 $this->assertArrayHasKey( 'slug', $properties ); 303 304 $this->assertArrayHasKey( 'title', $properties ); 304 305 $this->assertArrayHasKey( 'preview_link', $properties ); 306 $this->assertArrayHasKey( 'meta', $properties ); 305 307 } 306 308 307 309 public function test_create_item() { -
tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php
diff --git tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php index 9e580d5f3c..30e5b983ea 100644
class WP_REST_Global_Styles_Revisions_Controller_Test extends WP_Test_REST_Contr 132 132 ), 133 133 ); 134 134 135 wp_update_post( $new_styles_post, true , false);135 wp_update_post( $new_styles_post, true ); 136 136 137 137 $new_styles_post = array( 138 138 'ID' => self::$global_styles_id, … … class WP_REST_Global_Styles_Revisions_Controller_Test extends WP_Test_REST_Contr 162 162 ), 163 163 ); 164 164 165 wp_update_post( $new_styles_post, true , false);165 wp_update_post( $new_styles_post, true ); 166 166 167 167 $new_styles_post = array( 168 168 'ID' => self::$global_styles_id, … … class WP_REST_Global_Styles_Revisions_Controller_Test extends WP_Test_REST_Contr 192 192 ), 193 193 ); 194 194 195 wp_update_post( $new_styles_post, true , false);195 wp_update_post( $new_styles_post, true ); 196 196 wp_set_current_user( 0 ); 197 197 } 198 198 … … class WP_REST_Global_Styles_Revisions_Controller_Test extends WP_Test_REST_Contr 326 326 'post_content' => wp_json_encode( $config ), 327 327 ); 328 328 329 wp_update_post( $updated_styles_post, true , false);329 wp_update_post( $updated_styles_post, true ); 330 330 331 331 $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions' ); 332 332 $response = rest_get_server()->dispatch( $request ); -
tests/phpunit/tests/rest-api/rest-post-meta-fields.php
diff --git tests/phpunit/tests/rest-api/rest-post-meta-fields.php tests/phpunit/tests/rest-api/rest-post-meta-fields.php index 11d06b86be..d049f7cce4 100644
class WP_Test_REST_Post_Meta_Fields extends WP_Test_REST_TestCase { 17 17 'cpt', 18 18 array( 19 19 'show_in_rest' => true, 20 'supports' => array( 'custom-fields' ),20 'supports' => array( 'custom-fields', 'revisions' ), 21 21 ) 22 22 ); 23 23 … … class WP_Test_REST_Post_Meta_Fields extends WP_Test_REST_TestCase { 157 157 'cpt', 158 158 array( 159 159 'show_in_rest' => true, 160 'supports' => array( 'custom-fields' ),160 'supports' => array( 'custom-fields', 'revisions' ), 161 161 ) 162 162 ); 163 163 … … class WP_Test_REST_Post_Meta_Fields extends WP_Test_REST_TestCase { 1376 1376 * @dataProvider data_update_value_return_success_with_same_value 1377 1377 */ 1378 1378 public function test_update_value_return_success_with_same_value( $meta_key, $meta_value ) { 1379 add_post_meta( self::$post_id, $meta_key, $meta_value );1380 1381 1379 $this->grant_write_permission(); 1382 1380 1383 1381 $data = array( … … class WP_Test_REST_Post_Meta_Fields extends WP_Test_REST_TestCase { 1392 1390 $response = rest_get_server()->dispatch( $request ); 1393 1391 1394 1392 $this->assertSame( 200, $response->get_status() ); 1393 1394 // Verify the returned meta value is correct. 1395 $data = $response->get_data(); 1396 $this->assertArrayHasKey( 'meta', $data ); 1397 $this->assertArrayHasKey( $meta_key, $data['meta'] ); 1398 $this->assertSame( $meta_value, $data['meta'][ $meta_key ] ); 1399 1395 1400 } 1396 1401 1397 1402 public function data_update_value_return_success_with_same_value() { … … class WP_Test_REST_Post_Meta_Fields extends WP_Test_REST_TestCase { 3112 3117 } 3113 3118 return $query; 3114 3119 } 3120 3121 3122 /** 3123 * Test that single post meta is revisioned when saving to the posts REST API endpoint. 3124 * 3125 * @ticket 20564 3126 */ 3127 public function test_revisioned_single_post_meta_with_posts_endpoint() { 3128 $this->grant_write_permission(); 3129 3130 register_post_meta( 3131 'post', 3132 'foo', 3133 array( 3134 'single' => true, 3135 'show_in_rest' => true, 3136 'revisions_enabled' => true, 3137 ) 3138 ); 3139 3140 $post_id = self::$post_id; 3141 3142 // Update the post, saving the meta. 3143 $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', $post_id ) ); 3144 $request->set_body_params( 3145 array( 3146 'title' => 'Revision 1', 3147 'meta' => array( 3148 'foo' => 'bar', 3149 ), 3150 ) 3151 ); 3152 $response = rest_get_server()->dispatch( $request ); 3153 $this->assertSame( 200, $response->get_status() ); 3154 3155 // Get the last revision. 3156 $revisions = wp_get_post_revisions( $post_id, array( 'posts_per_page' => 1 ) ); 3157 $revision_id = array_shift( $revisions )->ID; 3158 3159 // @todo Ensure the revisions endpoint returns the correct meta values 3160 // Check that the revisions endpoint returns the correct meta value. 3161 $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d/revisions/%d', $post_id, $revision_id ) ); 3162 $response = rest_get_server()->dispatch( $request ); 3163 $this->assertSame( 200, $response->get_status() ); 3164 $data = $response->get_data(); 3165 $this->assertSame( 'bar', $response->get_data()['meta']['foo'] ); 3166 3167 // Check that the post meta is set correctly. 3168 $this->assertSame( 'bar', get_post_meta( $revision_id, 'foo', true ) ); 3169 3170 // Create two more revisions with different meta values for the foo key. 3171 $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', $post_id ) ); 3172 $request->set_body_params( 3173 array( 3174 'title' => 'Revision 2', 3175 'meta' => array( 3176 'foo' => 'baz', 3177 ), 3178 ) 3179 ); 3180 $response = rest_get_server()->dispatch( $request ); 3181 $this->assertSame( 200, $response->get_status() ); 3182 3183 // Get the last revision. 3184 $revisions = wp_get_post_revisions( $post_id, array( 'posts_per_page' => 1 ) ); 3185 $revision_id_2 = array_shift( $revisions )->ID; 3186 3187 // Check that the revision has the correct meta value. 3188 $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d/revisions/%d', $post_id, $revision_id_2 ) ); 3189 $response = rest_get_server()->dispatch( $request ); 3190 $this->assertSame( 200, $response->get_status() ); 3191 $this->assertSame( 'baz', $response->get_data()['meta']['foo'] ); 3192 3193 // Check that the post meta is set correctly. 3194 $this->assertSame( 'baz', get_post_meta( $revision_id_2, 'foo', true ) ); 3195 3196 // One more revision! 3197 $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', $post_id ) ); 3198 $request->set_body_params( 3199 array( 3200 'title' => 'Revision 3', 3201 'meta' => array( 3202 'foo' => 'qux', 3203 ), 3204 ) 3205 ); 3206 $response = rest_get_server()->dispatch( $request ); 3207 $this->assertSame( 200, $response->get_status() ); 3208 3209 // Get the last revision. 3210 $revisions = wp_get_post_revisions( $post_id, array( 'posts_per_page' => 1 ) ); 3211 $revision_id_3 = array_shift( $revisions )->ID; 3212 3213 // Check that the revision has the correct meta value. 3214 $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d/revisions/%d', $post_id, $revision_id_3 ) ); 3215 $response = rest_get_server()->dispatch( $request ); 3216 $this->assertSame( 200, $response->get_status() ); 3217 $this->assertSame( 'qux', $response->get_data()['meta']['foo'] ); 3218 3219 // Check that the post meta is set correctly. 3220 $this->assertSame( 'qux', get_post_meta( $revision_id_3, 'foo', true ) ); 3221 3222 // Restore Revision 3 and verify the post gets the correct meta value. 3223 wp_restore_post_revision( $revision_id_3 ); 3224 $this->assertSame( 'qux', get_post_meta( $post_id, 'foo', true ) ); 3225 3226 // Restore Revision 2 and verify the post gets the correct meta value. 3227 wp_restore_post_revision( $revision_id_2 ); 3228 $this->assertSame( 'baz', get_post_meta( $post_id, 'foo', true ) ); 3229 } 3230 3231 /** 3232 * Test that multi-post meta is revisioned when saving to the posts REST API endpoint. 3233 * 3234 * @ticket 20564 3235 */ 3236 public function test_revisioned_multiple_post_meta_with_posts_endpoint() { 3237 $this->grant_write_permission(); 3238 3239 register_post_meta( 3240 'post', 3241 'foo', 3242 array( 3243 'single' => false, 3244 'show_in_rest' => true, 3245 'revisions_enabled' => true, 3246 ) 3247 ); 3248 3249 $post_id = self::$post_id; 3250 3251 $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', $post_id ) ); 3252 $request->set_body_params( 3253 array( 3254 'title' => 'Revision 1', 3255 'meta' => array( 3256 'foo' => array( 3257 'bar', 3258 'bat', 3259 'baz', 3260 ), 3261 ), 3262 ) 3263 ); 3264 $response = rest_get_server()->dispatch( $request ); 3265 $this->assertSame( 200, $response->get_status() ); 3266 3267 // Log the current post meta. 3268 $meta = get_post_meta( $post_id ); 3269 3270 // Update the post. 3271 $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', $post_id ) ); 3272 $request->set_body_params( 3273 array( 3274 'title' => 'Revision 1 update', 3275 ) 3276 ); 3277 $response = rest_get_server()->dispatch( $request ); 3278 $this->assertSame( 200, $response->get_status() ); 3279 3280 // Get the last revision. 3281 $revisions = wp_get_post_revisions( $post_id, array( 'posts_per_page' => 1 ) ); 3282 $revision_id_1 = array_shift( $revisions )->ID; 3283 3284 // Check that the revision has the correct meta value. 3285 $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d/revisions/%d', $post_id, $revision_id_1 ) ); 3286 $response = rest_get_server()->dispatch( $request ); 3287 $this->assertSame( 200, $response->get_status() ); 3288 3289 $this->assertSame( 3290 array( 'bar', 'bat', 'baz' ), 3291 $response->get_data()['meta']['foo'] 3292 ); 3293 $this->assertSame( 3294 array( 'bar', 'bat', 'baz' ), 3295 get_post_meta( $revision_id_1, 'foo' ) 3296 ); 3297 3298 $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', $post_id ) ); 3299 $request->set_body_params( 3300 array( 3301 'title' => 'Revision 2', 3302 'meta' => array( 3303 'foo' => array( 3304 'car', 3305 'cat', 3306 ), 3307 ), 3308 ) 3309 ); 3310 $response = rest_get_server()->dispatch( $request ); 3311 $this->assertSame( 200, $response->get_status() ); 3312 3313 // Get the last revision. 3314 $revisions = wp_get_post_revisions( $post_id, array( 'posts_per_page' => 1 ) ); 3315 $revision_id_2 = array_shift( $revisions )->ID; 3316 3317 // Check that the revision has the correct meta value. 3318 $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d/revisions/%d', $post_id, $revision_id_2 ) ); 3319 $response = rest_get_server()->dispatch( $request ); 3320 $this->assertSame( 200, $response->get_status() ); 3321 3322 $this->assertSame( 3323 array( 'car', 'cat' ), 3324 $response->get_data()['meta']['foo'] 3325 ); 3326 $this->assertSame( array( 'car', 'cat' ), get_post_meta( $revision_id_2, 'foo' ) ); 3327 3328 $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', $post_id ) ); 3329 $request->set_body_params( 3330 array( 3331 'title' => 'Revision 3', 3332 'meta' => array( 3333 'foo' => null, 3334 ), 3335 ) 3336 ); 3337 $response = rest_get_server()->dispatch( $request ); 3338 $this->assertSame( 200, $response->get_status() ); 3339 3340 // Get the last revision. 3341 $revisions = wp_get_post_revisions( $post_id, array( 'posts_per_page' => 1 ) ); 3342 $revision_id_3 = array_shift( $revisions )->ID; 3343 3344 // Check that the revision has the correct meta value. 3345 $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d/revisions/%d', $post_id, $revision_id_3 ) ); 3346 $response = rest_get_server()->dispatch( $request ); 3347 $this->assertSame( 200, $response->get_status() ); 3348 3349 $this->assertSame( 3350 array(), 3351 $response->get_data()['meta']['foo'] 3352 ); 3353 $this->assertSame( array(), get_post_meta( $revision_id_3, 'foo' ) ); 3354 3355 // Restore Revision 3 and verify the post gets the correct meta value. 3356 wp_restore_post_revision( $revision_id_3 ); 3357 $this->assertSame( array(), get_post_meta( $post_id, 'foo' ) ); 3358 3359 // Restore Revision 2 and verify the post gets the correct meta value. 3360 wp_restore_post_revision( $revision_id_2 ); 3361 $this->assertSame( array( 'car', 'cat' ), get_post_meta( $post_id, 'foo' ) ); 3362 } 3363 3364 /** 3365 * Test post meta revisions with a custom post type and the page post type. 3366 * 3367 * @group revision 3368 * @dataProvider test_revisioned_single_post_meta_with_posts_endpoint_page_and_cpt_data_provider 3369 */ 3370 public function test_revisioned_single_post_meta_with_posts_endpoint_page_and_cpt( $passed, $expected, $post_type ) { 3371 3372 $this->grant_write_permission(); 3373 3374 // Create the custom meta. 3375 register_post_meta( 3376 $post_type, 3377 'foo', 3378 array( 3379 'show_in_rest' => true, 3380 'revisions_enabled' => true, 3381 'single' => true, 3382 'type' => 'string', 3383 ) 3384 ); 3385 3386 // Set up a new post. 3387 $post_id = $this->factory->post->create( 3388 array( 3389 'post_content' => 'initial content', 3390 'post_type' => $post_type, 3391 'meta_input' => array( 3392 'foo' => 'foo', 3393 ), 3394 ) 3395 ); 3396 3397 $plural_mapping = array( 3398 'page' => 'pages', 3399 'cpt' => 'cpt', 3400 ); 3401 $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/%s', $plural_mapping[ $post_type ] ) ); 3402 3403 $response = rest_get_server()->dispatch( $request ); 3404 3405 $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/%s/%d', $plural_mapping[ $post_type ], $post_id ) ); 3406 $request->set_body_params( 3407 array( 3408 'title' => 'Revision 1', 3409 'meta' => array( 3410 'foo' => $passed, 3411 ), 3412 ) 3413 ); 3414 3415 $response = rest_get_server()->dispatch( $request ); 3416 $this->assertSame( 200, $response->get_status() ); 3417 3418 // Update the post. 3419 $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/%s/%d', $plural_mapping[ $post_type ], $post_id ) ); 3420 $request->set_body_params( 3421 array( 3422 'title' => 'Revision 1 update', 3423 ) 3424 ); 3425 $response = rest_get_server()->dispatch( $request ); 3426 $this->assertSame( 200, $response->get_status() ); 3427 3428 // Get the last revision. 3429 $revisions = wp_get_post_revisions( $post_id, array( 'posts_per_page' => 1 ) ); 3430 3431 $revision_id_1 = array_shift( $revisions )->ID; 3432 3433 // Check that the revision has the correct meta value. 3434 $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/%s/%d/revisions/%d', $plural_mapping[ $post_type ], $post_id, $revision_id_1 ) ); 3435 $response = rest_get_server()->dispatch( $request ); 3436 $this->assertSame( 200, $response->get_status() ); 3437 3438 $this->assertSame( 3439 $passed, 3440 $response->get_data()['meta']['foo'] 3441 ); 3442 3443 $this->assertSame( 3444 array( $passed ), 3445 get_post_meta( $revision_id_1, 'foo' ) 3446 ); 3447 3448 unregister_post_meta( $post_type, 'foo' ); 3449 wp_delete_post( $post_id, true ); 3450 } 3451 3452 /** 3453 * Provide data for the meta revision checks. 3454 */ 3455 public function test_revisioned_single_post_meta_with_posts_endpoint_page_and_cpt_data_provider() { 3456 return array( 3457 array( 3458 'Test string', 3459 'Test string', 3460 'cpt', 3461 ), 3462 array( 3463 'Test string', 3464 'Test string', 3465 'page', 3466 ), 3467 array( 3468 'Test string', 3469 false, 3470 'cpt', 3471 ), 3472 3473 ); 3474 } 3115 3475 } -
tests/phpunit/tests/rest-api/rest-revisions-controller.php
diff --git tests/phpunit/tests/rest-api/rest-revisions-controller.php tests/phpunit/tests/rest-api/rest-revisions-controller.php index e0b713c882..74cd040d85 100644
class WP_Test_REST_Revisions_Controller extends WP_Test_REST_Controller_Testcase 179 179 'modified_gmt', 180 180 'guid', 181 181 'id', 182 'meta', 182 183 'parent', 183 184 'slug', 184 185 'title', … … class WP_Test_REST_Revisions_Controller extends WP_Test_REST_Controller_Testcase 335 336 $response = rest_get_server()->dispatch( $request ); 336 337 $data = $response->get_data(); 337 338 $properties = $data['schema']['properties']; 338 $this->assertCount( 1 2, $properties );339 $this->assertCount( 13, $properties ); 339 340 $this->assertArrayHasKey( 'author', $properties ); 340 341 $this->assertArrayHasKey( 'content', $properties ); 341 342 $this->assertArrayHasKey( 'date', $properties ); … … class WP_Test_REST_Revisions_Controller extends WP_Test_REST_Controller_Testcase 348 349 $this->assertArrayHasKey( 'parent', $properties ); 349 350 $this->assertArrayHasKey( 'slug', $properties ); 350 351 $this->assertArrayHasKey( 'title', $properties ); 352 $this->assertArrayHasKey( 'meta', $properties ); 351 353 } 352 354 353 355 public function test_create_item() { -
tests/phpunit/tests/user/wpRegisterPersistedPreferencesMeta.php
diff --git tests/phpunit/tests/user/wpRegisterPersistedPreferencesMeta.php tests/phpunit/tests/user/wpRegisterPersistedPreferencesMeta.php index 9c4725ffbf..8af6ae9b81 100644
class Tests_User_WpRegisterPersistedPreferencesMeta extends WP_UnitTestCase { 52 52 'additionalProperties' => true, 53 53 ), 54 54 ), 55 'revisions_enabled' => false, 55 56 ), 56 57 $wp_meta_keys['user'][''][ $meta_key ], 57 58 'The registered metadata did not have the expected structure' -
tests/qunit/fixtures/wp-api-generated.js
diff --git tests/qunit/fixtures/wp-api-generated.js tests/qunit/fixtures/wp-api-generated.js index 36cab80cc1..8341830452 100644
mockedApiResponse.postRevisions = [ 11782 11782 "excerpt": { 11783 11783 "rendered": "" 11784 11784 }, 11785 "meta": { 11786 "meta_key": "" 11787 }, 11785 11788 "_links": { 11786 11789 "parent": [ 11787 11790 { … … mockedApiResponse.postRevisions = [ 11811 11814 "excerpt": { 11812 11815 "rendered": "<p>REST API Client Fixture: Post</p>\n" 11813 11816 }, 11817 "meta": { 11818 "meta_key": "" 11819 }, 11814 11820 "_links": { 11815 11821 "parent": [ 11816 11822 { … … mockedApiResponse.revision = { 11841 11847 }, 11842 11848 "excerpt": { 11843 11849 "rendered": "<p>REST API Client Fixture: Post</p>\n" 11850 }, 11851 "meta": { 11852 "meta_key": "" 11844 11853 } 11845 11854 }; 11846 11855 … … mockedApiResponse.postAutosaves = [ 11866 11875 "excerpt": { 11867 11876 "rendered": "" 11868 11877 }, 11878 "meta": { 11879 "meta_key": "" 11880 }, 11869 11881 "_links": { 11870 11882 "parent": [ 11871 11883 { … … mockedApiResponse.autosave = { 11896 11908 }, 11897 11909 "excerpt": { 11898 11910 "rendered": "" 11911 }, 11912 "meta": { 11913 "meta_key": "" 11899 11914 } 11900 11915 }; 11901 11916 … … mockedApiResponse.pageRevisions = [ 12042 12057 "excerpt": { 12043 12058 "rendered": "" 12044 12059 }, 12060 "meta": { 12061 "meta_key": "" 12062 }, 12045 12063 "_links": { 12046 12064 "parent": [ 12047 12065 { … … mockedApiResponse.pageRevisions = [ 12071 12089 "excerpt": { 12072 12090 "rendered": "<p>REST API Client Fixture: Page</p>\n" 12073 12091 }, 12092 "meta": { 12093 "meta_key": "" 12094 }, 12074 12095 "_links": { 12075 12096 "parent": [ 12076 12097 { … … mockedApiResponse.pageRevision = { 12101 12122 }, 12102 12123 "excerpt": { 12103 12124 "rendered": "<p>REST API Client Fixture: Page</p>\n" 12125 }, 12126 "meta": { 12127 "meta_key": "" 12104 12128 } 12105 12129 }; 12106 12130 … … mockedApiResponse.pageAutosaves = [ 12126 12150 "excerpt": { 12127 12151 "rendered": "" 12128 12152 }, 12153 "meta": { 12154 "meta_key": "" 12155 }, 12129 12156 "_links": { 12130 12157 "parent": [ 12131 12158 { … … mockedApiResponse.pageAutosave = { 12156 12183 }, 12157 12184 "excerpt": { 12158 12185 "rendered": "" 12186 }, 12187 "meta": { 12188 "meta_key": "" 12159 12189 } 12160 12190 }; 12161 12191