I'm converting existing meta boxes in many plugin and the related meta data are saved with names prefixed by underscore, example:
_my_meta_data
The problem is that when the meta name is prefixed with underscore editPost doesn't save the meta data:
//This doesn't work because of the underscore prefix
wp.data.dispatch( 'core/editor' ).editPost(
{ meta: { _my_meta_data: 'hello world!' } }
);
And the following response is generated:
{
"code":"rest_cannot_update",
"message":"Sorry, you are not allowed to edit the _my_meta_data custom field.",
"data":{
"key":"_my_meta_data",
"status":403
}
}
The problem can easily be solved by removing the underscore like in the script below but we are working with existing meta data and the names of the meta data can't be changed:
//This works
wp.data.dispatch( 'core/editor' ).editPost(
{ meta: { my_meta_data: 'hello world!' } }
);
Do you know how to use editPost in this situation? I don't want to manually register Rest API routes with PHP and then perform requests with apiFetch() via JavaScript if not necessary.
Thank you.
You need to use register_meta / register_post_meta to register your _my_meta_data meta field. Set 'show_in_rest' => true to make it available in the REST API. Because it's a protected field (leading underscore), also set auth_callback, e.g. 'auth_callback' => true
The register_meta() function is already implemented and based on your feedback I also tried adding auth_callback => true, but this doesn't solve the issue.
If you implement the example presented in this tutorial with a meta data prefixed by underscore you receive the following answer on the endpoint /wp-json/wp/v2/posts/1048?_locale=user when the post is saved:
{
"code":"rest_cannot_update",
"message":"Sorry, you are not allowed to edit the _my_meta_data custom field.",
"data":{
"key":"_my_meta_data",
"status":403
}
}
Please note that:
The JavaScript implementation:
( function( wp ) {
var registerPlugin = wp.plugins.registerPlugin;
var PluginSidebar = wp.editPost.PluginSidebar;
var el = wp.element.createElement;
var Text = wp.components.TextControl;
var SelectControl = wp.components.SelectControl;
var withSelect = wp.data.withSelect;
var withDispatch = wp.data.withDispatch;
var MetaBlockField = function( props ) {
return el( SelectControl, {
label: 'Meta Block Field',
value: props.metaFieldValue,
options: [
{ value: '0', label: 'No' },
{ value: '1', label: 'Yes' }
],
onChange: function( content ) {
props.setMetaFieldValue( content );
},
} );
}
var MetaBlockFieldWithData = withSelect( function( select ) {
return {
metaFieldValue: select( 'core/editor' )
.getEditedPostAttribute( 'meta' )
[ '_daam_enable_autolinks' ],
}
} )( MetaBlockField );
var MetaBlockFieldWithDataAndActions = withDispatch(
function( dispatch ) {
return {
setMetaFieldValue: function( value ) {
dispatch( 'core/editor' ).editPost(
{ meta: { _daam_enable_autolinks: value } }
);
}
}
}
)( MetaBlockFieldWithData );
registerPlugin( 'my-plugin-sidebar', {
render: function() {
return el( PluginSidebar,
{
name: 'my-plugin-sidebar',
icon: 'admin-post',
title: 'My plugin sidebar',
},
el( 'div',
{ className: 'plugin-sidebar-content' },
el( MetaBlockFieldWithDataAndActions )
)
);
}
} );
} )( window.wp );
The PHP part:
register_meta( 'post', '_daam_enable_autolinks', array(
'show_in_rest' => true,
'single' => true,
'type' => 'string'
) );
I've also already verified that the meta is register and available in the data module:
wp.data.select( 'core/editor' ).getCurrentPost().meta;
I solved the issue by using a real callback function instead of auth_callback => true:
register_meta( 'post', '_my_meta_data', array(
'show_in_rest' => true,
'single' => true,
'type' => 'string',
'auth_callback' => function(){return true;}
) );
Thank you for your help.
Ugh, sorry, my bad! I meant to write 'auth_callback' => '__return_true' 🤦♂️
'auth_callback' => '__return_true' 亲测有效!
It’s best to check the user permissions in the auth_callback, verify he can edit posts or any other permission you think is relevant in you case....
When returning just ‘__return_true’ you are allowing this ability to all user in your site and it’s not wise to do so.
register_meta( 'post', '_my_meta_data', array(
'show_in_rest' => true,
'single' => true,
'type' => 'string',
'auth_callback' => function () {
return current_user_can('edit_posts');
}
) );
Most helpful comment
I solved the issue by using a real callback function instead of
auth_callback => true:Thank you for your help.