nguyenvanduocit
6/10/2016 - 8:56 AM

lamitak_bidirectional_acf_update_value


/**
 * 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);