I'm trying to add Gutenberg support to a plugin that registers a custom post type with a checkbox-type meta field called _meta_restrict
, while maintaining back-compatibility with the classic editor at the same time. I've made some progress but I'm stuck now and need a bit of help.
This is the relevant code I'm using to register and save the meta field value in the classic editor:
function register_meta_field() {
register_post_meta( 'custom_post_type', '_meta_restrict', array(
'show_in_rest' => true,
'single' => true,
'type' => 'boolean',
'auth_callback' => function() {
return current_user_can( 'edit_posts' );
}
) );
}
add_action( 'init', 'register_meta_field' );
function add_custom_meta_boxes() {
add_meta_box(
'custom-meta-box',
'Options',
'custom_meta_box_callback',
'custom_post_type',
'side',
'low',
array(
'__block_editor_compatible_meta_box' => false,
'__back_compat_meta_box' => true,
)
);
}
add_action( 'add_meta_boxes', 'add_custom_meta_boxes' );
function save_custom_post_type( $post_id ) {
// verify nonce
if ( isset( $_POST['metabox_nonce'] ) && !wp_verify_nonce( $_POST['metabox_nonce'], basename( __FILE__ ) ) ) {
return $post_id;
}
// is autosave?
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
// check permissions
if ( isset( $_POST['post_type'] ) ) {
if ( 'page' == $_POST['post_type'] ) {
if ( !current_user_can( 'edit_page', $post_id ) ) {
return $post_id;
}
} elseif ( !current_user_can( 'edit_post', $post_id ) ) {
return $post_id;
}
}
// save meta field
$meta_restrict = isset( $_POST['meta_restrict'] ) ? $_POST['meta_restrict'] : '';
update_post_meta( $post_id, '_meta_restrict', $meta_restrict );
}
add_action( 'save_post', 'save_custom_post_type' );
In the block editor, I added a ToggleControl
to the PluginDocumentSettingPanel
in order to manage my _meta_restrict
meta field. This is the code I came up with:
let RestrictControl = ({ restrict, onUpdateRestrict }) => (
<ToggleControl
label={ 'Restrict viewing?' }
help={ restrict ? 'Viewing is restricted.' : 'Viewing is not restricted.' }
checked={ restrict }
onChange={ restrict => onUpdateRestrict( restrict ) }
/>
);
RestrictControl = compose( [
withSelect( ( select ) => {
return {
restrict: select( 'core/editor' ).getEditedPostAttribute( 'meta' )['_meta_restrict']
};
} ),
withDispatch( ( dispatch ) => {
return {
onUpdateRestrict: ( value ) => {
dispatch( 'core/editor' ).editPost({ meta: { _meta_restrict: value } })
}
}
} ),
] )( RestrictControl );
This code works perfectly. The issue is that after the meta field value is saved via rest_insert_{$this->post_type}
, the classic editor save_post
action is also fired, so the meta field is overwritten with an empty value because $_POST['meta_restrict']
is not available in the block editor. If I comment my save_custom_post_type
function, the value is successfully saved in the block editor, but I need to provide backwards compatibility with the classic editor.
How am I supposed to do this? Why is the save_post
action fired even though __block_editor_compatible_meta_box
is set to false and __back_compat_meta_box
is set to true? Can I disable it from running when working in the block editor?
Any help would be appreciated.