0

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.

0

I found the culprit. I had to change the nonce check in save_custom_post_type() to:

if ( !isset( $_POST['metabox_nonce'] ) || !wp_verify_nonce( $_POST['metabox_nonce'], basename( __FILE__ ) ) ) {
    return $post_id;
}
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.