Repository navigation
Visual Revisions fail to restore meta controlled by Classic Meta Boxes #78130
Copy link
Copy link
Closed
Copy link
Labels
[Feature] HistoryHistory, undo, redo, revisions, autosave.History, undo, redo, revisions, autosave.[Status] In ProgressTracking issues with work in progressTracking issues with work in progress[Type] BugAn existing feature does not function as intendedAn existing feature does not function as intended
Description
Description
- Restoring a revision via the Visual Revisions screen does not successfully restore meta values that are controlled by a Classic Meta Box. However, meta controlled by a Gutenberg block/sidebar restores correctly. In the classic revisions screen, both restore properly.
- In the Visual Revisions sidebar, long meta keys overlap visually with the diff text values , making it unreadable.
Step-by-step reproduction instructions
- Register one classic meta box and one Gutenberg sidebar meta field, ensuring both support revisions.
- Create a new post.
- Enter a value into the "Classic Meta Field" (meta box).
- Enter a value into the "Gutenberg Meta Field" (sidebar panel).
- Publish or save the post.
- Modify both values and update the post to generate a revision.
- Open the Visual Revisions screen.
- Observe the UI: Look at the "Meta" section in the right sidebar and notice that the long meta keys overlap with the value text.
- Click Restore to revert to the previous revision.
- Observe the result: The Gutenberg Meta Field will have successfully restored to its previous value, but the Classic Meta Field will remain at the newer value.
Code I used to register the meta:
<?php
/**
* Plugin Name: MyGuten Separate Meta Test
* Description: Classic meta box + Gutenberg sidebar meta field, both REST and revision enabled.
* Version: 1.0.0
*/
if (!defined('ABSPATH')) {
exit;
}
const MYGUTEN_CLASSIC_META_KEY = 'myguten_classic_meta_field';
const MYGUTEN_GUTENBERG_META_KEY = 'myguten_gutenberg_meta_field';
/**
* Register meta fields.
*/
add_action('init', function() {
$common_args = [
'type' => 'string',
'single' => true,
'show_in_rest' => true,
'revisions_enabled' => true,
'sanitize_callback' => 'sanitize_text_field',
'auth_callback' => function () {
return current_user_can('edit_posts');
},
];
register_post_meta('post', MYGUTEN_CLASSIC_META_KEY, $common_args);
register_post_meta('post', MYGUTEN_GUTENBERG_META_KEY, $common_args);
});
/**
* Show meta fields in revisions
*/
add_filter( '_wp_post_revision_fields', function( $fields ) {
$fields[ MYGUTEN_CLASSIC_META_KEY ] = 'Classic Meta Field';
$fields[ MYGUTEN_GUTENBERG_META_KEY ] = 'Gutenberg Meta Field';
return $fields;
} );
/**
* Enqueue Block Editor Assets
*/
add_action('enqueue_block_editor_assets', function() {
$script_path = plugin_dir_path(__FILE__) . 'sidebar.js';
wp_enqueue_script(
'myguten-meta-sidebar',
plugin_dir_url(__FILE__) . 'sidebar.js',
['wp-plugins', 'wp-edit-post', 'wp-element', 'wp-components', 'wp-data', 'wp-core-data'],
file_exists($script_path) ? filemtime($script_path) : '1.0.0',
true
);
});
/**
* Classic Meta Box Setup
*/
add_action('add_meta_boxes', function() {
add_meta_box(
'myguten_classic_meta_box',
'Classic Meta Field',
'myguten_render_classic_meta_box',
'post',
'side'
);
});
function myguten_render_classic_meta_box($post) {
$value = get_post_meta($post->ID, MYGUTEN_CLASSIC_META_KEY, true);
wp_nonce_field('myguten_save_classic_meta', 'myguten_nonce');
printf(
'<input type="text" name="%1$s" value="%2$s" style="width:100%%;" />',
esc_attr(MYGUTEN_CLASSIC_META_KEY),
esc_attr($value)
);
}
/**
* Save Classic Meta
*/
add_action('save_post_post', function($post_id) {
if (!isset($_POST['myguten_nonce']) || !wp_verify_nonce($_POST['myguten_nonce'], 'myguten_save_classic_meta')) {
return;
}
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
if (!current_user_can('edit_post', $post_id)) return;
if (isset($_POST['myguten_classic_meta_field'])) {
update_post_meta($post_id, MYGUTEN_CLASSIC_META_KEY, sanitize_text_field(wp_unslash($_POST['myguten_classic_meta_field'])));
}
});( function ( wp ) {
const { registerPlugin } = wp.plugins;
const { PluginDocumentSettingPanel } = wp.editPost;
const { TextControl } = wp.components;
const { useSelect, useDispatch } = wp.data; // Added useDispatch for more control if needed
const { useEntityProp } = wp.coreData;
const { createElement: el } = wp.element;
const { __ } = wp.i18n; // For translations
const META_KEY = 'myguten_gutenberg_meta_field';
function MyGutenMetaPanel() {
const postType = useSelect( ( select ) => {
return select( 'core/editor' ).getCurrentPostType();
}, [] );
if ( ! [ 'post' ].includes( postType ) ) {
return null;
}
const [ meta, setMeta ] = useEntityProp( 'postType', postType, 'meta' );
const value = meta?.[ META_KEY ] || '';
const updateValue = ( newValue ) => {
setMeta( {
...meta,
[ META_KEY ]: newValue,
} );
};
return el(
PluginDocumentSettingPanel,
{
name: 'myguten-meta-sidebar-panel',
title: __( 'Meta block Field', 'my-text-domain' ),
className: 'myguten-meta-sidebar-panel',
},
el( TextControl, {
label: __( 'Gutenberg Meta Field', 'my-text-domain' ),
value: value,
onChange: updateValue,
help: __( 'This field saves to separate Gutenberg post meta.', 'my-text-domain' ),
} )
);
}
registerPlugin( 'myguten-meta-sidebar', {
render: MyGutenMetaPanel,
// Optional: icon: 'admin-settings',
} );
} )( window.wp );Screenshots, screen recording, code snippet
| Classic Revisions | Visual Revisions |
|---|---|
classic-revisions.mp4 |
visual-revision.mp4 |
Environment info
No response
Please confirm that you have searched existing issues in the repo.
- Yes
Please confirm that you have tested with all plugins deactivated except Gutenberg.
- Yes
Please confirm which theme type you used for testing.
- Block
- Classic
- Hybrid (e.g. classic with theme.json)
- Not sure
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
[Feature] HistoryHistory, undo, redo, revisions, autosave.History, undo, redo, revisions, autosave.[Status] In ProgressTracking issues with work in progressTracking issues with work in progress[Type] BugAn existing feature does not function as intendedAn existing feature does not function as intended
Type
Projects
- StatusShow more project fields✅ Done
Activity
t-hamano commentedon May 11, 2026
Thanks for the report.
We may need to disable the visual revision diff if the metabox is enabled. cc @ellatrix
I believe this is an issue that can be fixed separately from the metabox.
Mustafabharmal commentedon May 11, 2026
I'm working on a fix for this. The root cause for the meta restoration bug is that after
restoreRevisioncallssavePost(), theeditor.savePosthook firesrequestMetaBoxUpdates()which resubmits the classic meta box form fields with their current (unreverted) DOM values, overwriting the meta values just restored via the REST API. The fix is to pass anisRevisionsRestoreflag tosavePost()so the hook skips the meta box resubmission. The label overlap issue will be fixed withword-break: break-wordon the panel row label.ellatrix commentedon May 12, 2026
I think we should probably disable if there's classic meta boxes, but it's kind of a pity. I'd love to hear more opinions, but disabling seems like the safer thing to do at this stage.
t-hamano commentedon May 13, 2026
@Mustafabharmal, can you split #78156 into two PRs? Splitting into two PRs is easier to review and make decisions on than addressing two bugs in one PR. The two bugs are completely different in nature.
ellatrix commentedon May 13, 2026
Also made a PR in #78249.
Alternatively we have to restore on the server and reload the editor.