-
Notifications
You must be signed in to change notification settings - Fork 62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bidirectional relationship #28
Comments
This would be a great core feature of this plugin, but is not currently supported. There are plenty of hooks during the save process (both in WordPress and in CMB2) that could be leveraged to save the bidirectional data. |
I'm trying to use In this case I could compare old and new values and remove old meta values from posts that not connected anymore. I thought I could make a database query and get all posts that have this meta key and value (which is a current post id), but it's not possible as the ids from the Attached Posts Field stored in a serialized array. |
You're best bet is to get the previous values before CMB2 updates them to the DB (maybe using the |
Justin, thank you! I managed to solve it.. used the hook as you said. Works. |
Would you consider a pull request to optionally enable this feature? |
I would be glad, but I'm not sure that I'm skilled enough to make it flawlesly, Actually never done PR before. I've just recently dived into the theme of coding after 15 years pause :) I could share what I reached in my case, hopefully it may be helpful. Post A and Post B are edited in the same time. Make a relation from Post B: B<->A, saved. Relation done for both posts. Standard way of initializing function cmb2_attached_posts_for_posts() {
$prefix = '_cmb2_attached_posts';
$cmb_post = new_cmb2_box( array(
'id' => $prefix . '_metabox',
'title' => __( 'Attached Posts', 'cmb2' ),
'object_types' => array( 'post','project' ), // Post type
'context' => 'normal',
'priority' => 'high',
'show_names' => false, // Show field names on the left
) );
$cmb_post->add_field( array(
'name' => __( 'Attached Posts', 'cmb2' ),
'desc' => __( 'Drag posts from the left column to the right column to attach them to this page.<br />You may rearrange the order of the posts in the right column by dragging and dropping.', 'cmb2' ),
'id' => $prefix . '_ids',
'type' => 'custom_attached_posts',
'options' => 'do_attached_posts_options_cb',
'old_values' => '', // store old values taken in 'pre_post_update' hook , used for bidirectional relation
) );
}
add_action( 'cmb2_init', 'cmb2_attached_posts_for_posts' );
// Options callback
function do_attached_posts_options_cb( $field ) {
return array(
'show_thumbnails' => true,
'filter_boxes' => true,
'query_args' => array(
'post__not_in' => array( $field->object_id ),
'posts_per_page' => 10,
),
);
} Using function attached_posts_for_posts_get_old_values( $post_ID ) {
// check if post type is not a 'revision'. Otherwise the hook fires more than once.
if ( 'revision' !== get_post_type( $post_ID ) ) {
$old_values = get_post_meta( $post_ID,'_cmb2_attached_posts_ids', true );
// Retrieve a CMB2 instance
$cmb = cmb2_get_metabox( '_cmb2_attached_posts_metabox' );
//$old_values = $cmb->get_field( '_cmb2_attached_posts_ids' )->escaped_value();
$cmb->update_field_property( '_cmb2_attached_posts_ids', 'old_values', $old_values );
}
}
add_action( 'pre_post_update', 'attached_posts_for_posts_get_old_values' ); Using function attached_posts_for_posts_delete( $post_ID ) {
if ( ! $unbind_posts = get_post_meta( $post_ID, '_cmb2_attached_posts_ids', true ) ) {
return;
}
foreach ( $unbind_posts as $value => $id ) {
$post_values = get_post_meta( $id, '_cmb2_attached_posts_ids', true );
$pos = array_search( $post_ID, $post_values );
unset( $post_values[ $pos ] );
update_post_meta( $id, '_cmb2_attached_posts_ids', $post_values );
}
}
add_action( 'before_delete_post', 'attached_posts_for_posts_delete' ); To store and pass old values that I took in /**
* Bidirectional relation
* @param bool $updated Whether the metadata update action occurred.
* @param string $action Action performed. Could be "repeatable", "updated", or "removed".
* @param CMB2_Field object $field This field object
*/
function attached_posts_for_posts_bidirectional( $updated, $action, $field ) {
if ( ! $updated ) {
return;
}
// getting old values
$old_values = $field->args['old_values'];
// getting current post id
$object_id = $field->object_id;
// getting meta key
$meta_key = $field->args['id'];
// getting new values from the Attached Posts field
//$related_posts = $field->escaped_value();
$related_posts = get_post_meta( $object_id, $meta_key, true );
$field_ids = array();
// update meta field for each selected post with current Post ID
foreach ( (array) $related_posts as $post => $id ) {
$field_ids = get_post_meta( $id, $meta_key, true );
if ( $field_ids && in_array( $object_id ,$field_ids ) ) {
continue;
} else {
$field_ids[] = $object_id;
}
update_post_meta( $id, $meta_key, $field_ids );
}
// deleting removed relationships
$unbind_posts = array();
if ( ! empty( $related_posts ) && ! empty( $old_values ) ) {
$unbind_posts = array_diff( $old_values, $related_posts );
} elseif ( ! empty( $old_values ) ) {
$unbind_posts = $old_values;
}
foreach ( (array) $unbind_posts as $value => $post_id ) {
// check if there is no meta field by some reason
if ( ! $post_values = get_post_meta( $post_id, $meta_key, true ) ) {
continue;
}
$pos = array_search( $object_id, $post_values );
unset( $post_values[ $pos ] );
update_post_meta( $post_id, $meta_key, $post_values );
}
}
add_action( 'cmb2_save_field__cmb2_attached_posts_ids', 'attached_posts_for_posts_bidirectional', 10, 3 ); |
Hi! Is there any way to make a bidirectional relationship?
The text was updated successfully, but these errors were encountered: