Commit df893e5505 for wordpress.org
commit df893e5505810bf0eea50b1434fff1c792e8b66e
Author: adamsilverstein <adamsilverstein@git.wordpress.org>
Date: Mon Oct 26 17:34:53 2026 +0000
REST API: only include revisioned meta in revision responses.
Fix an issue where restoring a revision in the editor overwrote meta values that weren't associated with the revision.
Visual Revisions in the block editor, introduced in 7.0, restores a revision by saving the `meta` returned from the revisions endpoint onto the post. That endpoint returned every `show_in_rest` meta key for the parent post type, but only revisioned keys are stored on a revision, so the rest came back as their default (or `null`) and the restore overwrote the post's real values. Unsynced patterns silently became synced, synced patterns failed to restore with a `rest_invalid_stored_value` error, and any other non-revisioned `show_in_rest` key was reset.
Introduce `WP_REST_Revision_Meta_Fields`, used by `WP_REST_Revisions_Controller`, which limits a revision's `meta` and its schema to the keys from `wp_post_revision_meta_keys()`. This matches what `wp_restore_post_revision()` restores from the classic revisions screen, and requires no editor change. Autosave responses follow the same rules, since they are prepared by the revisions controller; autosave requests still accept all of the parent post type's meta. Plugins that write meta onto revisions directly should add those keys with the `wp_post_revision_meta_keys` filter to keep them in responses.
Also fixes https://github.com/WordPress/gutenberg/issues/84809.
Props dlocc, davidsword, talldanwp, rachelbaker, prasadkarmalkar, umeshnevase.
Fixes #66329.
Built from https://develop.svn.wordpress.org/trunk@64731
git-svn-id: http://core.svn.wordpress.org/trunk@63881 1a063a9b-81f0-0310-95a4-ce76da25c4cd
diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php
index 2dbba2b6d5..9abced65e6 100644
--- a/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php
+++ b/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php
@@ -28,6 +28,7 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller {
* Instance of a revision meta fields object.
*
* @since 6.4.0
+ * @since 7.2.0 Now a WP_REST_Revision_Meta_Fields instance, which only exposes revisioned meta keys.
* @var WP_REST_Post_Meta_Fields
*/
protected $meta;
@@ -68,7 +69,7 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller {
$this->rest_base = 'revisions';
$this->parent_base = ! empty( $post_type_object->rest_base ) ? $post_type_object->rest_base : $post_type_object->name;
$this->namespace = ! empty( $post_type_object->rest_namespace ) ? $post_type_object->rest_namespace : 'wp/v2';
- $this->meta = new WP_REST_Post_Meta_Fields( $parent_post_type );
+ $this->meta = new WP_REST_Revision_Meta_Fields( $parent_post_type );
}
/**
@@ -596,6 +597,7 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller {
* @since 4.7.0
* @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support.
* @since 7.1.0 The global post is now restored to its previous value before returning.
+ * @since 7.2.0 The `meta` field only includes the meta keys that are revisioned for the parent post type.
*
* @global WP_Post|null $post Global post object.
*
@@ -813,6 +815,7 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller {
* Retrieves the revision's schema, conforming to JSON Schema.
*
* @since 4.7.0
+ * @since 7.2.0 The `meta` property only describes the meta keys that are revisioned for the parent post type.
*
* @return array Item schema data.
*/
diff --git a/wp-includes/rest-api/fields/class-wp-rest-revision-meta-fields.php b/wp-includes/rest-api/fields/class-wp-rest-revision-meta-fields.php
new file mode 100644
index 0000000000..3db7c0a6dc
--- /dev/null
+++ b/wp-includes/rest-api/fields/class-wp-rest-revision-meta-fields.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * REST API: WP_REST_Revision_Meta_Fields class
+ *
+ * @package WordPress
+ * @subpackage REST_API
+ * @since 7.2.0
+ */
+
+/**
+ * Core class used to read the meta values of post revisions via the REST API.
+ *
+ * Only the meta keys that are revisioned for the parent post type are exposed,
+ * because those are the only values that are stored on a revision. Any other
+ * meta key registered for the post type would be read from the revision ID,
+ * find nothing, and be reported with its default value instead.
+ *
+ * @since 7.2.0
+ *
+ * @see WP_REST_Post_Meta_Fields
+ * @see wp_post_revision_meta_keys()
+ */
+class WP_REST_Revision_Meta_Fields extends WP_REST_Post_Meta_Fields {
+
+ /**
+ * Retrieves the meta field values for a revision.
+ *
+ * When an author autosaves their own draft, the autosaves controller updates
+ * the post itself and returns it instead of an autosave. That post stores all
+ * of its meta, so its values are read as regular post meta.
+ *
+ * @since 7.2.0
+ *
+ * @param int $object_id Object ID to fetch meta for.
+ * @param WP_REST_Request $request Full details about the request.
+ * @return array Array containing the meta values keyed by name.
+ */
+ public function get_value( $object_id, $request ) {
+ if ( 'revision' !== get_post_type( $object_id ) ) {
+ $post_meta = new WP_REST_Post_Meta_Fields( $this->post_type );
+ return $post_meta->get_value( $object_id, $request );
+ }
+
+ return parent::get_value( $object_id, $request );
+ }
+
+ /**
+ * Retrieves the registered meta fields that are revisioned for the parent post type.
+ *
+ * @since 7.2.0
+ *
+ * @return array Registered fields, limited to the revisioned meta keys.
+ */
+ protected function get_registered_fields() {
+ // The keys are filterable, so ignore anything that isn't a meta key.
+ $revisioned_keys = array_filter( (array) wp_post_revision_meta_keys( $this->post_type ), 'is_string' );
+
+ return array_intersect_key(
+ parent::get_registered_fields(),
+ array_flip( $revisioned_keys )
+ );
+ }
+}
diff --git a/wp-includes/version.php b/wp-includes/version.php
index bd743353b4..76c3b10660 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
-$wp_version = '7.2-beta1-64730';
+$wp_version = '7.2-beta1-64731';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
diff --git a/wp-settings.php b/wp-settings.php
index cf8fb4d090..92f9456aa0 100644
--- a/wp-settings.php
+++ b/wp-settings.php
@@ -398,6 +398,7 @@ require ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-abilities-v1-run-co
require ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-meta-fields.php';
require ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-comment-meta-fields.php';
require ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-post-meta-fields.php';
+require ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-revision-meta-fields.php';
require ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-term-meta-fields.php';
require ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-user-meta-fields.php';
require ABSPATH . WPINC . '/rest-api/search/class-wp-rest-search-handler.php';