Skip to content

Instantly share code, notes, and snippets.

@solepixel
Created December 30, 2015 10:20
Show Gist options
  • Save solepixel/13c34d208ce46011be01 to your computer and use it in GitHub Desktop.
Save solepixel/13c34d208ce46011be01 to your computer and use it in GitHub Desktop.
Sync 2 relationship CPT fields in ACF that are connected. Example: Actors (Relationship Field) in a Movie (CPT), and Movies (Relationship field) an Actor (CPT) has been in.
<?php
function acf_sync_field( $sync_field, $value, $post_id, $field ){
// vars
$source_field = $field['name'];
$source_global_name = 'is_updating_' . $source_field;
$sync_global_name = 'is_updating_' . $sync_field;
// get this value early before anything is updated
$old_value = get_field( $source_field, $post_id, false );
// bail early if this filter was triggered from the update_field() function called within the loop below
// - this prevents an inifinte loop
if( isset( $GLOBALS[ $source_global_name ] ) && ! empty( $GLOBALS[ $source_global_name ] ) )
return $value;
if( isset( $GLOBALS[ $sync_global_name ] ) && ! empty( $GLOBALS[ $sync_global_name ] ) )
return $value;
// set global variable to avoid inifite loop
// - could also remove_filter() then add_filter() again, but this is simpler
$GLOBALS[ $source_global_name ] = 1;
$GLOBALS[ $sync_global_name ] = 1;
// loop over selected posts and add this $post_id
if( is_array( $value ) ) {
foreach( $value as $post_id2 ) {
// load existing sync data
$value2 = get_field( $sync_field, $post_id2, false );
// allow for selected posts to not contain a value
if( empty( $value2 ) ) {
$value2 = array();
}
// bail early if the current $post_id is already found in selected post's $value2
if( in_array( $post_id, $value2 ) )
continue;
// append the current $post_id to the selected post's 'related_posts' value
$value2[] = $post_id;
// update the selected post's value
update_field( $sync_field, $value2, $post_id2 );
}
}
// find posts which have been removed
if( is_array( $old_value ) ) {
foreach( $old_value as $post_id2 ) {
// bail early if this value has not been removed
if( is_array( $value ) && in_array( $post_id2, $value ) )
continue;
// load existing sync data
$value2 = get_field( $sync_field, $post_id2, false );
// bail early if no value
if( empty( $value2 ) )
continue;
// find the position of $post_id within $value2 so we can remove it
$pos = array_search( $post_id, $value2 );
if( $pos === false )
continue;
// remove
unset( $value2[ $pos ] );
// update the un-selected post's value
update_field( $sync_field, $value2, $post_id2 );
}
}
// reset global varibale to allow this filter to function as per normal
$GLOBALS[ $source_global_name ] = 0;
unset( $GLOBALS[ $source_global_name ] );
$GLOBALS[ $sync_global_name ] = 0;
unset( $GLOBALS[ $sync_global_name ] );
return $value;
}
<?php
/* Example Usage */
add_filter( 'acf/update_value/name=relationship-field', 'bidirectional_sync_relationship_field', 10, 3 );
function bidirectional_sync_relationship_field( $value, $post_id, $field ) {
return acf_sync_field( 'relationship-field', $value, $post_id, $field );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment