wp_set_object_terms

The timeline below displays how wordpress function wp_set_object_terms has changed across different WordPress versions. If a version is not listed, refer to the next available version below.

WordPress Version: 6.3

/**
 * Creates term and taxonomy relationships.
 *
 * Relates an object (post, link, etc.) to a term and taxonomy type. Creates the
 * term and taxonomy relationship if it doesn't already exist. Creates a term if
 * it doesn't exist (using the slug).
 *
 * A relationship means that the term is grouped in or belongs to the taxonomy.
 * A term has no meaning until it is given context by defining which taxonomy it
 * exists under.
 *
 * @since 2.3.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int              $object_id The object to relate to.
 * @param string|int|array $terms     A single term slug, single term ID, or array of either term slugs or IDs.
 *                                    Will replace all existing related terms in this taxonomy. Passing an
 *                                    empty array will remove all related terms.
 * @param string           $taxonomy  The context in which to relate the term to the object.
 * @param bool             $append    Optional. If false will delete difference of terms. Default false.
 * @return array|WP_Error Term taxonomy IDs of the affected terms or WP_Error on failure.
 */
function wp_set_object_terms($object_id, $terms, $taxonomy, $append = false)
{
    global $wpdb;
    $object_id = (int) $object_id;
    if (!taxonomy_exists($taxonomy)) {
        return new WP_Error('invalid_taxonomy', __('Invalid taxonomy.'));
    }
    if (empty($terms)) {
        $terms = array();
    } elseif (!is_array($terms)) {
        $terms = array($terms);
    }
    if (!$append) {
        $old_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'orderby' => 'none', 'update_term_meta_cache' => false));
    } else {
        $old_tt_ids = array();
    }
    $tt_ids = array();
    $term_ids = array();
    $new_tt_ids = array();
    foreach ((array) $terms as $term) {
        if ('' === trim($term)) {
            continue;
        }
        $term_info = term_exists($term, $taxonomy);
        if (!$term_info) {
            // Skip if a non-existent term ID is passed.
            if (is_int($term)) {
                continue;
            }
            $term_info = wp_insert_term($term, $taxonomy);
        }
        if (is_wp_error($term_info)) {
            return $term_info;
        }
        $term_ids[] = $term_info['term_id'];
        $tt_id = $term_info['term_taxonomy_id'];
        $tt_ids[] = $tt_id;
        if ($wpdb->get_var($wpdb->prepare("SELECT term_taxonomy_id FROM {$wpdb->term_relationships} WHERE object_id = %d AND term_taxonomy_id = %d", $object_id, $tt_id))) {
            continue;
        }
        /**
         * Fires immediately before an object-term relationship is added.
         *
         * @since 2.9.0
         * @since 4.7.0 Added the `$taxonomy` parameter.
         *
         * @param int    $object_id Object ID.
         * @param int    $tt_id     Term taxonomy ID.
         * @param string $taxonomy  Taxonomy slug.
         */
        do_action('add_term_relationship', $object_id, $tt_id, $taxonomy);
        $wpdb->insert($wpdb->term_relationships, array('object_id' => $object_id, 'term_taxonomy_id' => $tt_id));
        /**
         * Fires immediately after an object-term relationship is added.
         *
         * @since 2.9.0
         * @since 4.7.0 Added the `$taxonomy` parameter.
         *
         * @param int    $object_id Object ID.
         * @param int    $tt_id     Term taxonomy ID.
         * @param string $taxonomy  Taxonomy slug.
         */
        do_action('added_term_relationship', $object_id, $tt_id, $taxonomy);
        $new_tt_ids[] = $tt_id;
    }
    if ($new_tt_ids) {
        wp_update_term_count($new_tt_ids, $taxonomy);
    }
    if (!$append) {
        $delete_tt_ids = array_diff($old_tt_ids, $tt_ids);
        if ($delete_tt_ids) {
            $in_delete_tt_ids = "'" . implode("', '", $delete_tt_ids) . "'";
            $delete_term_ids = $wpdb->get_col($wpdb->prepare("SELECT tt.term_id FROM {$wpdb->term_taxonomy} AS tt WHERE tt.taxonomy = %s AND tt.term_taxonomy_id IN ({$in_delete_tt_ids})", $taxonomy));
            $delete_term_ids = array_map('intval', $delete_term_ids);
            $remove = wp_remove_object_terms($object_id, $delete_term_ids, $taxonomy);
            if (is_wp_error($remove)) {
                return $remove;
            }
        }
    }
    $t = get_taxonomy($taxonomy);
    if (!$append && isset($t->sort) && $t->sort) {
        $values = array();
        $term_order = 0;
        $final_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'update_term_meta_cache' => false));
        foreach ($tt_ids as $tt_id) {
            if (in_array((int) $tt_id, $final_tt_ids, true)) {
                $values[] = $wpdb->prepare('(%d, %d, %d)', $object_id, $tt_id, ++$term_order);
            }
        }
        if ($values) {
            if (false === $wpdb->query("INSERT INTO {$wpdb->term_relationships} (object_id, term_taxonomy_id, term_order) VALUES " . implode(',', $values) . ' ON DUPLICATE KEY UPDATE term_order = VALUES(term_order)')) {
                return new WP_Error('db_insert_error', __('Could not insert term relationship into the database.'), $wpdb->last_error);
            }
        }
    }
    wp_cache_delete($object_id, $taxonomy . '_relationships');
    wp_cache_set_terms_last_changed();
    /**
     * Fires after an object's terms have been set.
     *
     * @since 2.8.0
     *
     * @param int    $object_id  Object ID.
     * @param array  $terms      An array of object term IDs or slugs.
     * @param array  $tt_ids     An array of term taxonomy IDs.
     * @param string $taxonomy   Taxonomy slug.
     * @param bool   $append     Whether to append new terms to the old terms.
     * @param array  $old_tt_ids Old array of term taxonomy IDs.
     */
    do_action('set_object_terms', $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids);
    return $tt_ids;
}

WordPress Version: 6.1

/**
 * Creates term and taxonomy relationships.
 *
 * Relates an object (post, link, etc.) to a term and taxonomy type. Creates the
 * term and taxonomy relationship if it doesn't already exist. Creates a term if
 * it doesn't exist (using the slug).
 *
 * A relationship means that the term is grouped in or belongs to the taxonomy.
 * A term has no meaning until it is given context by defining which taxonomy it
 * exists under.
 *
 * @since 2.3.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int              $object_id The object to relate to.
 * @param string|int|array $terms     A single term slug, single term ID, or array of either term slugs or IDs.
 *                                    Will replace all existing related terms in this taxonomy. Passing an
 *                                    empty value will remove all related terms.
 * @param string           $taxonomy  The context in which to relate the term to the object.
 * @param bool             $append    Optional. If false will delete difference of terms. Default false.
 * @return array|WP_Error Term taxonomy IDs of the affected terms or WP_Error on failure.
 */
function wp_set_object_terms($object_id, $terms, $taxonomy, $append = false)
{
    global $wpdb;
    $object_id = (int) $object_id;
    if (!taxonomy_exists($taxonomy)) {
        return new WP_Error('invalid_taxonomy', __('Invalid taxonomy.'));
    }
    if (!is_array($terms)) {
        $terms = array($terms);
    }
    if (!$append) {
        $old_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'orderby' => 'none', 'update_term_meta_cache' => false));
    } else {
        $old_tt_ids = array();
    }
    $tt_ids = array();
    $term_ids = array();
    $new_tt_ids = array();
    foreach ((array) $terms as $term) {
        if ('' === trim($term)) {
            continue;
        }
        $term_info = term_exists($term, $taxonomy);
        if (!$term_info) {
            // Skip if a non-existent term ID is passed.
            if (is_int($term)) {
                continue;
            }
            $term_info = wp_insert_term($term, $taxonomy);
        }
        if (is_wp_error($term_info)) {
            return $term_info;
        }
        $term_ids[] = $term_info['term_id'];
        $tt_id = $term_info['term_taxonomy_id'];
        $tt_ids[] = $tt_id;
        if ($wpdb->get_var($wpdb->prepare("SELECT term_taxonomy_id FROM {$wpdb->term_relationships} WHERE object_id = %d AND term_taxonomy_id = %d", $object_id, $tt_id))) {
            continue;
        }
        /**
         * Fires immediately before an object-term relationship is added.
         *
         * @since 2.9.0
         * @since 4.7.0 Added the `$taxonomy` parameter.
         *
         * @param int    $object_id Object ID.
         * @param int    $tt_id     Term taxonomy ID.
         * @param string $taxonomy  Taxonomy slug.
         */
        do_action('add_term_relationship', $object_id, $tt_id, $taxonomy);
        $wpdb->insert($wpdb->term_relationships, array('object_id' => $object_id, 'term_taxonomy_id' => $tt_id));
        /**
         * Fires immediately after an object-term relationship is added.
         *
         * @since 2.9.0
         * @since 4.7.0 Added the `$taxonomy` parameter.
         *
         * @param int    $object_id Object ID.
         * @param int    $tt_id     Term taxonomy ID.
         * @param string $taxonomy  Taxonomy slug.
         */
        do_action('added_term_relationship', $object_id, $tt_id, $taxonomy);
        $new_tt_ids[] = $tt_id;
    }
    if ($new_tt_ids) {
        wp_update_term_count($new_tt_ids, $taxonomy);
    }
    if (!$append) {
        $delete_tt_ids = array_diff($old_tt_ids, $tt_ids);
        if ($delete_tt_ids) {
            $in_delete_tt_ids = "'" . implode("', '", $delete_tt_ids) . "'";
            $delete_term_ids = $wpdb->get_col($wpdb->prepare("SELECT tt.term_id FROM {$wpdb->term_taxonomy} AS tt WHERE tt.taxonomy = %s AND tt.term_taxonomy_id IN ({$in_delete_tt_ids})", $taxonomy));
            $delete_term_ids = array_map('intval', $delete_term_ids);
            $remove = wp_remove_object_terms($object_id, $delete_term_ids, $taxonomy);
            if (is_wp_error($remove)) {
                return $remove;
            }
        }
    }
    $t = get_taxonomy($taxonomy);
    if (!$append && isset($t->sort) && $t->sort) {
        $values = array();
        $term_order = 0;
        $final_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'update_term_meta_cache' => false));
        foreach ($tt_ids as $tt_id) {
            if (in_array((int) $tt_id, $final_tt_ids, true)) {
                $values[] = $wpdb->prepare('(%d, %d, %d)', $object_id, $tt_id, ++$term_order);
            }
        }
        if ($values) {
            if (false === $wpdb->query("INSERT INTO {$wpdb->term_relationships} (object_id, term_taxonomy_id, term_order) VALUES " . implode(',', $values) . ' ON DUPLICATE KEY UPDATE term_order = VALUES(term_order)')) {
                return new WP_Error('db_insert_error', __('Could not insert term relationship into the database.'), $wpdb->last_error);
            }
        }
    }
    wp_cache_delete($object_id, $taxonomy . '_relationships');
    wp_cache_delete('last_changed', 'terms');
    /**
     * Fires after an object's terms have been set.
     *
     * @since 2.8.0
     *
     * @param int    $object_id  Object ID.
     * @param array  $terms      An array of object term IDs or slugs.
     * @param array  $tt_ids     An array of term taxonomy IDs.
     * @param string $taxonomy   Taxonomy slug.
     * @param bool   $append     Whether to append new terms to the old terms.
     * @param array  $old_tt_ids Old array of term taxonomy IDs.
     */
    do_action('set_object_terms', $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids);
    return $tt_ids;
}

WordPress Version: 5.8

/**
 * Create Term and Taxonomy Relationships.
 *
 * Relates an object (post, link etc) to a term and taxonomy type. Creates the
 * term and taxonomy relationship if it doesn't already exist. Creates a term if
 * it doesn't exist (using the slug).
 *
 * A relationship means that the term is grouped in or belongs to the taxonomy.
 * A term has no meaning until it is given context by defining which taxonomy it
 * exists under.
 *
 * @since 2.3.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int              $object_id The object to relate to.
 * @param string|int|array $terms     A single term slug, single term ID, or array of either term slugs or IDs.
 *                                    Will replace all existing related terms in this taxonomy. Passing an
 *                                    empty value will remove all related terms.
 * @param string           $taxonomy  The context in which to relate the term to the object.
 * @param bool             $append    Optional. If false will delete difference of terms. Default false.
 * @return array|WP_Error Term taxonomy IDs of the affected terms or WP_Error on failure.
 */
function wp_set_object_terms($object_id, $terms, $taxonomy, $append = false)
{
    global $wpdb;
    $object_id = (int) $object_id;
    if (!taxonomy_exists($taxonomy)) {
        return new WP_Error('invalid_taxonomy', __('Invalid taxonomy.'));
    }
    if (!is_array($terms)) {
        $terms = array($terms);
    }
    if (!$append) {
        $old_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'orderby' => 'none', 'update_term_meta_cache' => false));
    } else {
        $old_tt_ids = array();
    }
    $tt_ids = array();
    $term_ids = array();
    $new_tt_ids = array();
    foreach ((array) $terms as $term) {
        if ('' === trim($term)) {
            continue;
        }
        $term_info = term_exists($term, $taxonomy);
        if (!$term_info) {
            // Skip if a non-existent term ID is passed.
            if (is_int($term)) {
                continue;
            }
            $term_info = wp_insert_term($term, $taxonomy);
        }
        if (is_wp_error($term_info)) {
            return $term_info;
        }
        $term_ids[] = $term_info['term_id'];
        $tt_id = $term_info['term_taxonomy_id'];
        $tt_ids[] = $tt_id;
        if ($wpdb->get_var($wpdb->prepare("SELECT term_taxonomy_id FROM {$wpdb->term_relationships} WHERE object_id = %d AND term_taxonomy_id = %d", $object_id, $tt_id))) {
            continue;
        }
        /**
         * Fires immediately before an object-term relationship is added.
         *
         * @since 2.9.0
         * @since 4.7.0 Added the `$taxonomy` parameter.
         *
         * @param int    $object_id Object ID.
         * @param int    $tt_id     Term taxonomy ID.
         * @param string $taxonomy  Taxonomy slug.
         */
        do_action('add_term_relationship', $object_id, $tt_id, $taxonomy);
        $wpdb->insert($wpdb->term_relationships, array('object_id' => $object_id, 'term_taxonomy_id' => $tt_id));
        /**
         * Fires immediately after an object-term relationship is added.
         *
         * @since 2.9.0
         * @since 4.7.0 Added the `$taxonomy` parameter.
         *
         * @param int    $object_id Object ID.
         * @param int    $tt_id     Term taxonomy ID.
         * @param string $taxonomy  Taxonomy slug.
         */
        do_action('added_term_relationship', $object_id, $tt_id, $taxonomy);
        $new_tt_ids[] = $tt_id;
    }
    if ($new_tt_ids) {
        wp_update_term_count($new_tt_ids, $taxonomy);
    }
    if (!$append) {
        $delete_tt_ids = array_diff($old_tt_ids, $tt_ids);
        if ($delete_tt_ids) {
            $in_delete_tt_ids = "'" . implode("', '", $delete_tt_ids) . "'";
            $delete_term_ids = $wpdb->get_col($wpdb->prepare("SELECT tt.term_id FROM {$wpdb->term_taxonomy} AS tt WHERE tt.taxonomy = %s AND tt.term_taxonomy_id IN ({$in_delete_tt_ids})", $taxonomy));
            $delete_term_ids = array_map('intval', $delete_term_ids);
            $remove = wp_remove_object_terms($object_id, $delete_term_ids, $taxonomy);
            if (is_wp_error($remove)) {
                return $remove;
            }
        }
    }
    $t = get_taxonomy($taxonomy);
    if (!$append && isset($t->sort) && $t->sort) {
        $values = array();
        $term_order = 0;
        $final_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'update_term_meta_cache' => false));
        foreach ($tt_ids as $tt_id) {
            if (in_array((int) $tt_id, $final_tt_ids, true)) {
                $values[] = $wpdb->prepare('(%d, %d, %d)', $object_id, $tt_id, ++$term_order);
            }
        }
        if ($values) {
            if (false === $wpdb->query("INSERT INTO {$wpdb->term_relationships} (object_id, term_taxonomy_id, term_order) VALUES " . implode(',', $values) . ' ON DUPLICATE KEY UPDATE term_order = VALUES(term_order)')) {
                return new WP_Error('db_insert_error', __('Could not insert term relationship into the database.'), $wpdb->last_error);
            }
        }
    }
    wp_cache_delete($object_id, $taxonomy . '_relationships');
    wp_cache_delete('last_changed', 'terms');
    /**
     * Fires after an object's terms have been set.
     *
     * @since 2.8.0
     *
     * @param int    $object_id  Object ID.
     * @param array  $terms      An array of object term IDs or slugs.
     * @param array  $tt_ids     An array of term taxonomy IDs.
     * @param string $taxonomy   Taxonomy slug.
     * @param bool   $append     Whether to append new terms to the old terms.
     * @param array  $old_tt_ids Old array of term taxonomy IDs.
     */
    do_action('set_object_terms', $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids);
    return $tt_ids;
}

WordPress Version: 5.6

/**
 * Create Term and Taxonomy Relationships.
 *
 * Relates an object (post, link etc) to a term and taxonomy type. Creates the
 * term and taxonomy relationship if it doesn't already exist. Creates a term if
 * it doesn't exist (using the slug).
 *
 * A relationship means that the term is grouped in or belongs to the taxonomy.
 * A term has no meaning until it is given context by defining which taxonomy it
 * exists under.
 *
 * @since 2.3.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int              $object_id The object to relate to.
 * @param string|int|array $terms     A single term slug, single term ID, or array of either term slugs or IDs.
 *                                    Will replace all existing related terms in this taxonomy. Passing an
 *                                    empty value will remove all related terms.
 * @param string           $taxonomy  The context in which to relate the term to the object.
 * @param bool             $append    Optional. If false will delete difference of terms. Default false.
 * @return array|WP_Error Term taxonomy IDs of the affected terms or WP_Error on failure.
 */
function wp_set_object_terms($object_id, $terms, $taxonomy, $append = false)
{
    global $wpdb;
    $object_id = (int) $object_id;
    if (!taxonomy_exists($taxonomy)) {
        return new WP_Error('invalid_taxonomy', __('Invalid taxonomy.'));
    }
    if (!is_array($terms)) {
        $terms = array($terms);
    }
    if (!$append) {
        $old_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'orderby' => 'none', 'update_term_meta_cache' => false));
    } else {
        $old_tt_ids = array();
    }
    $tt_ids = array();
    $term_ids = array();
    $new_tt_ids = array();
    foreach ((array) $terms as $term) {
        if ('' === trim($term)) {
            continue;
        }
        $term_info = term_exists($term, $taxonomy);
        if (!$term_info) {
            // Skip if a non-existent term ID is passed.
            if (is_int($term)) {
                continue;
            }
            $term_info = wp_insert_term($term, $taxonomy);
        }
        if (is_wp_error($term_info)) {
            return $term_info;
        }
        $term_ids[] = $term_info['term_id'];
        $tt_id = $term_info['term_taxonomy_id'];
        $tt_ids[] = $tt_id;
        if ($wpdb->get_var($wpdb->prepare("SELECT term_taxonomy_id FROM {$wpdb->term_relationships} WHERE object_id = %d AND term_taxonomy_id = %d", $object_id, $tt_id))) {
            continue;
        }
        /**
         * Fires immediately before an object-term relationship is added.
         *
         * @since 2.9.0
         * @since 4.7.0 Added the `$taxonomy` parameter.
         *
         * @param int    $object_id Object ID.
         * @param int    $tt_id     Term taxonomy ID.
         * @param string $taxonomy  Taxonomy slug.
         */
        do_action('add_term_relationship', $object_id, $tt_id, $taxonomy);
        $wpdb->insert($wpdb->term_relationships, array('object_id' => $object_id, 'term_taxonomy_id' => $tt_id));
        /**
         * Fires immediately after an object-term relationship is added.
         *
         * @since 2.9.0
         * @since 4.7.0 Added the `$taxonomy` parameter.
         *
         * @param int    $object_id Object ID.
         * @param int    $tt_id     Term taxonomy ID.
         * @param string $taxonomy  Taxonomy slug.
         */
        do_action('added_term_relationship', $object_id, $tt_id, $taxonomy);
        $new_tt_ids[] = $tt_id;
    }
    if ($new_tt_ids) {
        wp_update_term_count($new_tt_ids, $taxonomy);
    }
    if (!$append) {
        $delete_tt_ids = array_diff($old_tt_ids, $tt_ids);
        if ($delete_tt_ids) {
            $in_delete_tt_ids = "'" . implode("', '", $delete_tt_ids) . "'";
            $delete_term_ids = $wpdb->get_col($wpdb->prepare("SELECT tt.term_id FROM {$wpdb->term_taxonomy} AS tt WHERE tt.taxonomy = %s AND tt.term_taxonomy_id IN ({$in_delete_tt_ids})", $taxonomy));
            $delete_term_ids = array_map('intval', $delete_term_ids);
            $remove = wp_remove_object_terms($object_id, $delete_term_ids, $taxonomy);
            if (is_wp_error($remove)) {
                return $remove;
            }
        }
    }
    $t = get_taxonomy($taxonomy);
    if (!$append && isset($t->sort) && $t->sort) {
        $values = array();
        $term_order = 0;
        $final_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'update_term_meta_cache' => false));
        foreach ($tt_ids as $tt_id) {
            if (in_array((int) $tt_id, $final_tt_ids, true)) {
                $values[] = $wpdb->prepare('(%d, %d, %d)', $object_id, $tt_id, ++$term_order);
            }
        }
        if ($values) {
            if (false === $wpdb->query("INSERT INTO {$wpdb->term_relationships} (object_id, term_taxonomy_id, term_order) VALUES " . implode(',', $values) . ' ON DUPLICATE KEY UPDATE term_order = VALUES(term_order)')) {
                return new WP_Error('db_insert_error', __('Could not insert term relationship into the database.'), $wpdb->last_error);
            }
        }
    }
    wp_cache_delete($object_id, $taxonomy . '_relationships');
    wp_cache_delete('last_changed', 'terms');
    /**
     * Fires after an object's terms have been set.
     *
     * @since 2.8.0
     *
     * @param int    $object_id  Object ID.
     * @param array  $terms      An array of object terms.
     * @param array  $tt_ids     An array of term taxonomy IDs.
     * @param string $taxonomy   Taxonomy slug.
     * @param bool   $append     Whether to append new terms to the old terms.
     * @param array  $old_tt_ids Old array of term taxonomy IDs.
     */
    do_action('set_object_terms', $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids);
    return $tt_ids;
}

WordPress Version: 5.5

/**
 * Create Term and Taxonomy Relationships.
 *
 * Relates an object (post, link etc) to a term and taxonomy type. Creates the
 * term and taxonomy relationship if it doesn't already exist. Creates a term if
 * it doesn't exist (using the slug).
 *
 * A relationship means that the term is grouped in or belongs to the taxonomy.
 * A term has no meaning until it is given context by defining which taxonomy it
 * exists under.
 *
 * @since 2.3.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int              $object_id The object to relate to.
 * @param string|int|array $terms     A single term slug, single term ID, or array of either term slugs or IDs.
 *                                    Will replace all existing related terms in this taxonomy. Passing an
 *                                    empty value will remove all related terms.
 * @param string           $taxonomy  The context in which to relate the term to the object.
 * @param bool             $append    Optional. If false will delete difference of terms. Default false.
 * @return array|WP_Error Term taxonomy IDs of the affected terms or WP_Error on failure.
 */
function wp_set_object_terms($object_id, $terms, $taxonomy, $append = false)
{
    global $wpdb;
    $object_id = (int) $object_id;
    if (!taxonomy_exists($taxonomy)) {
        return new WP_Error('invalid_taxonomy', __('Invalid taxonomy.'));
    }
    if (!is_array($terms)) {
        $terms = array($terms);
    }
    if (!$append) {
        $old_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'orderby' => 'none', 'update_term_meta_cache' => false));
    } else {
        $old_tt_ids = array();
    }
    $tt_ids = array();
    $term_ids = array();
    $new_tt_ids = array();
    foreach ((array) $terms as $term) {
        if ('' === trim($term)) {
            continue;
        }
        $term_info = term_exists($term, $taxonomy);
        if (!$term_info) {
            // Skip if a non-existent term ID is passed.
            if (is_int($term)) {
                continue;
            }
            $term_info = wp_insert_term($term, $taxonomy);
        }
        if (is_wp_error($term_info)) {
            return $term_info;
        }
        $term_ids[] = $term_info['term_id'];
        $tt_id = $term_info['term_taxonomy_id'];
        $tt_ids[] = $tt_id;
        if ($wpdb->get_var($wpdb->prepare("SELECT term_taxonomy_id FROM {$wpdb->term_relationships} WHERE object_id = %d AND term_taxonomy_id = %d", $object_id, $tt_id))) {
            continue;
        }
        /**
         * Fires immediately before an object-term relationship is added.
         *
         * @since 2.9.0
         * @since 4.7.0 Added the `$taxonomy` parameter.
         *
         * @param int    $object_id Object ID.
         * @param int    $tt_id     Term taxonomy ID.
         * @param string $taxonomy  Taxonomy slug.
         */
        do_action('add_term_relationship', $object_id, $tt_id, $taxonomy);
        $wpdb->insert($wpdb->term_relationships, array('object_id' => $object_id, 'term_taxonomy_id' => $tt_id));
        /**
         * Fires immediately after an object-term relationship is added.
         *
         * @since 2.9.0
         * @since 4.7.0 Added the `$taxonomy` parameter.
         *
         * @param int    $object_id Object ID.
         * @param int    $tt_id     Term taxonomy ID.
         * @param string $taxonomy  Taxonomy slug.
         */
        do_action('added_term_relationship', $object_id, $tt_id, $taxonomy);
        $new_tt_ids[] = $tt_id;
    }
    if ($new_tt_ids) {
        wp_update_term_count($new_tt_ids, $taxonomy);
    }
    if (!$append) {
        $delete_tt_ids = array_diff($old_tt_ids, $tt_ids);
        if ($delete_tt_ids) {
            $in_delete_tt_ids = "'" . implode("', '", $delete_tt_ids) . "'";
            $delete_term_ids = $wpdb->get_col($wpdb->prepare("SELECT tt.term_id FROM {$wpdb->term_taxonomy} AS tt WHERE tt.taxonomy = %s AND tt.term_taxonomy_id IN ({$in_delete_tt_ids})", $taxonomy));
            $delete_term_ids = array_map('intval', $delete_term_ids);
            $remove = wp_remove_object_terms($object_id, $delete_term_ids, $taxonomy);
            if (is_wp_error($remove)) {
                return $remove;
            }
        }
    }
    $t = get_taxonomy($taxonomy);
    if (!$append && isset($t->sort) && $t->sort) {
        $values = array();
        $term_order = 0;
        $final_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'update_term_meta_cache' => false));
        foreach ($tt_ids as $tt_id) {
            if (in_array((int) $tt_id, $final_tt_ids, true)) {
                $values[] = $wpdb->prepare('(%d, %d, %d)', $object_id, $tt_id, ++$term_order);
            }
        }
        if ($values) {
            if (false === $wpdb->query("INSERT INTO {$wpdb->term_relationships} (object_id, term_taxonomy_id, term_order) VALUES " . join(',', $values) . ' ON DUPLICATE KEY UPDATE term_order = VALUES(term_order)')) {
                return new WP_Error('db_insert_error', __('Could not insert term relationship into the database.'), $wpdb->last_error);
            }
        }
    }
    wp_cache_delete($object_id, $taxonomy . '_relationships');
    wp_cache_delete('last_changed', 'terms');
    /**
     * Fires after an object's terms have been set.
     *
     * @since 2.8.0
     *
     * @param int    $object_id  Object ID.
     * @param array  $terms      An array of object terms.
     * @param array  $tt_ids     An array of term taxonomy IDs.
     * @param string $taxonomy   Taxonomy slug.
     * @param bool   $append     Whether to append new terms to the old terms.
     * @param array  $old_tt_ids Old array of term taxonomy IDs.
     */
    do_action('set_object_terms', $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids);
    return $tt_ids;
}

WordPress Version: 5.3

/**
 * Create Term and Taxonomy Relationships.
 *
 * Relates an object (post, link etc) to a term and taxonomy type. Creates the
 * term and taxonomy relationship if it doesn't already exist. Creates a term if
 * it doesn't exist (using the slug).
 *
 * A relationship means that the term is grouped in or belongs to the taxonomy.
 * A term has no meaning until it is given context by defining which taxonomy it
 * exists under.
 *
 * @since 2.3.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int              $object_id The object to relate to.
 * @param string|int|array $terms     A single term slug, single term id, or array of either term slugs or ids.
 *                                    Will replace all existing related terms in this taxonomy. Passing an
 *                                    empty value will remove all related terms.
 * @param string           $taxonomy  The context in which to relate the term to the object.
 * @param bool             $append    Optional. If false will delete difference of terms. Default false.
 * @return array|WP_Error Term taxonomy IDs of the affected terms or WP_Error on failure.
 */
function wp_set_object_terms($object_id, $terms, $taxonomy, $append = false)
{
    global $wpdb;
    $object_id = (int) $object_id;
    if (!taxonomy_exists($taxonomy)) {
        return new WP_Error('invalid_taxonomy', __('Invalid taxonomy.'));
    }
    if (!is_array($terms)) {
        $terms = array($terms);
    }
    if (!$append) {
        $old_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'orderby' => 'none', 'update_term_meta_cache' => false));
    } else {
        $old_tt_ids = array();
    }
    $tt_ids = array();
    $term_ids = array();
    $new_tt_ids = array();
    foreach ((array) $terms as $term) {
        if ('' === trim($term)) {
            continue;
        }
        $term_info = term_exists($term, $taxonomy);
        if (!$term_info) {
            // Skip if a non-existent term ID is passed.
            if (is_int($term)) {
                continue;
            }
            $term_info = wp_insert_term($term, $taxonomy);
        }
        if (is_wp_error($term_info)) {
            return $term_info;
        }
        $term_ids[] = $term_info['term_id'];
        $tt_id = $term_info['term_taxonomy_id'];
        $tt_ids[] = $tt_id;
        if ($wpdb->get_var($wpdb->prepare("SELECT term_taxonomy_id FROM {$wpdb->term_relationships} WHERE object_id = %d AND term_taxonomy_id = %d", $object_id, $tt_id))) {
            continue;
        }
        /**
         * Fires immediately before an object-term relationship is added.
         *
         * @since 2.9.0
         * @since 4.7.0 Added the `$taxonomy` parameter.
         *
         * @param int    $object_id Object ID.
         * @param int    $tt_id     Term taxonomy ID.
         * @param string $taxonomy  Taxonomy slug.
         */
        do_action('add_term_relationship', $object_id, $tt_id, $taxonomy);
        $wpdb->insert($wpdb->term_relationships, array('object_id' => $object_id, 'term_taxonomy_id' => $tt_id));
        /**
         * Fires immediately after an object-term relationship is added.
         *
         * @since 2.9.0
         * @since 4.7.0 Added the `$taxonomy` parameter.
         *
         * @param int    $object_id Object ID.
         * @param int    $tt_id     Term taxonomy ID.
         * @param string $taxonomy  Taxonomy slug.
         */
        do_action('added_term_relationship', $object_id, $tt_id, $taxonomy);
        $new_tt_ids[] = $tt_id;
    }
    if ($new_tt_ids) {
        wp_update_term_count($new_tt_ids, $taxonomy);
    }
    if (!$append) {
        $delete_tt_ids = array_diff($old_tt_ids, $tt_ids);
        if ($delete_tt_ids) {
            $in_delete_tt_ids = "'" . implode("', '", $delete_tt_ids) . "'";
            $delete_term_ids = $wpdb->get_col($wpdb->prepare("SELECT tt.term_id FROM {$wpdb->term_taxonomy} AS tt WHERE tt.taxonomy = %s AND tt.term_taxonomy_id IN ({$in_delete_tt_ids})", $taxonomy));
            $delete_term_ids = array_map('intval', $delete_term_ids);
            $remove = wp_remove_object_terms($object_id, $delete_term_ids, $taxonomy);
            if (is_wp_error($remove)) {
                return $remove;
            }
        }
    }
    $t = get_taxonomy($taxonomy);
    if (!$append && isset($t->sort) && $t->sort) {
        $values = array();
        $term_order = 0;
        $final_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'update_term_meta_cache' => false));
        foreach ($tt_ids as $tt_id) {
            if (in_array($tt_id, $final_tt_ids)) {
                $values[] = $wpdb->prepare('(%d, %d, %d)', $object_id, $tt_id, ++$term_order);
            }
        }
        if ($values) {
            if (false === $wpdb->query("INSERT INTO {$wpdb->term_relationships} (object_id, term_taxonomy_id, term_order) VALUES " . join(',', $values) . ' ON DUPLICATE KEY UPDATE term_order = VALUES(term_order)')) {
                return new WP_Error('db_insert_error', __('Could not insert term relationship into the database.'), $wpdb->last_error);
            }
        }
    }
    wp_cache_delete($object_id, $taxonomy . '_relationships');
    wp_cache_delete('last_changed', 'terms');
    /**
     * Fires after an object's terms have been set.
     *
     * @since 2.8.0
     *
     * @param int    $object_id  Object ID.
     * @param array  $terms      An array of object terms.
     * @param array  $tt_ids     An array of term taxonomy IDs.
     * @param string $taxonomy   Taxonomy slug.
     * @param bool   $append     Whether to append new terms to the old terms.
     * @param array  $old_tt_ids Old array of term taxonomy IDs.
     */
    do_action('set_object_terms', $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids);
    return $tt_ids;
}

WordPress Version: 5.1

/**
 * Create Term and Taxonomy Relationships.
 *
 * Relates an object (post, link etc) to a term and taxonomy type. Creates the
 * term and taxonomy relationship if it doesn't already exist. Creates a term if
 * it doesn't exist (using the slug).
 *
 * A relationship means that the term is grouped in or belongs to the taxonomy.
 * A term has no meaning until it is given context by defining which taxonomy it
 * exists under.
 *
 * @since 2.3.0
 *
 * @global wpdb $wpdb The WordPress database abstraction object.
 *
 * @param int              $object_id The object to relate to.
 * @param string|int|array $terms     A single term slug, single term id, or array of either term slugs or ids.
 *                                    Will replace all existing related terms in this taxonomy. Passing an
 *                                    empty value will remove all related terms.
 * @param string           $taxonomy  The context in which to relate the term to the object.
 * @param bool             $append    Optional. If false will delete difference of terms. Default false.
 * @return array|WP_Error Term taxonomy IDs of the affected terms.
 */
function wp_set_object_terms($object_id, $terms, $taxonomy, $append = false)
{
    global $wpdb;
    $object_id = (int) $object_id;
    if (!taxonomy_exists($taxonomy)) {
        return new WP_Error('invalid_taxonomy', __('Invalid taxonomy.'));
    }
    if (!is_array($terms)) {
        $terms = array($terms);
    }
    if (!$append) {
        $old_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'orderby' => 'none', 'update_term_meta_cache' => false));
    } else {
        $old_tt_ids = array();
    }
    $tt_ids = array();
    $term_ids = array();
    $new_tt_ids = array();
    foreach ((array) $terms as $term) {
        if (!strlen(trim($term))) {
            continue;
        }
        if (!$term_info = term_exists($term, $taxonomy)) {
            // Skip if a non-existent term ID is passed.
            if (is_int($term)) {
                continue;
            }
            $term_info = wp_insert_term($term, $taxonomy);
        }
        if (is_wp_error($term_info)) {
            return $term_info;
        }
        $term_ids[] = $term_info['term_id'];
        $tt_id = $term_info['term_taxonomy_id'];
        $tt_ids[] = $tt_id;
        if ($wpdb->get_var($wpdb->prepare("SELECT term_taxonomy_id FROM {$wpdb->term_relationships} WHERE object_id = %d AND term_taxonomy_id = %d", $object_id, $tt_id))) {
            continue;
        }
        /**
         * Fires immediately before an object-term relationship is added.
         *
         * @since 2.9.0
         * @since 4.7.0 Added the `$taxonomy` parameter.
         *
         * @param int    $object_id Object ID.
         * @param int    $tt_id     Term taxonomy ID.
         * @param string $taxonomy  Taxonomy slug.
         */
        do_action('add_term_relationship', $object_id, $tt_id, $taxonomy);
        $wpdb->insert($wpdb->term_relationships, array('object_id' => $object_id, 'term_taxonomy_id' => $tt_id));
        /**
         * Fires immediately after an object-term relationship is added.
         *
         * @since 2.9.0
         * @since 4.7.0 Added the `$taxonomy` parameter.
         *
         * @param int    $object_id Object ID.
         * @param int    $tt_id     Term taxonomy ID.
         * @param string $taxonomy  Taxonomy slug.
         */
        do_action('added_term_relationship', $object_id, $tt_id, $taxonomy);
        $new_tt_ids[] = $tt_id;
    }
    if ($new_tt_ids) {
        wp_update_term_count($new_tt_ids, $taxonomy);
    }
    if (!$append) {
        $delete_tt_ids = array_diff($old_tt_ids, $tt_ids);
        if ($delete_tt_ids) {
            $in_delete_tt_ids = "'" . implode("', '", $delete_tt_ids) . "'";
            $delete_term_ids = $wpdb->get_col($wpdb->prepare("SELECT tt.term_id FROM {$wpdb->term_taxonomy} AS tt WHERE tt.taxonomy = %s AND tt.term_taxonomy_id IN ({$in_delete_tt_ids})", $taxonomy));
            $delete_term_ids = array_map('intval', $delete_term_ids);
            $remove = wp_remove_object_terms($object_id, $delete_term_ids, $taxonomy);
            if (is_wp_error($remove)) {
                return $remove;
            }
        }
    }
    $t = get_taxonomy($taxonomy);
    if (!$append && isset($t->sort) && $t->sort) {
        $values = array();
        $term_order = 0;
        $final_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'update_term_meta_cache' => false));
        foreach ($tt_ids as $tt_id) {
            if (in_array($tt_id, $final_tt_ids)) {
                $values[] = $wpdb->prepare('(%d, %d, %d)', $object_id, $tt_id, ++$term_order);
            }
        }
        if ($values) {
            if (false === $wpdb->query("INSERT INTO {$wpdb->term_relationships} (object_id, term_taxonomy_id, term_order) VALUES " . join(',', $values) . ' ON DUPLICATE KEY UPDATE term_order = VALUES(term_order)')) {
                return new WP_Error('db_insert_error', __('Could not insert term relationship into the database.'), $wpdb->last_error);
            }
        }
    }
    wp_cache_delete($object_id, $taxonomy . '_relationships');
    wp_cache_delete('last_changed', 'terms');
    /**
     * Fires after an object's terms have been set.
     *
     * @since 2.8.0
     *
     * @param int    $object_id  Object ID.
     * @param array  $terms      An array of object terms.
     * @param array  $tt_ids     An array of term taxonomy IDs.
     * @param string $taxonomy   Taxonomy slug.
     * @param bool   $append     Whether to append new terms to the old terms.
     * @param array  $old_tt_ids Old array of term taxonomy IDs.
     */
    do_action('set_object_terms', $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids);
    return $tt_ids;
}

WordPress Version: 4.9

/**
 * Create Term and Taxonomy Relationships.
 *
 * Relates an object (post, link etc) to a term and taxonomy type. Creates the
 * term and taxonomy relationship if it doesn't already exist. Creates a term if
 * it doesn't exist (using the slug).
 *
 * A relationship means that the term is grouped in or belongs to the taxonomy.
 * A term has no meaning until it is given context by defining which taxonomy it
 * exists under.
 *
 * @since 2.3.0
 *
 * @global wpdb $wpdb The WordPress database abstraction object.
 *
 * @param int              $object_id The object to relate to.
 * @param string|int|array $terms     A single term slug, single term id, or array of either term slugs or ids.
 *                                    Will replace all existing related terms in this taxonomy. Passing an
 *                                    empty value will remove all related terms.
 * @param string           $taxonomy  The context in which to relate the term to the object.
 * @param bool             $append    Optional. If false will delete difference of terms. Default false.
 * @return array|WP_Error Term taxonomy IDs of the affected terms.
 */
function wp_set_object_terms($object_id, $terms, $taxonomy, $append = false)
{
    global $wpdb;
    $object_id = (int) $object_id;
    if (!taxonomy_exists($taxonomy)) {
        return new WP_Error('invalid_taxonomy', __('Invalid taxonomy.'));
    }
    if (!is_array($terms)) {
        $terms = array($terms);
    }
    if (!$append) {
        $old_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'orderby' => 'none'));
    } else {
        $old_tt_ids = array();
    }
    $tt_ids = array();
    $term_ids = array();
    $new_tt_ids = array();
    foreach ((array) $terms as $term) {
        if (!strlen(trim($term))) {
            continue;
        }
        if (!$term_info = term_exists($term, $taxonomy)) {
            // Skip if a non-existent term ID is passed.
            if (is_int($term)) {
                continue;
            }
            $term_info = wp_insert_term($term, $taxonomy);
        }
        if (is_wp_error($term_info)) {
            return $term_info;
        }
        $term_ids[] = $term_info['term_id'];
        $tt_id = $term_info['term_taxonomy_id'];
        $tt_ids[] = $tt_id;
        if ($wpdb->get_var($wpdb->prepare("SELECT term_taxonomy_id FROM {$wpdb->term_relationships} WHERE object_id = %d AND term_taxonomy_id = %d", $object_id, $tt_id))) {
            continue;
        }
        /**
         * Fires immediately before an object-term relationship is added.
         *
         * @since 2.9.0
         * @since 4.7.0 Added the `$taxonomy` parameter.
         *
         * @param int    $object_id Object ID.
         * @param int    $tt_id     Term taxonomy ID.
         * @param string $taxonomy  Taxonomy slug.
         */
        do_action('add_term_relationship', $object_id, $tt_id, $taxonomy);
        $wpdb->insert($wpdb->term_relationships, array('object_id' => $object_id, 'term_taxonomy_id' => $tt_id));
        /**
         * Fires immediately after an object-term relationship is added.
         *
         * @since 2.9.0
         * @since 4.7.0 Added the `$taxonomy` parameter.
         *
         * @param int    $object_id Object ID.
         * @param int    $tt_id     Term taxonomy ID.
         * @param string $taxonomy  Taxonomy slug.
         */
        do_action('added_term_relationship', $object_id, $tt_id, $taxonomy);
        $new_tt_ids[] = $tt_id;
    }
    if ($new_tt_ids) {
        wp_update_term_count($new_tt_ids, $taxonomy);
    }
    if (!$append) {
        $delete_tt_ids = array_diff($old_tt_ids, $tt_ids);
        if ($delete_tt_ids) {
            $in_delete_tt_ids = "'" . implode("', '", $delete_tt_ids) . "'";
            $delete_term_ids = $wpdb->get_col($wpdb->prepare("SELECT tt.term_id FROM {$wpdb->term_taxonomy} AS tt WHERE tt.taxonomy = %s AND tt.term_taxonomy_id IN ({$in_delete_tt_ids})", $taxonomy));
            $delete_term_ids = array_map('intval', $delete_term_ids);
            $remove = wp_remove_object_terms($object_id, $delete_term_ids, $taxonomy);
            if (is_wp_error($remove)) {
                return $remove;
            }
        }
    }
    $t = get_taxonomy($taxonomy);
    if (!$append && isset($t->sort) && $t->sort) {
        $values = array();
        $term_order = 0;
        $final_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids'));
        foreach ($tt_ids as $tt_id) {
            if (in_array($tt_id, $final_tt_ids)) {
                $values[] = $wpdb->prepare("(%d, %d, %d)", $object_id, $tt_id, ++$term_order);
            }
        }
        if ($values) {
            if (false === $wpdb->query("INSERT INTO {$wpdb->term_relationships} (object_id, term_taxonomy_id, term_order) VALUES " . join(',', $values) . " ON DUPLICATE KEY UPDATE term_order = VALUES(term_order)")) {
                return new WP_Error('db_insert_error', __('Could not insert term relationship into the database.'), $wpdb->last_error);
            }
        }
    }
    wp_cache_delete($object_id, $taxonomy . '_relationships');
    wp_cache_delete('last_changed', 'terms');
    /**
     * Fires after an object's terms have been set.
     *
     * @since 2.8.0
     *
     * @param int    $object_id  Object ID.
     * @param array  $terms      An array of object terms.
     * @param array  $tt_ids     An array of term taxonomy IDs.
     * @param string $taxonomy   Taxonomy slug.
     * @param bool   $append     Whether to append new terms to the old terms.
     * @param array  $old_tt_ids Old array of term taxonomy IDs.
     */
    do_action('set_object_terms', $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids);
    return $tt_ids;
}

WordPress Version: 4.8

/**
 * Create Term and Taxonomy Relationships.
 *
 * Relates an object (post, link etc) to a term and taxonomy type. Creates the
 * term and taxonomy relationship if it doesn't already exist. Creates a term if
 * it doesn't exist (using the slug).
 *
 * A relationship means that the term is grouped in or belongs to the taxonomy.
 * A term has no meaning until it is given context by defining which taxonomy it
 * exists under.
 *
 * @since 2.3.0
 *
 * @global wpdb $wpdb The WordPress database abstraction object.
 *
 * @param int              $object_id The object to relate to.
 * @param string|int|array $terms     A single term slug, single term id, or array of either term slugs or ids.
 *                                    Will replace all existing related terms in this taxonomy. Passing an
 *                                    empty value will remove all related terms.
 * @param string           $taxonomy  The context in which to relate the term to the object.
 * @param bool             $append    Optional. If false will delete difference of terms. Default false.
 * @return array|WP_Error Term taxonomy IDs of the affected terms.
 */
function wp_set_object_terms($object_id, $terms, $taxonomy, $append = false)
{
    global $wpdb;
    $object_id = (int) $object_id;
    if (!taxonomy_exists($taxonomy)) {
        return new WP_Error('invalid_taxonomy', __('Invalid taxonomy.'));
    }
    if (!is_array($terms)) {
        $terms = array($terms);
    }
    if (!$append) {
        $old_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'orderby' => 'none'));
    } else {
        $old_tt_ids = array();
    }
    $tt_ids = array();
    $term_ids = array();
    $new_tt_ids = array();
    foreach ((array) $terms as $term) {
        if (!strlen(trim($term))) {
            continue;
        }
        if (!$term_info = term_exists($term, $taxonomy)) {
            // Skip if a non-existent term ID is passed.
            if (is_int($term)) {
                continue;
            }
            $term_info = wp_insert_term($term, $taxonomy);
        }
        if (is_wp_error($term_info)) {
            return $term_info;
        }
        $term_ids[] = $term_info['term_id'];
        $tt_id = $term_info['term_taxonomy_id'];
        $tt_ids[] = $tt_id;
        if ($wpdb->get_var($wpdb->prepare("SELECT term_taxonomy_id FROM {$wpdb->term_relationships} WHERE object_id = %d AND term_taxonomy_id = %d", $object_id, $tt_id))) {
            continue;
        }
        /**
         * Fires immediately before an object-term relationship is added.
         *
         * @since 2.9.0
         * @since 4.7.0 Added the `$taxonomy` parameter.
         *
         * @param int    $object_id Object ID.
         * @param int    $tt_id     Term taxonomy ID.
         * @param string $taxonomy  Taxonomy slug.
         */
        do_action('add_term_relationship', $object_id, $tt_id, $taxonomy);
        $wpdb->insert($wpdb->term_relationships, array('object_id' => $object_id, 'term_taxonomy_id' => $tt_id));
        /**
         * Fires immediately after an object-term relationship is added.
         *
         * @since 2.9.0
         * @since 4.7.0 Added the `$taxonomy` parameter.
         *
         * @param int    $object_id Object ID.
         * @param int    $tt_id     Term taxonomy ID.
         * @param string $taxonomy  Taxonomy slug.
         */
        do_action('added_term_relationship', $object_id, $tt_id, $taxonomy);
        $new_tt_ids[] = $tt_id;
    }
    if ($new_tt_ids) {
        wp_update_term_count($new_tt_ids, $taxonomy);
    }
    if (!$append) {
        $delete_tt_ids = array_diff($old_tt_ids, $tt_ids);
        if ($delete_tt_ids) {
            $in_delete_tt_ids = "'" . implode("', '", $delete_tt_ids) . "'";
            $delete_term_ids = $wpdb->get_col($wpdb->prepare("SELECT tt.term_id FROM {$wpdb->term_taxonomy} AS tt WHERE tt.taxonomy = %s AND tt.term_taxonomy_id IN ({$in_delete_tt_ids})", $taxonomy));
            $delete_term_ids = array_map('intval', $delete_term_ids);
            $remove = wp_remove_object_terms($object_id, $delete_term_ids, $taxonomy);
            if (is_wp_error($remove)) {
                return $remove;
            }
        }
    }
    $t = get_taxonomy($taxonomy);
    if (!$append && isset($t->sort) && $t->sort) {
        $values = array();
        $term_order = 0;
        $final_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids'));
        foreach ($tt_ids as $tt_id) {
            if (in_array($tt_id, $final_tt_ids)) {
                $values[] = $wpdb->prepare("(%d, %d, %d)", $object_id, $tt_id, ++$term_order);
            }
        }
        if ($values) {
            if (false === $wpdb->query("INSERT INTO {$wpdb->term_relationships} (object_id, term_taxonomy_id, term_order) VALUES " . join(',', $values) . " ON DUPLICATE KEY UPDATE term_order = VALUES(term_order)")) {
                return new WP_Error('db_insert_error', __('Could not insert term relationship into the database'), $wpdb->last_error);
            }
        }
    }
    wp_cache_delete($object_id, $taxonomy . '_relationships');
    wp_cache_delete('last_changed', 'terms');
    /**
     * Fires after an object's terms have been set.
     *
     * @since 2.8.0
     *
     * @param int    $object_id  Object ID.
     * @param array  $terms      An array of object terms.
     * @param array  $tt_ids     An array of term taxonomy IDs.
     * @param string $taxonomy   Taxonomy slug.
     * @param bool   $append     Whether to append new terms to the old terms.
     * @param array  $old_tt_ids Old array of term taxonomy IDs.
     */
    do_action('set_object_terms', $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids);
    return $tt_ids;
}

WordPress Version: 4.7

/**
 * Create Term and Taxonomy Relationships.
 *
 * Relates an object (post, link etc) to a term and taxonomy type. Creates the
 * term and taxonomy relationship if it doesn't already exist. Creates a term if
 * it doesn't exist (using the slug).
 *
 * A relationship means that the term is grouped in or belongs to the taxonomy.
 * A term has no meaning until it is given context by defining which taxonomy it
 * exists under.
 *
 * @since 2.3.0
 *
 * @global wpdb $wpdb The WordPress database abstraction object.
 *
 * @param int              $object_id The object to relate to.
 * @param array|int|string $terms     A single term slug, single term id, or array of either term slugs or ids.
 *                                    Will replace all existing related terms in this taxonomy.
 * @param string           $taxonomy  The context in which to relate the term to the object.
 * @param bool             $append    Optional. If false will delete difference of terms. Default false.
 * @return array|WP_Error Term taxonomy IDs of the affected terms.
 */
function wp_set_object_terms($object_id, $terms, $taxonomy, $append = false)
{
    global $wpdb;
    $object_id = (int) $object_id;
    if (!taxonomy_exists($taxonomy)) {
        return new WP_Error('invalid_taxonomy', __('Invalid taxonomy.'));
    }
    if (!is_array($terms)) {
        $terms = array($terms);
    }
    if (!$append) {
        $old_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'orderby' => 'none'));
    } else {
        $old_tt_ids = array();
    }
    $tt_ids = array();
    $term_ids = array();
    $new_tt_ids = array();
    foreach ((array) $terms as $term) {
        if (!strlen(trim($term))) {
            continue;
        }
        if (!$term_info = term_exists($term, $taxonomy)) {
            // Skip if a non-existent term ID is passed.
            if (is_int($term)) {
                continue;
            }
            $term_info = wp_insert_term($term, $taxonomy);
        }
        if (is_wp_error($term_info)) {
            return $term_info;
        }
        $term_ids[] = $term_info['term_id'];
        $tt_id = $term_info['term_taxonomy_id'];
        $tt_ids[] = $tt_id;
        if ($wpdb->get_var($wpdb->prepare("SELECT term_taxonomy_id FROM {$wpdb->term_relationships} WHERE object_id = %d AND term_taxonomy_id = %d", $object_id, $tt_id))) {
            continue;
        }
        /**
         * Fires immediately before an object-term relationship is added.
         *
         * @since 2.9.0
         * @since 4.7.0 Added the `$taxonomy` parameter.
         *
         * @param int    $object_id Object ID.
         * @param int    $tt_id     Term taxonomy ID.
         * @param string $taxonomy  Taxonomy slug.
         */
        do_action('add_term_relationship', $object_id, $tt_id, $taxonomy);
        $wpdb->insert($wpdb->term_relationships, array('object_id' => $object_id, 'term_taxonomy_id' => $tt_id));
        /**
         * Fires immediately after an object-term relationship is added.
         *
         * @since 2.9.0
         * @since 4.7.0 Added the `$taxonomy` parameter.
         *
         * @param int    $object_id Object ID.
         * @param int    $tt_id     Term taxonomy ID.
         * @param string $taxonomy  Taxonomy slug.
         */
        do_action('added_term_relationship', $object_id, $tt_id, $taxonomy);
        $new_tt_ids[] = $tt_id;
    }
    if ($new_tt_ids) {
        wp_update_term_count($new_tt_ids, $taxonomy);
    }
    if (!$append) {
        $delete_tt_ids = array_diff($old_tt_ids, $tt_ids);
        if ($delete_tt_ids) {
            $in_delete_tt_ids = "'" . implode("', '", $delete_tt_ids) . "'";
            $delete_term_ids = $wpdb->get_col($wpdb->prepare("SELECT tt.term_id FROM {$wpdb->term_taxonomy} AS tt WHERE tt.taxonomy = %s AND tt.term_taxonomy_id IN ({$in_delete_tt_ids})", $taxonomy));
            $delete_term_ids = array_map('intval', $delete_term_ids);
            $remove = wp_remove_object_terms($object_id, $delete_term_ids, $taxonomy);
            if (is_wp_error($remove)) {
                return $remove;
            }
        }
    }
    $t = get_taxonomy($taxonomy);
    if (!$append && isset($t->sort) && $t->sort) {
        $values = array();
        $term_order = 0;
        $final_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids'));
        foreach ($tt_ids as $tt_id) {
            if (in_array($tt_id, $final_tt_ids)) {
                $values[] = $wpdb->prepare("(%d, %d, %d)", $object_id, $tt_id, ++$term_order);
            }
        }
        if ($values) {
            if (false === $wpdb->query("INSERT INTO {$wpdb->term_relationships} (object_id, term_taxonomy_id, term_order) VALUES " . join(',', $values) . " ON DUPLICATE KEY UPDATE term_order = VALUES(term_order)")) {
                return new WP_Error('db_insert_error', __('Could not insert term relationship into the database'), $wpdb->last_error);
            }
        }
    }
    wp_cache_delete($object_id, $taxonomy . '_relationships');
    /**
     * Fires after an object's terms have been set.
     *
     * @since 2.8.0
     *
     * @param int    $object_id  Object ID.
     * @param array  $terms      An array of object terms.
     * @param array  $tt_ids     An array of term taxonomy IDs.
     * @param string $taxonomy   Taxonomy slug.
     * @param bool   $append     Whether to append new terms to the old terms.
     * @param array  $old_tt_ids Old array of term taxonomy IDs.
     */
    do_action('set_object_terms', $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids);
    return $tt_ids;
}

WordPress Version: 4.6

/**
 * Create Term and Taxonomy Relationships.
 *
 * Relates an object (post, link etc) to a term and taxonomy type. Creates the
 * term and taxonomy relationship if it doesn't already exist. Creates a term if
 * it doesn't exist (using the slug).
 *
 * A relationship means that the term is grouped in or belongs to the taxonomy.
 * A term has no meaning until it is given context by defining which taxonomy it
 * exists under.
 *
 * @since 2.3.0
 *
 * @global wpdb $wpdb The WordPress database abstraction object.
 *
 * @param int              $object_id The object to relate to.
 * @param array|int|string $terms     A single term slug, single term id, or array of either term slugs or ids.
 *                                    Will replace all existing related terms in this taxonomy.
 * @param string           $taxonomy  The context in which to relate the term to the object.
 * @param bool             $append    Optional. If false will delete difference of terms. Default false.
 * @return array|WP_Error Term taxonomy IDs of the affected terms.
 */
function wp_set_object_terms($object_id, $terms, $taxonomy, $append = false)
{
    global $wpdb;
    $object_id = (int) $object_id;
    if (!taxonomy_exists($taxonomy)) {
        return new WP_Error('invalid_taxonomy', __('Invalid taxonomy.'));
    }
    if (!is_array($terms)) {
        $terms = array($terms);
    }
    if (!$append) {
        $old_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'orderby' => 'none'));
    } else {
        $old_tt_ids = array();
    }
    $tt_ids = array();
    $term_ids = array();
    $new_tt_ids = array();
    foreach ((array) $terms as $term) {
        if (!strlen(trim($term))) {
            continue;
        }
        if (!$term_info = term_exists($term, $taxonomy)) {
            // Skip if a non-existent term ID is passed.
            if (is_int($term)) {
                continue;
            }
            $term_info = wp_insert_term($term, $taxonomy);
        }
        if (is_wp_error($term_info)) {
            return $term_info;
        }
        $term_ids[] = $term_info['term_id'];
        $tt_id = $term_info['term_taxonomy_id'];
        $tt_ids[] = $tt_id;
        if ($wpdb->get_var($wpdb->prepare("SELECT term_taxonomy_id FROM {$wpdb->term_relationships} WHERE object_id = %d AND term_taxonomy_id = %d", $object_id, $tt_id))) {
            continue;
        }
        /**
         * Fires immediately before an object-term relationship is added.
         *
         * @since 2.9.0
         *
         * @param int $object_id Object ID.
         * @param int $tt_id     Term taxonomy ID.
         */
        do_action('add_term_relationship', $object_id, $tt_id);
        $wpdb->insert($wpdb->term_relationships, array('object_id' => $object_id, 'term_taxonomy_id' => $tt_id));
        /**
         * Fires immediately after an object-term relationship is added.
         *
         * @since 2.9.0
         *
         * @param int $object_id Object ID.
         * @param int $tt_id     Term taxonomy ID.
         */
        do_action('added_term_relationship', $object_id, $tt_id);
        $new_tt_ids[] = $tt_id;
    }
    if ($new_tt_ids) {
        wp_update_term_count($new_tt_ids, $taxonomy);
    }
    if (!$append) {
        $delete_tt_ids = array_diff($old_tt_ids, $tt_ids);
        if ($delete_tt_ids) {
            $in_delete_tt_ids = "'" . implode("', '", $delete_tt_ids) . "'";
            $delete_term_ids = $wpdb->get_col($wpdb->prepare("SELECT tt.term_id FROM {$wpdb->term_taxonomy} AS tt WHERE tt.taxonomy = %s AND tt.term_taxonomy_id IN ({$in_delete_tt_ids})", $taxonomy));
            $delete_term_ids = array_map('intval', $delete_term_ids);
            $remove = wp_remove_object_terms($object_id, $delete_term_ids, $taxonomy);
            if (is_wp_error($remove)) {
                return $remove;
            }
        }
    }
    $t = get_taxonomy($taxonomy);
    if (!$append && isset($t->sort) && $t->sort) {
        $values = array();
        $term_order = 0;
        $final_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids'));
        foreach ($tt_ids as $tt_id) {
            if (in_array($tt_id, $final_tt_ids)) {
                $values[] = $wpdb->prepare("(%d, %d, %d)", $object_id, $tt_id, ++$term_order);
            }
        }
        if ($values) {
            if (false === $wpdb->query("INSERT INTO {$wpdb->term_relationships} (object_id, term_taxonomy_id, term_order) VALUES " . join(',', $values) . " ON DUPLICATE KEY UPDATE term_order = VALUES(term_order)")) {
                return new WP_Error('db_insert_error', __('Could not insert term relationship into the database'), $wpdb->last_error);
            }
        }
    }
    wp_cache_delete($object_id, $taxonomy . '_relationships');
    /**
     * Fires after an object's terms have been set.
     *
     * @since 2.8.0
     *
     * @param int    $object_id  Object ID.
     * @param array  $terms      An array of object terms.
     * @param array  $tt_ids     An array of term taxonomy IDs.
     * @param string $taxonomy   Taxonomy slug.
     * @param bool   $append     Whether to append new terms to the old terms.
     * @param array  $old_tt_ids Old array of term taxonomy IDs.
     */
    do_action('set_object_terms', $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids);
    return $tt_ids;
}

WordPress Version: 4.5

/**
 * Create Term and Taxonomy Relationships.
 *
 * Relates an object (post, link etc) to a term and taxonomy type. Creates the
 * term and taxonomy relationship if it doesn't already exist. Creates a term if
 * it doesn't exist (using the slug).
 *
 * A relationship means that the term is grouped in or belongs to the taxonomy.
 * A term has no meaning until it is given context by defining which taxonomy it
 * exists under.
 *
 * @since 2.3.0
 *
 * @global wpdb $wpdb The WordPress database abstraction object.
 *
 * @param int              $object_id The object to relate to.
 * @param array|int|string $terms     A single term slug, single term id, or array of either term slugs or ids.
 *                                    Will replace all existing related terms in this taxonomy.
 * @param string           $taxonomy  The context in which to relate the term to the object.
 * @param bool             $append    Optional. If false will delete difference of terms. Default false.
 * @return array|WP_Error Term taxonomy IDs of the affected terms.
 */
function wp_set_object_terms($object_id, $terms, $taxonomy, $append = false)
{
    global $wpdb;
    $object_id = (int) $object_id;
    if (!taxonomy_exists($taxonomy)) {
        return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
    }
    if (!is_array($terms)) {
        $terms = array($terms);
    }
    if (!$append) {
        $old_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'orderby' => 'none'));
    } else {
        $old_tt_ids = array();
    }
    $tt_ids = array();
    $term_ids = array();
    $new_tt_ids = array();
    foreach ((array) $terms as $term) {
        if (!strlen(trim($term))) {
            continue;
        }
        if (!$term_info = term_exists($term, $taxonomy)) {
            // Skip if a non-existent term ID is passed.
            if (is_int($term)) {
                continue;
            }
            $term_info = wp_insert_term($term, $taxonomy);
        }
        if (is_wp_error($term_info)) {
            return $term_info;
        }
        $term_ids[] = $term_info['term_id'];
        $tt_id = $term_info['term_taxonomy_id'];
        $tt_ids[] = $tt_id;
        if ($wpdb->get_var($wpdb->prepare("SELECT term_taxonomy_id FROM {$wpdb->term_relationships} WHERE object_id = %d AND term_taxonomy_id = %d", $object_id, $tt_id))) {
            continue;
        }
        /**
         * Fires immediately before an object-term relationship is added.
         *
         * @since 2.9.0
         *
         * @param int $object_id Object ID.
         * @param int $tt_id     Term taxonomy ID.
         */
        do_action('add_term_relationship', $object_id, $tt_id);
        $wpdb->insert($wpdb->term_relationships, array('object_id' => $object_id, 'term_taxonomy_id' => $tt_id));
        /**
         * Fires immediately after an object-term relationship is added.
         *
         * @since 2.9.0
         *
         * @param int $object_id Object ID.
         * @param int $tt_id     Term taxonomy ID.
         */
        do_action('added_term_relationship', $object_id, $tt_id);
        $new_tt_ids[] = $tt_id;
    }
    if ($new_tt_ids) {
        wp_update_term_count($new_tt_ids, $taxonomy);
    }
    if (!$append) {
        $delete_tt_ids = array_diff($old_tt_ids, $tt_ids);
        if ($delete_tt_ids) {
            $in_delete_tt_ids = "'" . implode("', '", $delete_tt_ids) . "'";
            $delete_term_ids = $wpdb->get_col($wpdb->prepare("SELECT tt.term_id FROM {$wpdb->term_taxonomy} AS tt WHERE tt.taxonomy = %s AND tt.term_taxonomy_id IN ({$in_delete_tt_ids})", $taxonomy));
            $delete_term_ids = array_map('intval', $delete_term_ids);
            $remove = wp_remove_object_terms($object_id, $delete_term_ids, $taxonomy);
            if (is_wp_error($remove)) {
                return $remove;
            }
        }
    }
    $t = get_taxonomy($taxonomy);
    if (!$append && isset($t->sort) && $t->sort) {
        $values = array();
        $term_order = 0;
        $final_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids'));
        foreach ($tt_ids as $tt_id) {
            if (in_array($tt_id, $final_tt_ids)) {
                $values[] = $wpdb->prepare("(%d, %d, %d)", $object_id, $tt_id, ++$term_order);
            }
        }
        if ($values) {
            if (false === $wpdb->query("INSERT INTO {$wpdb->term_relationships} (object_id, term_taxonomy_id, term_order) VALUES " . join(',', $values) . " ON DUPLICATE KEY UPDATE term_order = VALUES(term_order)")) {
                return new WP_Error('db_insert_error', __('Could not insert term relationship into the database'), $wpdb->last_error);
            }
        }
    }
    wp_cache_delete($object_id, $taxonomy . '_relationships');
    /**
     * Fires after an object's terms have been set.
     *
     * @since 2.8.0
     *
     * @param int    $object_id  Object ID.
     * @param array  $terms      An array of object terms.
     * @param array  $tt_ids     An array of term taxonomy IDs.
     * @param string $taxonomy   Taxonomy slug.
     * @param bool   $append     Whether to append new terms to the old terms.
     * @param array  $old_tt_ids Old array of term taxonomy IDs.
     */
    do_action('set_object_terms', $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids);
    return $tt_ids;
}

WordPress Version: 4.3

/**
 * Create Term and Taxonomy Relationships.
 *
 * Relates an object (post, link etc) to a term and taxonomy type. Creates the
 * term and taxonomy relationship if it doesn't already exist. Creates a term if
 * it doesn't exist (using the slug).
 *
 * A relationship means that the term is grouped in or belongs to the taxonomy.
 * A term has no meaning until it is given context by defining which taxonomy it
 * exists under.
 *
 * @since 2.3.0
 *
 * @global wpdb $wpdb The WordPress database abstraction object.
 *
 * @param int              $object_id The object to relate to.
 * @param array|int|string $terms     A single term slug, single term id, or array of either term slugs or ids.
 *                                    Will replace all existing related terms in this taxonomy.
 * @param string           $taxonomy  The context in which to relate the term to the object.
 * @param bool             $append    Optional. If false will delete difference of terms. Default false.
 * @return array|WP_Error Affected Term IDs.
 */
function wp_set_object_terms($object_id, $terms, $taxonomy, $append = false)
{
    global $wpdb;
    $object_id = (int) $object_id;
    if (!taxonomy_exists($taxonomy)) {
        return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
    }
    if (!is_array($terms)) {
        $terms = array($terms);
    }
    if (!$append) {
        $old_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'orderby' => 'none'));
    } else {
        $old_tt_ids = array();
    }
    $tt_ids = array();
    $term_ids = array();
    $new_tt_ids = array();
    foreach ((array) $terms as $term) {
        if (!strlen(trim($term))) {
            continue;
        }
        if (!$term_info = term_exists($term, $taxonomy)) {
            // Skip if a non-existent term ID is passed.
            if (is_int($term)) {
                continue;
            }
            $term_info = wp_insert_term($term, $taxonomy);
        }
        if (is_wp_error($term_info)) {
            return $term_info;
        }
        $term_ids[] = $term_info['term_id'];
        $tt_id = $term_info['term_taxonomy_id'];
        $tt_ids[] = $tt_id;
        if ($wpdb->get_var($wpdb->prepare("SELECT term_taxonomy_id FROM {$wpdb->term_relationships} WHERE object_id = %d AND term_taxonomy_id = %d", $object_id, $tt_id))) {
            continue;
        }
        /**
         * Fires immediately before an object-term relationship is added.
         *
         * @since 2.9.0
         *
         * @param int $object_id Object ID.
         * @param int $tt_id     Term taxonomy ID.
         */
        do_action('add_term_relationship', $object_id, $tt_id);
        $wpdb->insert($wpdb->term_relationships, array('object_id' => $object_id, 'term_taxonomy_id' => $tt_id));
        /**
         * Fires immediately after an object-term relationship is added.
         *
         * @since 2.9.0
         *
         * @param int $object_id Object ID.
         * @param int $tt_id     Term taxonomy ID.
         */
        do_action('added_term_relationship', $object_id, $tt_id);
        $new_tt_ids[] = $tt_id;
    }
    if ($new_tt_ids) {
        wp_update_term_count($new_tt_ids, $taxonomy);
    }
    if (!$append) {
        $delete_tt_ids = array_diff($old_tt_ids, $tt_ids);
        if ($delete_tt_ids) {
            $in_delete_tt_ids = "'" . implode("', '", $delete_tt_ids) . "'";
            $delete_term_ids = $wpdb->get_col($wpdb->prepare("SELECT tt.term_id FROM {$wpdb->term_taxonomy} AS tt WHERE tt.taxonomy = %s AND tt.term_taxonomy_id IN ({$in_delete_tt_ids})", $taxonomy));
            $delete_term_ids = array_map('intval', $delete_term_ids);
            $remove = wp_remove_object_terms($object_id, $delete_term_ids, $taxonomy);
            if (is_wp_error($remove)) {
                return $remove;
            }
        }
    }
    $t = get_taxonomy($taxonomy);
    if (!$append && isset($t->sort) && $t->sort) {
        $values = array();
        $term_order = 0;
        $final_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids'));
        foreach ($tt_ids as $tt_id) {
            if (in_array($tt_id, $final_tt_ids)) {
                $values[] = $wpdb->prepare("(%d, %d, %d)", $object_id, $tt_id, ++$term_order);
            }
        }
        if ($values) {
            if (false === $wpdb->query("INSERT INTO {$wpdb->term_relationships} (object_id, term_taxonomy_id, term_order) VALUES " . join(',', $values) . " ON DUPLICATE KEY UPDATE term_order = VALUES(term_order)")) {
                return new WP_Error('db_insert_error', __('Could not insert term relationship into the database'), $wpdb->last_error);
            }
        }
    }
    wp_cache_delete($object_id, $taxonomy . '_relationships');
    /**
     * Fires after an object's terms have been set.
     *
     * @since 2.8.0
     *
     * @param int    $object_id  Object ID.
     * @param array  $terms      An array of object terms.
     * @param array  $tt_ids     An array of term taxonomy IDs.
     * @param string $taxonomy   Taxonomy slug.
     * @param bool   $append     Whether to append new terms to the old terms.
     * @param array  $old_tt_ids Old array of term taxonomy IDs.
     */
    do_action('set_object_terms', $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids);
    return $tt_ids;
}

WordPress Version: 4.2

/**
 * Create Term and Taxonomy Relationships.
 *
 * Relates an object (post, link etc) to a term and taxonomy type. Creates the
 * term and taxonomy relationship if it doesn't already exist. Creates a term if
 * it doesn't exist (using the slug).
 *
 * A relationship means that the term is grouped in or belongs to the taxonomy.
 * A term has no meaning until it is given context by defining which taxonomy it
 * exists under.
 *
 * @since 2.3.0
 *
 * @param int              $object_id The object to relate to.
 * @param array|int|string $terms     A single term slug, single term id, or array of either term slugs or ids.
 *                                    Will replace all existing related terms in this taxonomy.
 * @param string           $taxonomy  The context in which to relate the term to the object.
 * @param bool             $append    Optional. If false will delete difference of terms. Default false.
 * @return array|WP_Error Affected Term IDs.
 */
function wp_set_object_terms($object_id, $terms, $taxonomy, $append = false)
{
    global $wpdb;
    $object_id = (int) $object_id;
    if (!taxonomy_exists($taxonomy)) {
        return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
    }
    if (!is_array($terms)) {
        $terms = array($terms);
    }
    if (!$append) {
        $old_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'orderby' => 'none'));
    } else {
        $old_tt_ids = array();
    }
    $tt_ids = array();
    $term_ids = array();
    $new_tt_ids = array();
    foreach ((array) $terms as $term) {
        if (!strlen(trim($term))) {
            continue;
        }
        if (!$term_info = term_exists($term, $taxonomy)) {
            // Skip if a non-existent term ID is passed.
            if (is_int($term)) {
                continue;
            }
            $term_info = wp_insert_term($term, $taxonomy);
        }
        if (is_wp_error($term_info)) {
            return $term_info;
        }
        $term_ids[] = $term_info['term_id'];
        $tt_id = $term_info['term_taxonomy_id'];
        $tt_ids[] = $tt_id;
        if ($wpdb->get_var($wpdb->prepare("SELECT term_taxonomy_id FROM {$wpdb->term_relationships} WHERE object_id = %d AND term_taxonomy_id = %d", $object_id, $tt_id))) {
            continue;
        }
        /**
         * Fires immediately before an object-term relationship is added.
         *
         * @since 2.9.0
         *
         * @param int $object_id Object ID.
         * @param int $tt_id     Term taxonomy ID.
         */
        do_action('add_term_relationship', $object_id, $tt_id);
        $wpdb->insert($wpdb->term_relationships, array('object_id' => $object_id, 'term_taxonomy_id' => $tt_id));
        /**
         * Fires immediately after an object-term relationship is added.
         *
         * @since 2.9.0
         *
         * @param int $object_id Object ID.
         * @param int $tt_id     Term taxonomy ID.
         */
        do_action('added_term_relationship', $object_id, $tt_id);
        $new_tt_ids[] = $tt_id;
    }
    if ($new_tt_ids) {
        wp_update_term_count($new_tt_ids, $taxonomy);
    }
    if (!$append) {
        $delete_tt_ids = array_diff($old_tt_ids, $tt_ids);
        if ($delete_tt_ids) {
            $in_delete_tt_ids = "'" . implode("', '", $delete_tt_ids) . "'";
            $delete_term_ids = $wpdb->get_col($wpdb->prepare("SELECT tt.term_id FROM {$wpdb->term_taxonomy} AS tt WHERE tt.taxonomy = %s AND tt.term_taxonomy_id IN ({$in_delete_tt_ids})", $taxonomy));
            $delete_term_ids = array_map('intval', $delete_term_ids);
            $remove = wp_remove_object_terms($object_id, $delete_term_ids, $taxonomy);
            if (is_wp_error($remove)) {
                return $remove;
            }
        }
    }
    $t = get_taxonomy($taxonomy);
    if (!$append && isset($t->sort) && $t->sort) {
        $values = array();
        $term_order = 0;
        $final_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids'));
        foreach ($tt_ids as $tt_id) {
            if (in_array($tt_id, $final_tt_ids)) {
                $values[] = $wpdb->prepare("(%d, %d, %d)", $object_id, $tt_id, ++$term_order);
            }
        }
        if ($values) {
            if (false === $wpdb->query("INSERT INTO {$wpdb->term_relationships} (object_id, term_taxonomy_id, term_order) VALUES " . join(',', $values) . " ON DUPLICATE KEY UPDATE term_order = VALUES(term_order)")) {
                return new WP_Error('db_insert_error', __('Could not insert term relationship into the database'), $wpdb->last_error);
            }
        }
    }
    wp_cache_delete($object_id, $taxonomy . '_relationships');
    /**
     * Fires after an object's terms have been set.
     *
     * @since 2.8.0
     *
     * @param int    $object_id  Object ID.
     * @param array  $terms      An array of object terms.
     * @param array  $tt_ids     An array of term taxonomy IDs.
     * @param string $taxonomy   Taxonomy slug.
     * @param bool   $append     Whether to append new terms to the old terms.
     * @param array  $old_tt_ids Old array of term taxonomy IDs.
     */
    do_action('set_object_terms', $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids);
    return $tt_ids;
}

WordPress Version: 4.1

/**
 * Create Term and Taxonomy Relationships.
 *
 * Relates an object (post, link etc) to a term and taxonomy type. Creates the
 * term and taxonomy relationship if it doesn't already exist. Creates a term if
 * it doesn't exist (using the slug).
 *
 * A relationship means that the term is grouped in or belongs to the taxonomy.
 * A term has no meaning until it is given context by defining which taxonomy it
 * exists under.
 *
 * @since 2.3.0
 *
 * @param int              $object_id The object to relate to.
 * @param array|int|string $terms     A single term slug, single term id, or array of either term slugs or ids.
 *                                    Will replace all existing related terms in this taxonomy.
 * @param array|string     $taxonomy  The context in which to relate the term to the object.
 * @param bool             $append    Optional. If false will delete difference of terms. Default false.
 * @return array|WP_Error Affected Term IDs.
 */
function wp_set_object_terms($object_id, $terms, $taxonomy, $append = false)
{
    global $wpdb;
    $object_id = (int) $object_id;
    if (!taxonomy_exists($taxonomy)) {
        return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
    }
    if (!is_array($terms)) {
        $terms = array($terms);
    }
    if (!$append) {
        $old_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'orderby' => 'none'));
    } else {
        $old_tt_ids = array();
    }
    $tt_ids = array();
    $term_ids = array();
    $new_tt_ids = array();
    foreach ((array) $terms as $term) {
        if (!strlen(trim($term))) {
            continue;
        }
        if (!$term_info = term_exists($term, $taxonomy)) {
            // Skip if a non-existent term ID is passed.
            if (is_int($term)) {
                continue;
            }
            $term_info = wp_insert_term($term, $taxonomy);
        }
        if (is_wp_error($term_info)) {
            return $term_info;
        }
        $term_ids[] = $term_info['term_id'];
        $tt_id = $term_info['term_taxonomy_id'];
        $tt_ids[] = $tt_id;
        if ($wpdb->get_var($wpdb->prepare("SELECT term_taxonomy_id FROM {$wpdb->term_relationships} WHERE object_id = %d AND term_taxonomy_id = %d", $object_id, $tt_id))) {
            continue;
        }
        /**
         * Fires immediately before an object-term relationship is added.
         *
         * @since 2.9.0
         *
         * @param int $object_id Object ID.
         * @param int $tt_id     Term taxonomy ID.
         */
        do_action('add_term_relationship', $object_id, $tt_id);
        $wpdb->insert($wpdb->term_relationships, array('object_id' => $object_id, 'term_taxonomy_id' => $tt_id));
        /**
         * Fires immediately after an object-term relationship is added.
         *
         * @since 2.9.0
         *
         * @param int $object_id Object ID.
         * @param int $tt_id     Term taxonomy ID.
         */
        do_action('added_term_relationship', $object_id, $tt_id);
        $new_tt_ids[] = $tt_id;
    }
    if ($new_tt_ids) {
        wp_update_term_count($new_tt_ids, $taxonomy);
    }
    if (!$append) {
        $delete_tt_ids = array_diff($old_tt_ids, $tt_ids);
        if ($delete_tt_ids) {
            $in_delete_tt_ids = "'" . implode("', '", $delete_tt_ids) . "'";
            $delete_term_ids = $wpdb->get_col($wpdb->prepare("SELECT tt.term_id FROM {$wpdb->term_taxonomy} AS tt WHERE tt.taxonomy = %s AND tt.term_taxonomy_id IN ({$in_delete_tt_ids})", $taxonomy));
            $delete_term_ids = array_map('intval', $delete_term_ids);
            $remove = wp_remove_object_terms($object_id, $delete_term_ids, $taxonomy);
            if (is_wp_error($remove)) {
                return $remove;
            }
        }
    }
    $t = get_taxonomy($taxonomy);
    if (!$append && isset($t->sort) && $t->sort) {
        $values = array();
        $term_order = 0;
        $final_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids'));
        foreach ($tt_ids as $tt_id) {
            if (in_array($tt_id, $final_tt_ids)) {
                $values[] = $wpdb->prepare("(%d, %d, %d)", $object_id, $tt_id, ++$term_order);
            }
        }
        if ($values) {
            if (false === $wpdb->query("INSERT INTO {$wpdb->term_relationships} (object_id, term_taxonomy_id, term_order) VALUES " . join(',', $values) . " ON DUPLICATE KEY UPDATE term_order = VALUES(term_order)")) {
                return new WP_Error('db_insert_error', __('Could not insert term relationship into the database'), $wpdb->last_error);
            }
        }
    }
    wp_cache_delete($object_id, $taxonomy . '_relationships');
    /**
     * Fires after an object's terms have been set.
     *
     * @since 2.8.0
     *
     * @param int    $object_id  Object ID.
     * @param array  $terms      An array of object terms.
     * @param array  $tt_ids     An array of term taxonomy IDs.
     * @param string $taxonomy   Taxonomy slug.
     * @param bool   $append     Whether to append new terms to the old terms.
     * @param array  $old_tt_ids Old array of term taxonomy IDs.
     */
    do_action('set_object_terms', $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids);
    return $tt_ids;
}

WordPress Version: 4.0

/**
 * Create Term and Taxonomy Relationships.
 *
 * Relates an object (post, link etc) to a term and taxonomy type. Creates the
 * term and taxonomy relationship if it doesn't already exist. Creates a term if
 * it doesn't exist (using the slug).
 *
 * A relationship means that the term is grouped in or belongs to the taxonomy.
 * A term has no meaning until it is given context by defining which taxonomy it
 * exists under.
 *
 * @since 2.3.0
 * @uses wp_remove_object_terms()
 *
 * @param int              $object_id The object to relate to.
 * @param array|int|string $terms     A single term slug, single term id, or array of either term slugs or ids.
 *                                    Will replace all existing related terms in this taxonomy.
 * @param array|string     $taxonomy  The context in which to relate the term to the object.
 * @param bool             $append    Optional. If false will delete difference of terms. Default false.
 * @return array|WP_Error Affected Term IDs.
 */
function wp_set_object_terms($object_id, $terms, $taxonomy, $append = false)
{
    global $wpdb;
    $object_id = (int) $object_id;
    if (!taxonomy_exists($taxonomy)) {
        return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
    }
    if (!is_array($terms)) {
        $terms = array($terms);
    }
    if (!$append) {
        $old_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'orderby' => 'none'));
    } else {
        $old_tt_ids = array();
    }
    $tt_ids = array();
    $term_ids = array();
    $new_tt_ids = array();
    foreach ((array) $terms as $term) {
        if (!strlen(trim($term))) {
            continue;
        }
        if (!$term_info = term_exists($term, $taxonomy)) {
            // Skip if a non-existent term ID is passed.
            if (is_int($term)) {
                continue;
            }
            $term_info = wp_insert_term($term, $taxonomy);
        }
        if (is_wp_error($term_info)) {
            return $term_info;
        }
        $term_ids[] = $term_info['term_id'];
        $tt_id = $term_info['term_taxonomy_id'];
        $tt_ids[] = $tt_id;
        if ($wpdb->get_var($wpdb->prepare("SELECT term_taxonomy_id FROM {$wpdb->term_relationships} WHERE object_id = %d AND term_taxonomy_id = %d", $object_id, $tt_id))) {
            continue;
        }
        /**
         * Fires immediately before an object-term relationship is added.
         *
         * @since 2.9.0
         *
         * @param int $object_id Object ID.
         * @param int $tt_id     Term taxonomy ID.
         */
        do_action('add_term_relationship', $object_id, $tt_id);
        $wpdb->insert($wpdb->term_relationships, array('object_id' => $object_id, 'term_taxonomy_id' => $tt_id));
        /**
         * Fires immediately after an object-term relationship is added.
         *
         * @since 2.9.0
         *
         * @param int $object_id Object ID.
         * @param int $tt_id     Term taxonomy ID.
         */
        do_action('added_term_relationship', $object_id, $tt_id);
        $new_tt_ids[] = $tt_id;
    }
    if ($new_tt_ids) {
        wp_update_term_count($new_tt_ids, $taxonomy);
    }
    if (!$append) {
        $delete_tt_ids = array_diff($old_tt_ids, $tt_ids);
        if ($delete_tt_ids) {
            $in_delete_tt_ids = "'" . implode("', '", $delete_tt_ids) . "'";
            $delete_term_ids = $wpdb->get_col($wpdb->prepare("SELECT tt.term_id FROM {$wpdb->term_taxonomy} AS tt WHERE tt.taxonomy = %s AND tt.term_taxonomy_id IN ({$in_delete_tt_ids})", $taxonomy));
            $delete_term_ids = array_map('intval', $delete_term_ids);
            $remove = wp_remove_object_terms($object_id, $delete_term_ids, $taxonomy);
            if (is_wp_error($remove)) {
                return $remove;
            }
        }
    }
    $t = get_taxonomy($taxonomy);
    if (!$append && isset($t->sort) && $t->sort) {
        $values = array();
        $term_order = 0;
        $final_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids'));
        foreach ($tt_ids as $tt_id) {
            if (in_array($tt_id, $final_tt_ids)) {
                $values[] = $wpdb->prepare("(%d, %d, %d)", $object_id, $tt_id, ++$term_order);
            }
        }
        if ($values) {
            if (false === $wpdb->query("INSERT INTO {$wpdb->term_relationships} (object_id, term_taxonomy_id, term_order) VALUES " . join(',', $values) . " ON DUPLICATE KEY UPDATE term_order = VALUES(term_order)")) {
                return new WP_Error('db_insert_error', __('Could not insert term relationship into the database'), $wpdb->last_error);
            }
        }
    }
    wp_cache_delete($object_id, $taxonomy . '_relationships');
    /**
     * Fires after an object's terms have been set.
     *
     * @since 2.8.0
     *
     * @param int    $object_id  Object ID.
     * @param array  $terms      An array of object terms.
     * @param array  $tt_ids     An array of term taxonomy IDs.
     * @param string $taxonomy   Taxonomy slug.
     * @param bool   $append     Whether to append new terms to the old terms.
     * @param array  $old_tt_ids Old array of term taxonomy IDs.
     */
    do_action('set_object_terms', $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids);
    return $tt_ids;
}

WordPress Version: 3.9

/**
 * Create Term and Taxonomy Relationships.
 *
 * Relates an object (post, link etc) to a term and taxonomy type. Creates the
 * term and taxonomy relationship if it doesn't already exist. Creates a term if
 * it doesn't exist (using the slug).
 *
 * A relationship means that the term is grouped in or belongs to the taxonomy.
 * A term has no meaning until it is given context by defining which taxonomy it
 * exists under.
 *
 * @since 2.3.0
 * @uses wp_remove_object_terms()
 *
 * @param int $object_id The object to relate to.
 * @param array|int|string $terms The slug or id of the term, will replace all existing
 * related terms in this taxonomy.
 * @param array|string $taxonomy The context in which to relate the term to the object.
 * @param bool $append If false will delete difference of terms.
 * @return array|WP_Error Affected Term IDs
 */
function wp_set_object_terms($object_id, $terms, $taxonomy, $append = false)
{
    global $wpdb;
    $object_id = (int) $object_id;
    if (!taxonomy_exists($taxonomy)) {
        return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
    }
    if (!is_array($terms)) {
        $terms = array($terms);
    }
    if (!$append) {
        $old_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'orderby' => 'none'));
    } else {
        $old_tt_ids = array();
    }
    $tt_ids = array();
    $term_ids = array();
    $new_tt_ids = array();
    foreach ((array) $terms as $term) {
        if (!strlen(trim($term))) {
            continue;
        }
        if (!$term_info = term_exists($term, $taxonomy)) {
            // Skip if a non-existent term ID is passed.
            if (is_int($term)) {
                continue;
            }
            $term_info = wp_insert_term($term, $taxonomy);
        }
        if (is_wp_error($term_info)) {
            return $term_info;
        }
        $term_ids[] = $term_info['term_id'];
        $tt_id = $term_info['term_taxonomy_id'];
        $tt_ids[] = $tt_id;
        if ($wpdb->get_var($wpdb->prepare("SELECT term_taxonomy_id FROM {$wpdb->term_relationships} WHERE object_id = %d AND term_taxonomy_id = %d", $object_id, $tt_id))) {
            continue;
        }
        /**
         * Fires immediately before an object-term relationship is added.
         *
         * @since 2.9.0
         *
         * @param int $object_id Object ID.
         * @param int $tt_id     Term taxonomy ID.
         */
        do_action('add_term_relationship', $object_id, $tt_id);
        $wpdb->insert($wpdb->term_relationships, array('object_id' => $object_id, 'term_taxonomy_id' => $tt_id));
        /**
         * Fires immediately after an object-term relationship is added.
         *
         * @since 2.9.0
         *
         * @param int $object_id Object ID.
         * @param int $tt_id     Term taxonomy ID.
         */
        do_action('added_term_relationship', $object_id, $tt_id);
        $new_tt_ids[] = $tt_id;
    }
    if ($new_tt_ids) {
        wp_update_term_count($new_tt_ids, $taxonomy);
    }
    if (!$append) {
        $delete_tt_ids = array_diff($old_tt_ids, $tt_ids);
        if ($delete_tt_ids) {
            $in_delete_tt_ids = "'" . implode("', '", $delete_tt_ids) . "'";
            $delete_term_ids = $wpdb->get_col($wpdb->prepare("SELECT tt.term_id FROM {$wpdb->term_taxonomy} AS tt WHERE tt.taxonomy = %s AND tt.term_taxonomy_id IN ({$in_delete_tt_ids})", $taxonomy));
            $delete_term_ids = array_map('intval', $delete_term_ids);
            $remove = wp_remove_object_terms($object_id, $delete_term_ids, $taxonomy);
            if (is_wp_error($remove)) {
                return $remove;
            }
        }
    }
    $t = get_taxonomy($taxonomy);
    if (!$append && isset($t->sort) && $t->sort) {
        $values = array();
        $term_order = 0;
        $final_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids'));
        foreach ($tt_ids as $tt_id) {
            if (in_array($tt_id, $final_tt_ids)) {
                $values[] = $wpdb->prepare("(%d, %d, %d)", $object_id, $tt_id, ++$term_order);
            }
        }
        if ($values) {
            if (false === $wpdb->query("INSERT INTO {$wpdb->term_relationships} (object_id, term_taxonomy_id, term_order) VALUES " . join(',', $values) . " ON DUPLICATE KEY UPDATE term_order = VALUES(term_order)")) {
                return new WP_Error('db_insert_error', __('Could not insert term relationship into the database'), $wpdb->last_error);
            }
        }
    }
    wp_cache_delete($object_id, $taxonomy . '_relationships');
    /**
     * Fires after an object's terms have been set.
     *
     * @since 2.8.0
     *
     * @param int    $object_id  Object ID.
     * @param array  $terms      An array of object terms.
     * @param array  $tt_ids     An array of term taxonomy IDs.
     * @param string $taxonomy   Taxonomy slug.
     * @param bool   $append     Whether to append new terms to the old terms.
     * @param array  $old_tt_ids Old array of term taxonomy IDs.
     */
    do_action('set_object_terms', $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids);
    return $tt_ids;
}

WordPress Version: 3.7

/**
 * Create Term and Taxonomy Relationships.
 *
 * Relates an object (post, link etc) to a term and taxonomy type. Creates the
 * term and taxonomy relationship if it doesn't already exist. Creates a term if
 * it doesn't exist (using the slug).
 *
 * A relationship means that the term is grouped in or belongs to the taxonomy.
 * A term has no meaning until it is given context by defining which taxonomy it
 * exists under.
 *
 * @package WordPress
 * @subpackage Taxonomy
 * @since 2.3.0
 * @uses wp_remove_object_terms()
 *
 * @param int $object_id The object to relate to.
 * @param array|int|string $terms The slug or id of the term, will replace all existing
 * related terms in this taxonomy.
 * @param array|string $taxonomy The context in which to relate the term to the object.
 * @param bool $append If false will delete difference of terms.
 * @return array|WP_Error Affected Term IDs
 */
function wp_set_object_terms($object_id, $terms, $taxonomy, $append = false)
{
    global $wpdb;
    $object_id = (int) $object_id;
    if (!taxonomy_exists($taxonomy)) {
        return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
    }
    if (!is_array($terms)) {
        $terms = array($terms);
    }
    if (!$append) {
        $old_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'orderby' => 'none'));
    } else {
        $old_tt_ids = array();
    }
    $tt_ids = array();
    $term_ids = array();
    $new_tt_ids = array();
    foreach ((array) $terms as $term) {
        if (!strlen(trim($term))) {
            continue;
        }
        if (!$term_info = term_exists($term, $taxonomy)) {
            // Skip if a non-existent term ID is passed.
            if (is_int($term)) {
                continue;
            }
            $term_info = wp_insert_term($term, $taxonomy);
        }
        if (is_wp_error($term_info)) {
            return $term_info;
        }
        $term_ids[] = $term_info['term_id'];
        $tt_id = $term_info['term_taxonomy_id'];
        $tt_ids[] = $tt_id;
        if ($wpdb->get_var($wpdb->prepare("SELECT term_taxonomy_id FROM {$wpdb->term_relationships} WHERE object_id = %d AND term_taxonomy_id = %d", $object_id, $tt_id))) {
            continue;
        }
        do_action('add_term_relationship', $object_id, $tt_id);
        $wpdb->insert($wpdb->term_relationships, array('object_id' => $object_id, 'term_taxonomy_id' => $tt_id));
        do_action('added_term_relationship', $object_id, $tt_id);
        $new_tt_ids[] = $tt_id;
    }
    if ($new_tt_ids) {
        wp_update_term_count($new_tt_ids, $taxonomy);
    }
    if (!$append) {
        $delete_tt_ids = array_diff($old_tt_ids, $tt_ids);
        if ($delete_tt_ids) {
            $in_delete_tt_ids = "'" . implode("', '", $delete_tt_ids) . "'";
            $delete_term_ids = $wpdb->get_col($wpdb->prepare("SELECT tt.term_id FROM {$wpdb->term_taxonomy} AS tt WHERE tt.taxonomy = %s AND tt.term_taxonomy_id IN ({$in_delete_tt_ids})", $taxonomy));
            $delete_term_ids = array_map('intval', $delete_term_ids);
            $remove = wp_remove_object_terms($object_id, $delete_term_ids, $taxonomy);
            if (is_wp_error($remove)) {
                return $remove;
            }
        }
    }
    $t = get_taxonomy($taxonomy);
    if (!$append && isset($t->sort) && $t->sort) {
        $values = array();
        $term_order = 0;
        $final_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids'));
        foreach ($tt_ids as $tt_id) {
            if (in_array($tt_id, $final_tt_ids)) {
                $values[] = $wpdb->prepare("(%d, %d, %d)", $object_id, $tt_id, ++$term_order);
            }
        }
        if ($values) {
            if (false === $wpdb->query("INSERT INTO {$wpdb->term_relationships} (object_id, term_taxonomy_id, term_order) VALUES " . join(',', $values) . " ON DUPLICATE KEY UPDATE term_order = VALUES(term_order)")) {
                return new WP_Error('db_insert_error', __('Could not insert term relationship into the database'), $wpdb->last_error);
            }
        }
    }
    wp_cache_delete($object_id, $taxonomy . '_relationships');
    do_action('set_object_terms', $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids);
    return $tt_ids;
}