/**
* if value if key exists.
*
* @param $array
* @param $key
*
* @return bool
*/
function lamitak_get_bidirectional_array_value($array, $key)
{
if (array_key_exists($key, $array)) {
return $array[$key];
} else {
return false;
}
}
/**
* Get value if key exist, unless get value if exist.
*
* @param $source_key
*
* @return bool
*/
function lamitak_get_bidirectional_field_name($source_key)
{
$keyMap = [
'field_laminate_theme_concepts' => 'field_laminate_concept_theme',
];
if ($dest_key = lamitak_get_bidirectional_array_value($keyMap, $source_key)) {
return $dest_key;
} else {
$keyMap = array_flip($keyMap);
if ($dest_key = lamitak_get_bidirectional_array_value($keyMap, $source_key)) {
return $dest_key;
}
}
return $source_key;
}
/**
* Update sync field of all post in relationship when any post in the relationship update
*
* @param $value
* @param $post_id
* @param $field
*
* @return mixed
*/
function lamitak_bidirectional_acf_update_value($value, $post_id, $field)
{
// vars
$field_name = $field['key'];
$source_field_name = lamitak_get_bidirectional_field_name($field['key']);
$global_name = 'is_updating_'.$field_name;
$global_source_name = 'is_updating_'.$source_field_name;
$field2Object = get_field_object($source_field_name);
// bail early if this filter was triggered from the update_field() function called within the loop below
// - this prevents an inifinte loop
if (!empty($GLOBALS[ $global_name ])) {
return $value;
}
if (!empty($GLOBALS[ $global_source_name ])) {
return $value;
}
// set global variable to avoid inifite loop
// - could also remove_filter() then add_filter() again, but this is simpler
$GLOBALS[ $global_name ] = 1;
$GLOBALS[ $global_source_name ] = 1;
//Duplicate this value, to avoid address reference, $value will be use to save after this hook finish.
$valueArray = $value;
// loop over selected posts and add this $post_id
if (!is_array($valueArray)) {
$valueArray = [$value]; //Don't use cast operator, because $value may be object
}
foreach ($valueArray as $post_id2) {
// load existing related posts
$value2 = get_field($source_field_name, $post_id2, false);
// allow for selected posts to not contain a value
if (empty($value2) && $field2Object['multiple']) {
$value2 = array();
}
// bail early if the current $post_id is already found in selected post's $value2
if (in_array($post_id, $value2)) {
continue;
}
if ($field2Object['multiple']) {
// append the current $post_id to the selected post's 'related_posts' value
$value2[] = $post_id;
} else {
$value2 = $post_id;
}
// update the selected post's value
update_field($source_field_name, $value2, $post_id2);
}
// find posts which have been removed
$old_value = get_field($field_name, $post_id, false);
if (!is_array($old_value)) {
$old_value = [$old_value]; //Dont worry about var reference, because $old_value will not be used again
}
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 related posts
$value2 = get_field($source_field_name, $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 ($field2Object['multiple']) {
// remove
unset($value2[ $pos]);
// update the un-selected post's value
update_field($source_field_name, $value2, $post_id2);
} else {
delete_field($source_field_name, $post_id2);
}
}
// reset global varibale to allow this filter to function as per normal
$GLOBALS[ $global_name ] = 0;
$GLOBALS[ $global_source_name ] = 0;
// return
return $value;
}
add_filter('acf/update_value/key=field_laminate_concept_theme', 'lamitak_bidirectional_acf_update_value', 10, 3);
add_filter('acf/update_value/key=field_laminate_theme_concepts', 'lamitak_bidirectional_acf_update_value', 10, 3);