Piping CMB2
May 14, 2015
Piping meta box field content in CMB2.
The idea
This experiment of mine falls directly into the "probably useless" bucket but still poses some challenges I'm willing to dedicate myself to as recreational coding time.
This disclaimer made the idea would be to streamline the use of the Custom Meta Boxes 2 plugin to fill post properties (columns in the database).
By defaults Custom Meta Boxes 2 will take care of saving any value to a a custom post field (a meta data) and that is fine 99% of the times.
I've found myself needing to save the content of a text field not as a post custom field but as the post title (literally the post_title
field in the `posts’ table); thanks to the hooks Custom Meta Boxes 2 offers that's easily done.
The code below will add the meta boxes to the post edit screen and will take care of saving the content of the text field to the post title read it from that:
add_action( 'cmb2_init', 'post_meta_boxes' );
function post_meta_boxes() {
$post_meta_box = new_cmb2_box( array(
'id' => 'post-metabox',
'title' => __( 'A Meta Box', 'cmb2' ),
'object_types' => array( 'post' )
) );
$post_meta_box->add_field( array(
'name' => __( 'The post title', 'cmb2' ),
'id' => 'title',
'type' => 'text_small',
) );
}
add_filter( 'cmb2_override_title_meta_save', 'save_the_post_title', 10, 4 );
function save_the_post_title( $override, $args, $field_args, CMB2_Field $field ) {
remove_filter( 'cmb2_override_title_meta_save', __FUNCTION__ );
$args = (object) $args;
$post_title = $args->value;
$post_id = $args->id;
wp_update_post( array( 'ID' => $post_id, 'post_title' => $post_title ) );
// do override, do not save the meta
return true;
}
add_filter( 'cmb2_override_title_meta_value', 'get_the_post_title', 10, 4 );
function get_the_post_title( $override, $object_id, $args, CMB2_Field $field ) {
return get_the_title( $object_id );
}
Then it works already
Yes it does. What I'd like to be able to get rid of is the necessity to manually add the two filters above (save_the_post_title
and get_the_post_title
in the example) for each field that might work in a similar way. The less painful solution I could come up with is to allow the definition of a meta box meta fields to "tell" where and if a meta field value should be "piped" and in which direction.
A possible syntax
Supposing the imaginary plugin in place I'd like to be able to do this
add_action( 'cmb2_init', 'post_meta_boxes' );
function post_meta_boxes() {
$post_meta_box = new_cmb2_box( array(
'id' => 'post-metabox',
'title' => __( 'A Meta Box', 'cmb2' ),
'object_types' => array( 'post' )
) );
$post_meta_box->add_field( array(
'name' => __( 'The post title', 'cmb2' ),
'id' => 'title',
'type' => 'text_small <> post_title',
) );
}
The line 'type' => 'text_small <> post_title'
in particular would mean "save the content of this field to the post title and read it from there"; similarly other directions should be possible.
add_action( 'cmb2_init', 'post_meta_boxes' );
function post_meta_boxes() {
$post_meta_box = new_cmb2_box( array(
'id' => 'post-metabox',
'title' => __( 'A Meta Box', 'cmb2' ),
'object_types' => array( 'post' )
) );
$post_meta_box->add_field( array(
'name' => __( 'The post title I can change and read', 'cmb2' ),
'id' => 'writable_title',
'type' => 'text_small <> post_title',
) );
$post_meta_box->add_field( array(
'name' => __( 'The post content', 'cmb2' ),
'desc' => __( 'Display only, editing the post content is not possible', 'cmb2'),
'id' => 'read_only_content',
'type' => 'title < post_content',
) );
$post_meta_box->add_field( array(
'name' => __( 'The post title I can write', 'cmb2' ),
'desc' => __('A duplicate meta data will be save for this field, if post title is changed in other way this field will not update.', 'cmb2'),
'id' => 'meta_post_title',
'type' => 'text_small > post_title',
) );
}