wp_get_object_terms

The timeline below displays how wordpress function wp_get_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

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 * @since 4.4.0 Introduced `$meta_query` and `$update_term_meta_cache` arguments. When `$fields` is 'all' or
 *              'all_with_object_id', an array of `WP_Term` objects will be returned.
 * @since 4.7.0 Refactored to use WP_Term_Query, and to support any WP_Term_Query arguments.
 * @since 6.3.0 Passing `update_term_meta_cache` argument value false by default resulting in get_terms() to not
 *              prime the term meta cache.
 *
 * @param int|int[]       $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|string[] $taxonomies The taxonomy names to retrieve terms from.
 * @param array|string    $args       See WP_Term_Query::__construct() for supported arguments.
 * @return WP_Term[]|int[]|string[]|string|WP_Error Array of terms, a count thereof as a numeric string,
 *                                                  or WP_Error if any of the taxonomies do not exist.
 *                                                  See WP_Term_Query::get_terms() for more information.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy.'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('update_term_meta_cache' => false);
    $args = wp_parse_args($args, $defaults);
    /**
     * Filters arguments for retrieving object terms.
     *
     * @since 4.9.0
     *
     * @param array    $args       An array of arguments for retrieving terms for the given object(s).
     *                             See {@see wp_get_object_terms()} for details.
     * @param int[]    $object_ids Array of object IDs.
     * @param string[] $taxonomies Array of taxonomy names to retrieve terms from.
     */
    $args = apply_filters('wp_get_object_terms_args', $args, $object_ids, $taxonomies);
    /*
     * When one or more queried taxonomies is registered with an 'args' array,
     * those params override the `$args` passed to this function.
     */
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && array_merge($args, $t->args) != $args) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $args['taxonomy'] = $taxonomies;
    $args['object_ids'] = $object_ids;
    // Taxonomies registered without an 'args' param are handled here.
    if (!empty($taxonomies)) {
        $terms_from_remaining_taxonomies = get_terms($args);
        // Array keys should be preserved for values of $fields that use term_id for keys.
        if (!empty($args['fields']) && str_starts_with($args['fields'], 'id=>')) {
            $terms = $terms + $terms_from_remaining_taxonomies;
        } else {
            $terms = array_merge($terms, $terms_from_remaining_taxonomies);
        }
    }
    /**
     * Filters the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param WP_Term[]|int[]|string[]|string $terms      Array of terms or a count thereof as a numeric string.
     * @param int[]                           $object_ids Array of object IDs for which terms were retrieved.
     * @param string[]                        $taxonomies Array of taxonomy names from which terms were retrieved.
     * @param array                           $args       Array of arguments for retrieving terms for the given
     *                                                    object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_ids, $taxonomies, $args);
    $object_ids = implode(',', $object_ids);
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    /**
     * Filters the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param WP_Term[]|int[]|string[]|string $terms      Array of terms or a count thereof as a numeric string.
     * @param string                          $object_ids Comma separated list of object IDs for which terms were retrieved.
     * @param string                          $taxonomies SQL fragment of taxonomy names from which terms were retrieved.
     * @param array                           $args       Array of arguments for retrieving terms for the given
     *                                                    object(s). See wp_get_object_terms() for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 6.1

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 * @since 4.4.0 Introduced `$meta_query` and `$update_term_meta_cache` arguments. When `$fields` is 'all' or
 *              'all_with_object_id', an array of `WP_Term` objects will be returned.
 * @since 4.7.0 Refactored to use WP_Term_Query, and to support any WP_Term_Query arguments.
 *
 * @param int|int[]       $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|string[] $taxonomies The taxonomy names to retrieve terms from.
 * @param array|string    $args       See WP_Term_Query::__construct() for supported arguments.
 * @return WP_Term[]|int[]|string[]|string|WP_Error Array of terms, a count thereof as a numeric string,
 *                                                  or WP_Error if any of the taxonomies do not exist.
 *                                                  See WP_Term_Query::get_terms() for more information.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy.'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $args = wp_parse_args($args);
    /**
     * Filters arguments for retrieving object terms.
     *
     * @since 4.9.0
     *
     * @param array    $args       An array of arguments for retrieving terms for the given object(s).
     *                             See {@see wp_get_object_terms()} for details.
     * @param int[]    $object_ids Array of object IDs.
     * @param string[] $taxonomies Array of taxonomy names to retrieve terms from.
     */
    $args = apply_filters('wp_get_object_terms_args', $args, $object_ids, $taxonomies);
    /*
     * When one or more queried taxonomies is registered with an 'args' array,
     * those params override the `$args` passed to this function.
     */
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && array_merge($args, $t->args) != $args) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $args['taxonomy'] = $taxonomies;
    $args['object_ids'] = $object_ids;
    // Taxonomies registered without an 'args' param are handled here.
    if (!empty($taxonomies)) {
        $terms_from_remaining_taxonomies = get_terms($args);
        // Array keys should be preserved for values of $fields that use term_id for keys.
        if (!empty($args['fields']) && 0 === strpos($args['fields'], 'id=>')) {
            $terms = $terms + $terms_from_remaining_taxonomies;
        } else {
            $terms = array_merge($terms, $terms_from_remaining_taxonomies);
        }
    }
    /**
     * Filters the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param WP_Term[]|int[]|string[]|string $terms      Array of terms or a count thereof as a numeric string.
     * @param int[]                           $object_ids Array of object IDs for which terms were retrieved.
     * @param string[]                        $taxonomies Array of taxonomy names from which terms were retrieved.
     * @param array                           $args       Array of arguments for retrieving terms for the given
     *                                                    object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_ids, $taxonomies, $args);
    $object_ids = implode(',', $object_ids);
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    /**
     * Filters the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param WP_Term[]|int[]|string[]|string $terms      Array of terms or a count thereof as a numeric string.
     * @param string                          $object_ids Comma separated list of object IDs for which terms were retrieved.
     * @param string                          $taxonomies SQL fragment of taxonomy names from which terms were retrieved.
     * @param array                           $args       Array of arguments for retrieving terms for the given
     *                                                    object(s). See wp_get_object_terms() for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 5.6

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 * @since 4.4.0 Introduced `$meta_query` and `$update_term_meta_cache` arguments. When `$fields` is 'all' or
 *              'all_with_object_id', an array of `WP_Term` objects will be returned.
 * @since 4.7.0 Refactored to use WP_Term_Query, and to support any WP_Term_Query arguments.
 *
 * @param int|int[]       $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|string[] $taxonomies The taxonomy names to retrieve terms from.
 * @param array|string    $args       See WP_Term_Query::__construct() for supported arguments.
 * @return WP_Term[]|WP_Error Array of terms or empty array if no terms found.
 *                            WP_Error if any of the taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy.'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $args = wp_parse_args($args);
    /**
     * Filters arguments for retrieving object terms.
     *
     * @since 4.9.0
     *
     * @param array    $args       An array of arguments for retrieving terms for the given object(s).
     *                             See {@see wp_get_object_terms()} for details.
     * @param int[]    $object_ids Array of object IDs.
     * @param string[] $taxonomies Array of taxonomy names to retrieve terms from.
     */
    $args = apply_filters('wp_get_object_terms_args', $args, $object_ids, $taxonomies);
    /*
     * When one or more queried taxonomies is registered with an 'args' array,
     * those params override the `$args` passed to this function.
     */
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && array_merge($args, $t->args) != $args) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $args['taxonomy'] = $taxonomies;
    $args['object_ids'] = $object_ids;
    // Taxonomies registered without an 'args' param are handled here.
    if (!empty($taxonomies)) {
        $terms_from_remaining_taxonomies = get_terms($args);
        // Array keys should be preserved for values of $fields that use term_id for keys.
        if (!empty($args['fields']) && 0 === strpos($args['fields'], 'id=>')) {
            $terms = $terms + $terms_from_remaining_taxonomies;
        } else {
            $terms = array_merge($terms, $terms_from_remaining_taxonomies);
        }
    }
    /**
     * Filters the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param WP_Term[] $terms      Array of terms for the given object or objects.
     * @param int[]     $object_ids Array of object IDs for which terms were retrieved.
     * @param string[]  $taxonomies Array of taxonomy names from which terms were retrieved.
     * @param array     $args       Array of arguments for retrieving terms for the given
     *                              object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_ids, $taxonomies, $args);
    $object_ids = implode(',', $object_ids);
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    /**
     * Filters the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param WP_Term[] $terms      Array of terms for the given object or objects.
     * @param string    $object_ids Comma separated list of object IDs for which terms were retrieved.
     * @param string    $taxonomies SQL fragment of taxonomy names from which terms were retrieved.
     * @param array     $args       Array of arguments for retrieving terms for the given
     *                              object(s). See wp_get_object_terms() for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 5.4

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 * @since 4.4.0 Introduced `$meta_query` and `$update_term_meta_cache` arguments. When `$fields` is 'all' or
 *              'all_with_object_id', an array of `WP_Term` objects will be returned.
 * @since 4.7.0 Refactored to use WP_Term_Query, and to support any WP_Term_Query arguments.
 *
 * @param int|int[]       $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|string[] $taxonomies The taxonomy names to retrieve terms from.
 * @param array|string    $args       See WP_Term_Query::__construct() for supported arguments.
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy.'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $args = wp_parse_args($args);
    /**
     * Filter arguments for retrieving object terms.
     *
     * @since 4.9.0
     *
     * @param array    $args       An array of arguments for retrieving terms for the given object(s).
     *                             See {@see wp_get_object_terms()} for details.
     * @param int[]    $object_ids Array of object IDs.
     * @param string[] $taxonomies Array of taxonomy names to retrieve terms from.
     */
    $args = apply_filters('wp_get_object_terms_args', $args, $object_ids, $taxonomies);
    /*
     * When one or more queried taxonomies is registered with an 'args' array,
     * those params override the `$args` passed to this function.
     */
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && array_merge($args, $t->args) != $args) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $args['taxonomy'] = $taxonomies;
    $args['object_ids'] = $object_ids;
    // Taxonomies registered without an 'args' param are handled here.
    if (!empty($taxonomies)) {
        $terms_from_remaining_taxonomies = get_terms($args);
        // Array keys should be preserved for values of $fields that use term_id for keys.
        if (!empty($args['fields']) && 0 === strpos($args['fields'], 'id=>')) {
            $terms = $terms + $terms_from_remaining_taxonomies;
        } else {
            $terms = array_merge($terms, $terms_from_remaining_taxonomies);
        }
    }
    /**
     * Filters the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array    $terms      Array of terms for the given object or objects.
     * @param int[]    $object_ids Array of object IDs for which terms were retrieved.
     * @param string[] $taxonomies Array of taxonomy names from which terms were retrieved.
     * @param array    $args       Array of arguments for retrieving terms for the given
     *                             object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_ids, $taxonomies, $args);
    $object_ids = implode(',', $object_ids);
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    /**
     * Filters the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array    $terms      Array of terms for the given object or objects.
     * @param int[]    $object_ids Array of object IDs for which terms were retrieved.
     * @param string[] $taxonomies Array of taxonomy names from which terms were retrieved.
     * @param array    $args       Array of arguments for retrieving terms for the given
     *                             object(s). See wp_get_object_terms() for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 5.3

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 * @since 4.4.0 Introduced `$meta_query` and `$update_term_meta_cache` arguments. When `$fields` is 'all' or
 *              'all_with_object_id', an array of `WP_Term` objects will be returned.
 * @since 4.7.0 Refactored to use WP_Term_Query, and to support any WP_Term_Query arguments.
 *
 * @param int|int[]       $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|string[] $taxonomies The taxonomy names to retrieve terms from.
 * @param array|string    $args       See WP_Term_Query::__construct() for supported arguments.
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy.'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $args = wp_parse_args($args);
    /**
     * Filter arguments for retrieving object terms.
     *
     * @since 4.9.0
     *
     * @param array    $args       An array of arguments for retrieving terms for the given object(s).
     *                             See {@see wp_get_object_terms()} for details.
     * @param int[]    $object_ids Array of object IDs.
     * @param string[] $taxonomies Array of taxonomy names to retrieve terms from.
     */
    $args = apply_filters('wp_get_object_terms_args', $args, $object_ids, $taxonomies);
    /*
     * When one or more queried taxonomies is registered with an 'args' array,
     * those params override the `$args` passed to this function.
     */
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $args['taxonomy'] = $taxonomies;
    $args['object_ids'] = $object_ids;
    // Taxonomies registered without an 'args' param are handled here.
    if (!empty($taxonomies)) {
        $terms_from_remaining_taxonomies = get_terms($args);
        // Array keys should be preserved for values of $fields that use term_id for keys.
        if (!empty($args['fields']) && 0 === strpos($args['fields'], 'id=>')) {
            $terms = $terms + $terms_from_remaining_taxonomies;
        } else {
            $terms = array_merge($terms, $terms_from_remaining_taxonomies);
        }
    }
    /**
     * Filters the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array    $terms      Array of terms for the given object or objects.
     * @param int[]    $object_ids Array of object IDs for which terms were retrieved.
     * @param string[] $taxonomies Array of taxonomy names from which terms were retrieved.
     * @param array    $args       Array of arguments for retrieving terms for the given
     *                             object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_ids, $taxonomies, $args);
    $object_ids = implode(',', $object_ids);
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    /**
     * Filters the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array    $terms      Array of terms for the given object or objects.
     * @param int[]    $object_ids Array of object IDs for which terms were retrieved.
     * @param string[] $taxonomies Array of taxonomy names from which terms were retrieved.
     * @param array    $args       Array of arguments for retrieving terms for the given
     *                             object(s). See wp_get_object_terms() for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 4.9

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 * @since 4.4.0 Introduced `$meta_query` and `$update_term_meta_cache` arguments. When `$fields` is 'all' or
 *              'all_with_object_id', an array of `WP_Term` objects will be returned.
 * @since 4.7.0 Refactored to use WP_Term_Query, and to support any WP_Term_Query arguments.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args       See WP_Term_Query::__construct() for supported arguments.
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy.'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $args = wp_parse_args($args);
    /**
     * Filter arguments for retrieving object terms.
     *
     * @since 4.9.0
     *
     * @param array        $args       An array of arguments for retrieving terms for the given object(s).
     *                                 See {@see wp_get_object_terms()} for details.
     * @param int|array    $object_ids Object ID or array of IDs.
     * @param string|array $taxonomies The taxonomies to retrieve terms from.
     */
    $args = apply_filters('wp_get_object_terms_args', $args, $object_ids, $taxonomies);
    /*
     * When one or more queried taxonomies is registered with an 'args' array,
     * those params override the `$args` passed to this function.
     */
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $args['taxonomy'] = $taxonomies;
    $args['object_ids'] = $object_ids;
    // Taxonomies registered without an 'args' param are handled here.
    if (!empty($taxonomies)) {
        $terms_from_remaining_taxonomies = get_terms($args);
        // Array keys should be preserved for values of $fields that use term_id for keys.
        if (!empty($args['fields']) && 0 === strpos($args['fields'], 'id=>')) {
            $terms = $terms + $terms_from_remaining_taxonomies;
        } else {
            $terms = array_merge($terms, $terms_from_remaining_taxonomies);
        }
    }
    /**
     * Filters the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms      An array of terms for the given object or objects.
     * @param array $object_ids Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomies Array of taxonomies from which `$terms` were retrieved.
     * @param array $args       An array of arguments for retrieving terms for the given
     *                          object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_ids, $taxonomies, $args);
    $object_ids = implode(',', $object_ids);
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    /**
     * Filters the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See wp_get_object_terms() for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 8.1

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 * @since 4.4.0 Introduced `$meta_query` and `$update_term_meta_cache` arguments. When `$fields` is 'all' or
 *              'all_with_object_id', an array of `WP_Term` objects will be returned.
 * @since 4.7.0 Refactored to use WP_Term_Query, and to support any WP_Term_Query arguments.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args       See WP_Term_Query::__construct() for supported arguments.
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy.'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $args = wp_parse_args($args);
    /*
     * When one or more queried taxonomies is registered with an 'args' array,
     * those params override the `$args` passed to this function.
     */
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $args['taxonomy'] = $taxonomies;
    $args['object_ids'] = $object_ids;
    // Taxonomies registered without an 'args' param are handled here.
    if (!empty($taxonomies)) {
        $terms = array_merge($terms, get_terms($args));
    }
    /**
     * Filters the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms      An array of terms for the given object or objects.
     * @param array $object_ids Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomies Array of taxonomies from which `$terms` were retrieved.
     * @param array $args       An array of arguments for retrieving terms for the given
     *                          object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_ids, $taxonomies, $args);
    $object_ids = implode(',', $object_ids);
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    /**
     * Filters the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See wp_get_object_terms() for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 4.8

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 * @since 4.4.0 Introduced `$meta_query` and `$update_term_meta_cache` arguments. When `$fields` is 'all' or
 *              'all_with_object_id', an array of `WP_Term` objects will be returned.
 * @since 4.7.0 Refactored to use WP_Term_Query, and to support any WP_Term_Query arguments.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args       See WP_Term_Query::__construct() for supported arguments.
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy.'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $args = wp_parse_args($args);
    /*
     * When one or more queried taxonomies is registered with an 'args' array,
     * those params override the `$args` passed to this function.
     */
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $args['taxonomy'] = $taxonomies;
    $args['object_ids'] = $object_ids;
    $terms = array_merge($terms, get_terms($args));
    /**
     * Filters the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms      An array of terms for the given object or objects.
     * @param array $object_ids Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomies Array of taxonomies from which `$terms` were retrieved.
     * @param array $args       An array of arguments for retrieving terms for the given
     *                          object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_ids, $taxonomies, $args);
    $object_ids = implode(',', $object_ids);
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    /**
     * Filters the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See wp_get_object_terms() for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 7.1

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 * @since 4.4.0 Introduced `$meta_query` and `$update_term_meta_cache` arguments. When `$fields` is 'all' or
 *              'all_with_object_id', an array of `WP_Term` objects will be returned.
 * @since 4.7.0 Refactored to use WP_Term_Query, and to support any WP_Term_Query arguments.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args       See WP_Term_Query::__construct() for supported arguments.
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy.'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $args = wp_parse_args($args);
    $args['taxonomy'] = $taxonomies;
    $args['object_ids'] = $object_ids;
    $terms = get_terms($args);
    /**
     * Filters the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms      An array of terms for the given object or objects.
     * @param array $object_ids Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomies Array of taxonomies from which `$terms` were retrieved.
     * @param array $args       An array of arguments for retrieving terms for the given
     *                          object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_ids, $taxonomies, $args);
    $object_ids = implode(',', $object_ids);
    $taxonomies = implode(',', $taxonomies);
    /**
     * Filters the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See wp_get_object_terms() for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 4.7

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 * @since 4.4.0 Introduced `$meta_query` and `$update_term_meta_cache` arguments. When `$fields` is 'all' or
 *              'all_with_object_id', an array of `WP_Term` objects will be returned.
 * @since 4.7.0 Refactored to use WP_Term_Query, and to support any WP_Term_Query arguments.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args       See WP_Term_Query::__construct() for supported arguments.
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy.'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $args['taxonomy'] = $taxonomies;
    $args['object_ids'] = $object_ids;
    $terms = get_terms($args);
    /**
     * Filters the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms      An array of terms for the given object or objects.
     * @param array $object_ids Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomies Array of taxonomies from which `$terms` were retrieved.
     * @param array $args       An array of arguments for retrieving terms for the given
     *                          object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_ids, $taxonomies, $args);
    $object_ids = implode(',', $object_ids);
    $taxonomies = implode(',', $taxonomies);
    /**
     * Filters the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See wp_get_object_terms() for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 4.6

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 * @since 4.4.0 Introduced `$meta_query` and `$update_term_meta_cache` arguments. When `$fields` is 'all' or
 *              'all_with_object_id', an array of `WP_Term` objects will be returned.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args {
 *     Array of arguments.
 *     @type string $orderby                Field by which results should be sorted. Accepts 'name', 'count', 'slug',
 *                                          'term_group', 'term_order', 'taxonomy', 'parent', or 'term_taxonomy_id'.
 *                                          Default 'name'.
 *     @type string $order                  Sort order. Accepts 'ASC' or 'DESC'. Default 'ASC'.
 *     @type string $fields                 Fields to return for matched terms. Accepts 'all', 'ids', 'names', and
 *                                          'all_with_object_id'. Note that 'all' or 'all_with_object_id' will result
 *                                          in an array of term objects being returned, 'ids' will return an array of
 *                                          integers, and 'names' an array of strings.
 *     @type int    $parent                 Optional. Limit results to the direct children of a given term ID.
 *     @type bool   $update_term_meta_cache Whether to prime termmeta cache for matched terms. Only applies when
 *                                          `$fields` is 'all', 'all_with_object_id', or 'term_id'. Default true.
 *     @type array  $meta_query             Meta query clauses to limit retrieved terms by. See `WP_Meta_Query`.
 *                                          Default empty.
 * }
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy.'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'parent' => '', 'update_term_meta_cache' => true, 'meta_query' => '');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if (in_array($orderby, array('term_id', 'name', 'slug', 'term_group'))) {
        $orderby = "t.{$orderby}";
    } elseif (in_array($orderby, array('count', 'parent', 'taxonomy', 'term_taxonomy_id'))) {
        $orderby = "tt.{$orderby}";
    } elseif ('term_order' === $orderby) {
        $orderby = 'tr.term_order';
    } elseif ('none' === $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomy_array = $taxonomies;
    $object_id_array = $object_ids;
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } elseif ('ids' == $fields) {
        $select_this = 't.term_id';
    } elseif ('names' == $fields) {
        $select_this = 't.name';
    } elseif ('slugs' == $fields) {
        $select_this = 't.slug';
    } elseif ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $where = array("tt.taxonomy IN ({$taxonomies})", "tr.object_id IN ({$object_ids})");
    if ('' !== $args['parent']) {
        $where[] = $wpdb->prepare('tt.parent = %d', $args['parent']);
    }
    // Meta query support.
    $meta_query_join = '';
    if (!empty($args['meta_query'])) {
        $mquery = new WP_Meta_Query($args['meta_query']);
        $mq_sql = $mquery->get_sql('term', 't', 'term_id');
        $meta_query_join .= $mq_sql['join'];
        // Strip leading AND.
        $where[] = preg_replace('/^\s*AND/', '', $mq_sql['where']);
    }
    $where = implode(' AND ', $where);
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id {$meta_query_join} WHERE {$where} {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        $object_id_index = array();
        foreach ($_terms as $key => $term) {
            $term = sanitize_term($term, $taxonomy, 'raw');
            $_terms[$key] = $term;
            if (isset($term->object_id)) {
                $object_id_index[$key] = $term->object_id;
            }
        }
        update_term_cache($_terms);
        $_terms = array_map('get_term', $_terms);
        // Re-add the object_id data, which is lost when fetching terms from cache.
        if ('all_with_object_id' === $fields) {
            foreach ($_terms as $key => $_term) {
                if (isset($object_id_index[$key])) {
                    $_term->object_id = $object_id_index[$key];
                }
            }
        }
        $terms = array_merge($terms, $_terms);
        $objects = true;
    } elseif ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } elseif ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    // Update termmeta cache, if necessary.
    if ($args['update_term_meta_cache'] && ('all' === $fields || 'all_with_object_id' === $fields || 'ids' === $fields)) {
        if ('ids' === $fields) {
            $term_ids = $terms;
        } else {
            $term_ids = wp_list_pluck($terms, 'term_id');
        }
        update_termmeta_cache($term_ids);
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filters the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms           An array of terms for the given object or objects.
     * @param array $object_id_array Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomy_array  Array of taxonomies from which `$terms` were retrieved.
     * @param array $args            An array of arguments for retrieving terms for the given
     *                               object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_id_array, $taxonomy_array, $args);
    /**
     * Filters the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See wp_get_object_terms() for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .20

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 * @since 4.4.0 Introduced `$meta_query` and `$update_term_meta_cache` arguments. When `$fields` is 'all' or
 *              'all_with_object_id', an array of `WP_Term` objects will be returned.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args {
 *     Array of arguments.
 *     @type string $orderby                Field by which results should be sorted. Accepts 'name', 'count', 'slug',
 *                                          'term_group', 'term_order', 'taxonomy', 'parent', or 'term_taxonomy_id'.
 *                                          Default 'name'.
 *     @type string $order                  Sort order. Accepts 'ASC' or 'DESC'. Default 'ASC'.
 *     @type string $fields                 Fields to return for matched terms. Accepts 'all', 'ids', 'names', and
 *                                          'all_with_object_id'. Note that 'all' or 'all_with_object_id' will result
 *                                          in an array of term objects being returned, 'ids' will return an array of
 *                                          integers, and 'names' an array of strings.
 *     @type int    $parent                 Optional. Limit results to the direct children of a given term ID.
 *     @type bool   $update_term_meta_cache Whether to prime termmeta cache for matched terms. Only applies when
 *                                          `$fields` is 'all', 'all_with_object_id', or 'term_id'. Default true.
 *     @type array  $meta_query             Meta query clauses to limit retrieved terms by. See `WP_Meta_Query`.
 *                                          Default empty.
 * }
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'parent' => '', 'update_term_meta_cache' => true, 'meta_query' => '');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if (in_array($orderby, array('term_id', 'name', 'slug', 'term_group'))) {
        $orderby = "t.{$orderby}";
    } elseif (in_array($orderby, array('count', 'parent', 'taxonomy', 'term_taxonomy_id'))) {
        $orderby = "tt.{$orderby}";
    } elseif ('term_order' === $orderby) {
        $orderby = 'tr.term_order';
    } elseif ('none' === $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomy_array = $taxonomies;
    $object_id_array = $object_ids;
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } elseif ('ids' == $fields) {
        $select_this = 't.term_id';
    } elseif ('names' == $fields) {
        $select_this = 't.name';
    } elseif ('slugs' == $fields) {
        $select_this = 't.slug';
    } elseif ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $where = array("tt.taxonomy IN ({$taxonomies})", "tr.object_id IN ({$object_ids})");
    if ('' !== $args['parent']) {
        $where[] = $wpdb->prepare('tt.parent = %d', $args['parent']);
    }
    // Meta query support.
    $meta_query_join = '';
    if (!empty($args['meta_query'])) {
        $mquery = new WP_Meta_Query($args['meta_query']);
        $mq_sql = $mquery->get_sql('term', 't', 'term_id');
        $meta_query_join .= $mq_sql['join'];
        // Strip leading AND.
        $where[] = preg_replace('/^\s*AND/', '', $mq_sql['where']);
    }
    $where = implode(' AND ', $where);
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id {$meta_query_join} WHERE {$where} {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        $object_id_index = array();
        foreach ($_terms as $key => $term) {
            $term = sanitize_term($term, $taxonomy, 'raw');
            $_terms[$key] = $term;
            if (isset($term->object_id)) {
                $object_id_index[$key] = $term->object_id;
            }
        }
        update_term_cache($_terms);
        $_terms = array_map('get_term', $_terms);
        // Re-add the object_id data, which is lost when fetching terms from cache.
        if ('all_with_object_id' === $fields) {
            foreach ($_terms as $key => $_term) {
                if (isset($object_id_index[$key])) {
                    $_term->object_id = $object_id_index[$key];
                }
            }
        }
        $terms = array_merge($terms, $_terms);
        $objects = true;
    } elseif ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } elseif ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    // Update termmeta cache, if necessary.
    if ($args['update_term_meta_cache'] && ('all' === $fields || 'all_with_object_ids' === $fields || 'term_id' === $fields)) {
        if ('term_id' === $fields) {
            $term_ids = $fields;
        } else {
            $term_ids = wp_list_pluck($terms, 'term_id');
        }
        update_termmeta_cache($term_ids);
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms           An array of terms for the given object or objects.
     * @param array $object_id_array Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomy_array  Array of taxonomies from which `$terms` were retrieved.
     * @param array $args            An array of arguments for retrieving terms for the given
     *                               object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_id_array, $taxonomy_array, $args);
    /**
     * Filter the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See {@see wp_get_object_terms()} for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 4.2

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 * @since 4.4.0 Introduced `$meta_query` and `$update_term_meta_cache` arguments. When `$fields` is 'all' or
 *              'all_with_object_id', an array of `WP_Term` objects will be returned.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args {
 *     Array of arguments.
 *     @type string $orderby                Field by which results should be sorted. Accepts 'name', 'count', 'slug',
 *                                          'term_group', 'term_order', 'taxonomy', 'parent', or 'term_taxonomy_id'.
 *                                          Default 'name'.
 *     @type string $order                  Sort order. Accepts 'ASC' or 'DESC'. Default 'ASC'.
 *     @type string $fields                 Fields to return for matched terms. Accepts 'all', 'ids', 'names', and
 *                                          'all_with_object_id'. Note that 'all' or 'all_with_object_id' will result
 *                                          in an array of term objects being returned, 'ids' will return an array of
 *                                          integers, and 'names' an array of strings.
 *     @type int    $parent                 Optional. Limit results to the direct children of a given term ID.
 *     @type bool   $update_term_meta_cache Whether to prime termmeta cache for matched terms. Only applies when
 *                                          `$fields` is 'all', 'all_with_object_id', or 'term_id'. Default true.
 *     @type array  $meta_query             Meta query clauses to limit retrieved terms by. See `WP_Meta_Query`.
 *                                          Default empty.
 * }
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'parent' => '', 'update_term_meta_cache' => true, 'meta_query' => '');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if (in_array($orderby, array('term_id', 'name', 'slug', 'term_group'))) {
        $orderby = "t.{$orderby}";
    } elseif (in_array($orderby, array('count', 'parent', 'taxonomy', 'term_taxonomy_id'))) {
        $orderby = "tt.{$orderby}";
    } elseif ('term_order' === $orderby) {
        $orderby = 'tr.term_order';
    } elseif ('none' === $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomy_array = $taxonomies;
    $object_id_array = $object_ids;
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } elseif ('ids' == $fields) {
        $select_this = 't.term_id';
    } elseif ('names' == $fields) {
        $select_this = 't.name';
    } elseif ('slugs' == $fields) {
        $select_this = 't.slug';
    } elseif ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $where = array("tt.taxonomy IN ({$taxonomies})", "tr.object_id IN ({$object_ids})");
    if ('' !== $args['parent']) {
        $where[] = $wpdb->prepare('tt.parent = %d', $args['parent']);
    }
    // Meta query support.
    $meta_query_join = '';
    if (!empty($args['meta_query'])) {
        $mquery = new WP_Meta_Query($args['meta_query']);
        $mq_sql = $mquery->get_sql('term', 't', 'term_id');
        $meta_query_join .= $mq_sql['join'];
        // Strip leading AND.
        $where[] = preg_replace('/^\s*AND/', '', $mq_sql['where']);
    }
    $where = implode(' AND ', $where);
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id {$meta_query_join} WHERE {$where} {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        $object_id_index = array();
        foreach ($_terms as $key => $term) {
            $term = sanitize_term($term, $taxonomy, 'raw');
            $_terms[$key] = $term;
            if (isset($term->object_id)) {
                $object_id_index[$key] = $term->object_id;
            }
        }
        update_term_cache($_terms);
        $_terms = array_map('get_term', $_terms);
        // Re-add the object_id data, which is lost when fetching terms from cache.
        if ('all_with_object_id' === $fields) {
            foreach ($_terms as $key => $_term) {
                if (isset($object_id_index[$key])) {
                    $_term->object_id = $object_id_index[$key];
                }
            }
        }
        $terms = array_merge($terms, $_terms);
        $objects = true;
    } elseif ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } elseif ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    // Update termmeta cache, if necessary.
    if ($args['update_term_meta_cache'] && ('all' === $fields || 'all_with_object_ids' === $fields || 'term_id' === $fields)) {
        if ('term_id' === $fields) {
            $term_ids = $fields;
        } else {
            $term_ids = wp_list_pluck($terms, 'term_id');
        }
        update_termmeta_cache($term_ids);
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms           An array of terms for the given object or objects.
     * @param array $object_id_array Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomy_array  Array of taxonomies from which `$terms` were retrieved.
     * @param array $args            An array of arguments for retrieving terms for the given
     *                               object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_id_array, $taxonomy_array, $args);
    /**
     * Filter the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See {@see wp_get_object_terms()} for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .10

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 * @since 4.4.0 Introduced `$meta_query` and `$update_term_meta_cache` arguments. When `$fields` is 'all' or
 *              'all_with_object_id', an array of `WP_Term` objects will be returned.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args {
 *     Array of arguments.
 *     @type string $orderby                Field by which results should be sorted. Accepts 'name', 'count', 'slug',
 *                                          'term_group', 'term_order', 'taxonomy', 'parent', or 'term_taxonomy_id'.
 *                                          Default 'name'.
 *     @type string $order                  Sort order. Accepts 'ASC' or 'DESC'. Default 'ASC'.
 *     @type string $fields                 Fields to return for matched terms. Accepts 'all', 'ids', 'names', and
 *                                          'all_with_object_id'. Note that 'all' or 'all_with_object_id' will result
 *                                          in an array of term objects being returned, 'ids' will return an array of
 *                                          integers, and 'names' an array of strings.
 *     @type int    $parent                 Optional. Limit results to the direct children of a given term ID.
 *     @type bool   $update_term_meta_cache Whether to prime termmeta cache for matched terms. Only applies when
 *                                          `$fields` is 'all', 'all_with_object_id', or 'term_id'. Default true.
 *     @type array  $meta_query             Meta query clauses to limit retrieved terms by. See `WP_Meta_Query`.
 *                                          Default empty.
 * }
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'parent' => '', 'update_term_meta_cache' => true, 'meta_query' => '');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if (in_array($orderby, array('term_id', 'name', 'slug', 'term_group'))) {
        $orderby = "t.{$orderby}";
    } elseif (in_array($orderby, array('count', 'parent', 'taxonomy', 'term_taxonomy_id'))) {
        $orderby = "tt.{$orderby}";
    } elseif ('term_order' === $orderby) {
        $orderby = 'tr.term_order';
    } elseif ('none' === $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomy_array = $taxonomies;
    $object_id_array = $object_ids;
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } elseif ('ids' == $fields) {
        $select_this = 't.term_id';
    } elseif ('names' == $fields) {
        $select_this = 't.name';
    } elseif ('slugs' == $fields) {
        $select_this = 't.slug';
    } elseif ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $where = array("tt.taxonomy IN ({$taxonomies})", "tr.object_id IN ({$object_ids})");
    if ('' !== $args['parent']) {
        $where[] = $wpdb->prepare('tt.parent = %d', $args['parent']);
    }
    // Meta query support.
    $meta_query_join = '';
    if (!empty($args['meta_query'])) {
        $mquery = new WP_Meta_Query($args['meta_query']);
        $mq_sql = $mquery->get_sql('term', 't', 'term_id');
        $meta_query_join .= $mq_sql['join'];
        // Strip leading AND.
        $where[] = preg_replace('/^\s*AND/', '', $mq_sql['where']);
    }
    $where = implode(' AND ', $where);
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id {$meta_query_join} WHERE {$where} {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        $object_id_index = array();
        foreach ($_terms as $key => $term) {
            $term = sanitize_term($term, $taxonomy, 'raw');
            $_terms[$key] = $term;
            if (isset($term->object_id)) {
                $object_id_index[$key] = $term->object_id;
            }
        }
        update_term_cache($_terms);
        $_terms = array_map('get_term', $_terms);
        // Re-add the object_id data, which is lost when fetching terms from cache.
        if ('all_with_object_id' === $fields) {
            foreach ($_terms as $key => $_term) {
                if (isset($object_id_index[$key])) {
                    $_term->object_id = $object_id_index[$key];
                }
            }
        }
        $terms = array_merge($terms, $_terms);
        $objects = true;
    } elseif ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } elseif ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    // Update termmeta cache, if necessary.
    if ($args['update_term_meta_cache'] && ('all' === $fields || 'all_with_object_ids' === $fields || 'term_id' === $fields)) {
        if ('term_id' === $fields) {
            $term_ids = $fields;
        } else {
            $term_ids = wp_list_pluck($terms, 'term_id');
        }
        update_termmeta_cache($term_ids);
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms           An array of terms for the given object or objects.
     * @param array $object_id_array Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomy_array  Array of taxonomies from which `$terms` were retrieved.
     * @param array $args            An array of arguments for retrieving terms for the given
     *                               object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_id_array, $taxonomy_array, $args);
    /**
     * Filter the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See {@see wp_get_object_terms()} for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 4.4

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 * @since 4.4.0 Introduced `$meta_query` and `$update_term_meta_cache` arguments. When `$fields` is 'all' or
 *              'all_with_object_id', an array of `WP_Term` objects will be returned.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args {
 *     Array of arguments.
 *     @type string $orderby                Field by which results should be sorted. Accepts 'name', 'count', 'slug',
 *                                          'term_group', 'term_order', 'taxonomy', 'parent', or 'term_taxonomy_id'.
 *                                          Default 'name'.
 *     @type string $order                  Sort order. Accepts 'ASC' or 'DESC'. Default 'ASC'.
 *     @type string $fields                 Fields to return for matched terms. Accepts 'all', 'ids', 'names', and
 *                                          'all_with_object_id'. Note that 'all' or 'all_with_object_id' will result
 *                                          in an array of term objects being returned, 'ids' will return an array of
 *                                          integers, and 'names' an array of strings.
 *     @type int    $parent                 Optional. Limit results to the direct children of a given term ID.
 *     @type bool   $update_term_meta_cache Whether to prime termmeta cache for matched terms. Only applies when
 *                                          `$fields` is 'all', 'all_with_object_id', or 'term_id'. Default true.
 *     @type array  $meta_query             Meta query clauses to limit retrieved terms by. See `WP_Meta_Query`.
 *                                          Default empty.
 * }
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'parent' => '', 'update_term_meta_cache' => true, 'meta_query' => '');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if (in_array($orderby, array('term_id', 'name', 'slug', 'term_group'))) {
        $orderby = "t.{$orderby}";
    } elseif (in_array($orderby, array('count', 'parent', 'taxonomy', 'term_taxonomy_id'))) {
        $orderby = "tt.{$orderby}";
    } elseif ('term_order' === $orderby) {
        $orderby = 'tr.term_order';
    } elseif ('none' === $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomy_array = $taxonomies;
    $object_id_array = $object_ids;
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } elseif ('ids' == $fields) {
        $select_this = 't.term_id';
    } elseif ('names' == $fields) {
        $select_this = 't.name';
    } elseif ('slugs' == $fields) {
        $select_this = 't.slug';
    } elseif ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $where = array("tt.taxonomy IN ({$taxonomies})", "tr.object_id IN ({$object_ids})");
    if ('' !== $args['parent']) {
        $where[] = $wpdb->prepare('tt.parent = %d', $args['parent']);
    }
    // Meta query support.
    $meta_query_join = '';
    if (!empty($args['meta_query'])) {
        $mquery = new WP_Meta_Query($args['meta_query']);
        $mq_sql = $mquery->get_sql('term', 't', 'term_id');
        $meta_query_join .= $mq_sql['join'];
        // Strip leading AND.
        $where[] = preg_replace('/^\s*AND/', '', $mq_sql['where']);
    }
    $where = implode(' AND ', $where);
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id {$meta_query_join} WHERE {$where} {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        $object_id_index = array();
        foreach ($_terms as $key => $term) {
            $term = sanitize_term($term, $taxonomy, 'raw');
            $_terms[$key] = $term;
            if (isset($term->object_id)) {
                $object_id_index[$key] = $term->object_id;
            }
        }
        update_term_cache($_terms);
        $_terms = array_map('get_term', $_terms);
        // Re-add the object_id data, which is lost when fetching terms from cache.
        if ('all_with_object_id' === $fields) {
            foreach ($_terms as $key => $_term) {
                if (isset($object_id_index[$key])) {
                    $_term->object_id = $object_id_index[$key];
                }
            }
        }
        $terms = array_merge($terms, $_terms);
        $objects = true;
    } elseif ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } elseif ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    // Update termmeta cache, if necessary.
    if ($args['update_term_meta_cache'] && ('all' === $fields || 'all_with_object_ids' === $fields || 'term_id' === $fields)) {
        if ('term_id' === $fields) {
            $term_ids = $fields;
        } else {
            $term_ids = wp_list_pluck($terms, 'term_id');
        }
        update_termmeta_cache($term_ids);
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms           An array of terms for the given object or objects.
     * @param array $object_id_array Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomy_array  Array of taxonomies from which `$terms` were retrieved.
     * @param array $args            An array of arguments for retrieving terms for the given
     *                               object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_id_array, $taxonomy_array, $args);
    /**
     * Filter the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See {@see wp_get_object_terms()} for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .30

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args {
 *     Array of arguments.
 *     @type string $orderby Field by which results should be sorted. Accepts 'name', 'count', 'slug', 'term_group',
 *                           'term_order', 'taxonomy', 'parent', or 'term_taxonomy_id'. Default 'name'.
 *     @type string $order   Sort order. Accepts 'ASC' or 'DESC'. Default 'ASC'.
 *     @type string $fields  Fields to return for matched terms. Accepts 'all', 'ids', 'names', and
 *                           'all_with_object_id'. Note that 'all' or 'all_with_object_id' will result in an array of
 *                           term objects being returned, 'ids' will return an array of integers, and 'names' an array
 *                           of strings.
 *     @type int    $parent  Optional. Limit results to the direct children of a given term ID.
 * }
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'parent' => '');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if (in_array($orderby, array('term_id', 'name', 'slug', 'term_group'))) {
        $orderby = "t.{$orderby}";
    } elseif (in_array($orderby, array('count', 'parent', 'taxonomy', 'term_taxonomy_id'))) {
        $orderby = "tt.{$orderby}";
    } elseif ('term_order' === $orderby) {
        $orderby = 'tr.term_order';
    } elseif ('none' === $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomy_array = $taxonomies;
    $object_id_array = $object_ids;
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } elseif ('ids' == $fields) {
        $select_this = 't.term_id';
    } elseif ('names' == $fields) {
        $select_this = 't.name';
    } elseif ('slugs' == $fields) {
        $select_this = 't.slug';
    } elseif ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $where = array("tt.taxonomy IN ({$taxonomies})", "tr.object_id IN ({$object_ids})");
    if ('' !== $args['parent']) {
        $where[] = $wpdb->prepare('tt.parent = %d', $args['parent']);
    }
    $where = implode(' AND ', $where);
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE {$where} {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } elseif ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } elseif ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms           An array of terms for the given object or objects.
     * @param array $object_id_array Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomy_array  Array of taxonomies from which `$terms` were retrieved.
     * @param array $args            An array of arguments for retrieving terms for the given
     *                               object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_id_array, $taxonomy_array, $args);
    /**
     * Filter the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See {@see wp_get_object_terms()} for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 3.3

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args {
 *     Array of arguments.
 *     @type string $orderby Field by which results should be sorted. Accepts 'name', 'count', 'slug', 'term_group',
 *                           'term_order', 'taxonomy', 'parent', or 'term_taxonomy_id'. Default 'name'.
 *     @type string $order   Sort order. Accepts 'ASC' or 'DESC'. Default 'ASC'.
 *     @type string $fields  Fields to return for matched terms. Accepts 'all', 'ids', 'names', and
 *                           'all_with_object_id'. Note that 'all' or 'all_with_object_id' will result in an array of
 *                           term objects being returned, 'ids' will return an array of integers, and 'names' an array
 *                           of strings.
 *     @type int    $parent  Optional. Limit results to the direct children of a given term ID.
 * }
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'parent' => '');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if (in_array($orderby, array('term_id', 'name', 'slug', 'term_group'))) {
        $orderby = "t.{$orderby}";
    } elseif (in_array($orderby, array('count', 'parent', 'taxonomy', 'term_taxonomy_id'))) {
        $orderby = "tt.{$orderby}";
    } elseif ('term_order' === $orderby) {
        $orderby = 'tr.term_order';
    } elseif ('none' === $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomy_array = $taxonomies;
    $object_id_array = $object_ids;
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } elseif ('ids' == $fields) {
        $select_this = 't.term_id';
    } elseif ('names' == $fields) {
        $select_this = 't.name';
    } elseif ('slugs' == $fields) {
        $select_this = 't.slug';
    } elseif ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $where = array("tt.taxonomy IN ({$taxonomies})", "tr.object_id IN ({$object_ids})");
    if ('' !== $args['parent']) {
        $where[] = $wpdb->prepare('tt.parent = %d', $args['parent']);
    }
    $where = implode(' AND ', $where);
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE {$where} {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } elseif ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } elseif ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms           An array of terms for the given object or objects.
     * @param array $object_id_array Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomy_array  Array of taxonomies from which `$terms` were retrieved.
     * @param array $args            An array of arguments for retrieving terms for the given
     *                               object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_id_array, $taxonomy_array, $args);
    /**
     * Filter the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See {@see wp_get_object_terms()} for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .20

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args {
 *     Array of arguments.
 *     @type string $orderby Field by which results should be sorted. Accepts 'name', 'count', 'slug', 'term_group',
 *                           'term_order', 'taxonomy', 'parent', or 'term_taxonomy_id'. Default 'name'.
 *     @type string $order   Sort order. Accepts 'ASC' or 'DESC'. Default 'ASC'.
 *     @type string $fields  Fields to return for matched terms. Accepts 'all', 'ids', 'names', and
 *                           'all_with_object_id'. Note that 'all' or 'all_with_object_id' will result in an array of
 *                           term objects being returned, 'ids' will return an array of integers, and 'names' an array
 *                           of strings.
 *     @type int    $parent  Optional. Limit results to the direct children of a given term ID.
 * }
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'parent' => '');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if (in_array($orderby, array('term_id', 'name', 'slug', 'term_group'))) {
        $orderby = "t.{$orderby}";
    } elseif (in_array($orderby, array('count', 'parent', 'taxonomy', 'term_taxonomy_id'))) {
        $orderby = "tt.{$orderby}";
    } elseif ('term_order' === $orderby) {
        $orderby = 'tr.term_order';
    } elseif ('none' === $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomy_array = $taxonomies;
    $object_id_array = $object_ids;
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } elseif ('ids' == $fields) {
        $select_this = 't.term_id';
    } elseif ('names' == $fields) {
        $select_this = 't.name';
    } elseif ('slugs' == $fields) {
        $select_this = 't.slug';
    } elseif ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $where = array("tt.taxonomy IN ({$taxonomies})", "tr.object_id IN ({$object_ids})");
    if ('' !== $args['parent']) {
        $where[] = $wpdb->prepare('tt.parent = %d', $args['parent']);
    }
    $where = implode(' AND ', $where);
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE {$where} {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } elseif ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } elseif ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms           An array of terms for the given object or objects.
     * @param array $object_id_array Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomy_array  Array of taxonomies from which `$terms` were retrieved.
     * @param array $args            An array of arguments for retrieving terms for the given
     *                               object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_id_array, $taxonomy_array, $args);
    /**
     * Filter the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See {@see wp_get_object_terms()} for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 3.2

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args {
 *     Array of arguments.
 *     @type string $orderby Field by which results should be sorted. Accepts 'name', 'count', 'slug', 'term_group',
 *                           'term_order', 'taxonomy', 'parent', or 'term_taxonomy_id'. Default 'name'.
 *     @type string $order   Sort order. Accepts 'ASC' or 'DESC'. Default 'ASC'.
 *     @type string $fields  Fields to return for matched terms. Accepts 'all', 'ids', 'names', and
 *                           'all_with_object_id'. Note that 'all' or 'all_with_object_id' will result in an array of
 *                           term objects being returned, 'ids' will return an array of integers, and 'names' an array
 *                           of strings.
 *     @type int    $parent  Optional. Limit results to the direct children of a given term ID.
 * }
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'parent' => '');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if (in_array($orderby, array('term_id', 'name', 'slug', 'term_group'))) {
        $orderby = "t.{$orderby}";
    } elseif (in_array($orderby, array('count', 'parent', 'taxonomy', 'term_taxonomy_id'))) {
        $orderby = "tt.{$orderby}";
    } elseif ('term_order' === $orderby) {
        $orderby = 'tr.term_order';
    } elseif ('none' === $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomy_array = $taxonomies;
    $object_id_array = $object_ids;
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } elseif ('ids' == $fields) {
        $select_this = 't.term_id';
    } elseif ('names' == $fields) {
        $select_this = 't.name';
    } elseif ('slugs' == $fields) {
        $select_this = 't.slug';
    } elseif ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $where = array("tt.taxonomy IN ({$taxonomies})", "tr.object_id IN ({$object_ids})");
    if ('' !== $args['parent']) {
        $where[] = $wpdb->prepare('tt.parent = %d', $args['parent']);
    }
    $where = implode(' AND ', $where);
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE {$where} {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } elseif ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } elseif ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms           An array of terms for the given object or objects.
     * @param array $object_id_array Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomy_array  Array of taxonomies from which `$terms` were retrieved.
     * @param array $args            An array of arguments for retrieving terms for the given
     *                               object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_id_array, $taxonomy_array, $args);
    /**
     * Filter the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See {@see wp_get_object_terms()} for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .10

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args {
 *     Array of arguments.
 *     @type string $orderby Field by which results should be sorted. Accepts 'name', 'count', 'slug', 'term_group',
 *                           'term_order', 'taxonomy', 'parent', or 'term_taxonomy_id'. Default 'name'.
 *     @type string $order   Sort order. Accepts 'ASC' or 'DESC'. Default 'ASC'.
 *     @type string $fields  Fields to return for matched terms. Accepts 'all', 'ids', 'names', and
 *                           'all_with_object_id'. Note that 'all' or 'all_with_object_id' will result in an array of
 *                           term objects being returned, 'ids' will return an array of integers, and 'names' an array
 *                           of strings.
 *     @type int    $parent  Optional. Limit results to the direct children of a given term ID.
 * }
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'parent' => '');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if (in_array($orderby, array('term_id', 'name', 'slug', 'term_group'))) {
        $orderby = "t.{$orderby}";
    } elseif (in_array($orderby, array('count', 'parent', 'taxonomy', 'term_taxonomy_id'))) {
        $orderby = "tt.{$orderby}";
    } elseif ('term_order' === $orderby) {
        $orderby = 'tr.term_order';
    } elseif ('none' === $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomy_array = $taxonomies;
    $object_id_array = $object_ids;
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } elseif ('ids' == $fields) {
        $select_this = 't.term_id';
    } elseif ('names' == $fields) {
        $select_this = 't.name';
    } elseif ('slugs' == $fields) {
        $select_this = 't.slug';
    } elseif ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $where = array("tt.taxonomy IN ({$taxonomies})", "tr.object_id IN ({$object_ids})");
    if ('' !== $args['parent']) {
        $where[] = $wpdb->prepare('tt.parent = %d', $args['parent']);
    }
    $where = implode(' AND ', $where);
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE {$where} {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } elseif ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } elseif ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms           An array of terms for the given object or objects.
     * @param array $object_id_array Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomy_array  Array of taxonomies from which `$terms` were retrieved.
     * @param array $args            An array of arguments for retrieving terms for the given
     *                               object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_id_array, $taxonomy_array, $args);
    /**
     * Filter the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See {@see wp_get_object_terms()} for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 4.3

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args {
 *     Array of arguments.
 *     @type string $orderby Field by which results should be sorted. Accepts 'name', 'count', 'slug', 'term_group',
 *                           'term_order', 'taxonomy', 'parent', or 'term_taxonomy_id'. Default 'name'.
 *     @type string $order   Sort order. Accepts 'ASC' or 'DESC'. Default 'ASC'.
 *     @type string $fields  Fields to return for matched terms. Accepts 'all', 'ids', 'names', and
 *                           'all_with_object_id'. Note that 'all' or 'all_with_object_id' will result in an array of
 *                           term objects being returned, 'ids' will return an array of integers, and 'names' an array
 *                           of strings.
 *     @type int    $parent  Optional. Limit results to the direct children of a given term ID.
 * }
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'parent' => '');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if (in_array($orderby, array('term_id', 'name', 'slug', 'term_group'))) {
        $orderby = "t.{$orderby}";
    } elseif (in_array($orderby, array('count', 'parent', 'taxonomy', 'term_taxonomy_id'))) {
        $orderby = "tt.{$orderby}";
    } elseif ('term_order' === $orderby) {
        $orderby = 'tr.term_order';
    } elseif ('none' === $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomy_array = $taxonomies;
    $object_id_array = $object_ids;
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } elseif ('ids' == $fields) {
        $select_this = 't.term_id';
    } elseif ('names' == $fields) {
        $select_this = 't.name';
    } elseif ('slugs' == $fields) {
        $select_this = 't.slug';
    } elseif ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $where = array("tt.taxonomy IN ({$taxonomies})", "tr.object_id IN ({$object_ids})");
    if ('' !== $args['parent']) {
        $where[] = $wpdb->prepare('tt.parent = %d', $args['parent']);
    }
    $where = implode(' AND ', $where);
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE {$where} {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } elseif ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } elseif ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms           An array of terms for the given object or objects.
     * @param array $object_id_array Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomy_array  Array of taxonomies from which `$terms` were retrieved.
     * @param array $args            An array of arguments for retrieving terms for the given
     *                               object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_id_array, $taxonomy_array, $args);
    /**
     * Filter the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See {@see wp_get_object_terms()} for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 2.8

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args {
 *     Array of arguments.
 *     @type string $orderby Field by which results should be sorted. Accepts 'name', 'count', 'slug', 'term_group',
 *                           'term_order', 'taxonomy', 'parent', or 'term_taxonomy_id'. Default 'name'.
 *     @type string $order   Sort order. Accepts 'ASC' or 'DESC'. Default 'ASC'.
 *     @type string $fields  Fields to return for matched terms. Accepts 'all', 'ids', 'names', and
 *                           'all_with_object_id'. Note that 'all' or 'all_with_object_id' will result in an array of
 *                           term objects being returned, 'ids' will return an array of integers, and 'names' an array
 *                           of strings.
 *     @type int    $parent  Optional. Limit results to the direct children of a given term ID.
 * }
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'parent' => '');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if (in_array($orderby, array('term_id', 'name', 'slug', 'term_group'))) {
        $orderby = "t.{$orderby}";
    } else if (in_array($orderby, array('count', 'parent', 'taxonomy', 'term_taxonomy_id'))) {
        $orderby = "tt.{$orderby}";
    } else if ('term_order' === $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' === $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomy_array = $taxonomies;
    $object_id_array = $object_ids;
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } elseif ('ids' == $fields) {
        $select_this = 't.term_id';
    } elseif ('names' == $fields) {
        $select_this = 't.name';
    } elseif ('slugs' == $fields) {
        $select_this = 't.slug';
    } elseif ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $where = array("tt.taxonomy IN ({$taxonomies})", "tr.object_id IN ({$object_ids})");
    if ('' !== $args['parent']) {
        $where[] = $wpdb->prepare('tt.parent = %d', $args['parent']);
    }
    $where = implode(' AND ', $where);
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE {$where} {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } elseif ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } elseif ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms           An array of terms for the given object or objects.
     * @param array $object_id_array Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomy_array  Array of taxonomies from which `$terms` were retrieved.
     * @param array $args            An array of arguments for retrieving terms for the given
     *                               object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_id_array, $taxonomy_array, $args);
    /**
     * Filter the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See {@see wp_get_object_terms()} for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 2.4

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args {
 *     Array of arguments.
 *     @type string $orderby Field by which results should be sorted. Accepts 'name', 'count', 'slug', 'term_group',
 *                           'term_order', 'taxonomy', 'parent', or 'term_taxonomy_id'. Default 'name'.
 *     @type string $order   Sort order. Accepts 'ASC' or 'DESC'. Default 'ASC'.
 *     @type string $fields  Fields to return for matched terms. Accepts 'all', 'ids', 'names', and
 *                           'all_with_object_id'. Note that 'all' or 'all_with_object_id' will result in an array of
 *                           term objects being returned, 'ids' will return an array of integers, and 'names' an array
 *                           of strings.
 *     @type int    $parent  Optional. Limit results to the direct children of a given term ID.
 * }
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'parent' => '');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if (in_array($orderby, array('term_id', 'name', 'slug', 'term_group'))) {
        $orderby = "t.{$orderby}";
    } else if (in_array($orderby, array('count', 'parent', 'taxonomy', 'term_taxonomy_id'))) {
        $orderby = "tt.{$orderby}";
    } else if ('term_order' === $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' === $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomy_array = $taxonomies;
    $object_id_array = $object_ids;
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } elseif ('ids' == $fields) {
        $select_this = 't.term_id';
    } elseif ('names' == $fields) {
        $select_this = 't.name';
    } elseif ('slugs' == $fields) {
        $select_this = 't.slug';
    } elseif ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $where = array("tt.taxonomy IN ({$taxonomies})", "tr.object_id IN ({$object_ids})");
    if ('' !== $args['parent']) {
        $where[] = $wpdb->prepare('tt.parent = %d', $args['parent']);
    }
    $where = implode(' AND ', $where);
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE {$where} {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } elseif ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } elseif ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms           An array of terms for the given object or objects.
     * @param array $object_id_array Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomy_array  Array of taxonomies from which `$terms` were retrieved.
     * @param array $args            An array of arguments for retrieving terms for the given
     *                               object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_id_array, $taxonomy_array, $args);
    /**
     * Filter the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See {@see wp_get_object_terms()} for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .30

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args {
 *     Array of arguments.
 *     @type string $orderby Field by which results should be sorted. Accepts 'name', 'count', 'slug', 'term_group',
 *                           'term_order', 'taxonomy', 'parent', or 'term_taxonomy_id'. Default 'name'.
 *     @type string $order   Sort order. Accepts 'ASC' or 'DESC'. Default 'ASC'.
 *     @type string $fields  Fields to return for matched terms. Accepts 'all', 'ids', 'names', and
 *                           'all_with_object_id'. Note that 'all' or 'all_with_object_id' will result in an array of
 *                           term objects being returned, 'ids' will return an array of integers, and 'names' an array
 *                           of strings.
 *     @type int    $parent  Optional. Limit results to the direct children of a given term ID.
 * }
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'parent' => '');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if (in_array($orderby, array('term_id', 'name', 'slug', 'term_group'))) {
        $orderby = "t.{$orderby}";
    } else if (in_array($orderby, array('count', 'parent', 'taxonomy', 'term_taxonomy_id'))) {
        $orderby = "tt.{$orderby}";
    } else if ('term_order' === $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' === $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomy_array = $taxonomies;
    $object_id_array = $object_ids;
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } elseif ('ids' == $fields) {
        $select_this = 't.term_id';
    } elseif ('names' == $fields) {
        $select_this = 't.name';
    } elseif ('slugs' == $fields) {
        $select_this = 't.slug';
    } elseif ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $where = array("tt.taxonomy IN ({$taxonomies})", "tr.object_id IN ({$object_ids})");
    if ('' !== $args['parent']) {
        $where[] = $wpdb->prepare('tt.parent = %d', $args['parent']);
    }
    $where = implode(' AND ', $where);
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE {$where} {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } elseif ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } elseif ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms           An array of terms for the given object or objects.
     * @param array $object_id_array Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomy_array  Array of taxonomies from which `$terms` were retrieved.
     * @param array $args            An array of arguments for retrieving terms for the given
     *                               object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_id_array, $taxonomy_array, $args);
    /**
     * Filter the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See {@see wp_get_object_terms()} for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 2.3

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args {
 *     Array of arguments.
 *     @type string $orderby Field by which results should be sorted. Accepts 'name', 'count', 'slug', 'term_group',
 *                           'term_order', 'taxonomy', 'parent', or 'term_taxonomy_id'. Default 'name'.
 *     @type string $order   Sort order. Accepts 'ASC' or 'DESC'. Default 'ASC'.
 *     @type string $fields  Fields to return for matched terms. Accepts 'all', 'ids', 'names', and
 *                           'all_with_object_id'. Note that 'all' or 'all_with_object_id' will result in an array of
 *                           term objects being returned, 'ids' will return an array of integers, and 'names' an array
 *                           of strings.
 *     @type int    $parent  Optional. Limit results to the direct children of a given term ID.
 * }
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'parent' => '');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if (in_array($orderby, array('term_id', 'name', 'slug', 'term_group'))) {
        $orderby = "t.{$orderby}";
    } else if (in_array($orderby, array('count', 'parent', 'taxonomy', 'term_taxonomy_id'))) {
        $orderby = "tt.{$orderby}";
    } else if ('term_order' === $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' === $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomy_array = $taxonomies;
    $object_id_array = $object_ids;
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } elseif ('ids' == $fields) {
        $select_this = 't.term_id';
    } elseif ('names' == $fields) {
        $select_this = 't.name';
    } elseif ('slugs' == $fields) {
        $select_this = 't.slug';
    } elseif ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $where = array("tt.taxonomy IN ({$taxonomies})", "tr.object_id IN ({$object_ids})");
    if ('' !== $args['parent']) {
        $where[] = $wpdb->prepare('tt.parent = %d', $args['parent']);
    }
    $where = implode(' AND ', $where);
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE {$where} {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } elseif ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } elseif ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms           An array of terms for the given object or objects.
     * @param array $object_id_array Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomy_array  Array of taxonomies from which `$terms` were retrieved.
     * @param array $args            An array of arguments for retrieving terms for the given
     *                               object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_id_array, $taxonomy_array, $args);
    /**
     * Filter the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See {@see wp_get_object_terms()} for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .20

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args {
 *     Array of arguments.
 *     @type string $orderby Field by which results should be sorted. Accepts 'name', 'count', 'slug', 'term_group',
 *                           'term_order', 'taxonomy', 'parent', or 'term_taxonomy_id'. Default 'name'.
 *     @type string $order   Sort order. Accepts 'ASC' or 'DESC'. Default 'ASC'.
 *     @type string $fields  Fields to return for matched terms. Accepts 'all', 'ids', 'names', and
 *                           'all_with_object_id'. Note that 'all' or 'all_with_object_id' will result in an array of
 *                           term objects being returned, 'ids' will return an array of integers, and 'names' an array
 *                           of strings.
 *     @type int    $parent  Optional. Limit results to the direct children of a given term ID.
 * }
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'parent' => '');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if (in_array($orderby, array('term_id', 'name', 'slug', 'term_group'))) {
        $orderby = "t.{$orderby}";
    } else if (in_array($orderby, array('count', 'parent', 'taxonomy', 'term_taxonomy_id'))) {
        $orderby = "tt.{$orderby}";
    } else if ('term_order' === $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' === $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomy_array = $taxonomies;
    $object_id_array = $object_ids;
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } elseif ('ids' == $fields) {
        $select_this = 't.term_id';
    } elseif ('names' == $fields) {
        $select_this = 't.name';
    } elseif ('slugs' == $fields) {
        $select_this = 't.slug';
    } elseif ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $where = array("tt.taxonomy IN ({$taxonomies})", "tr.object_id IN ({$object_ids})");
    if ('' !== $args['parent']) {
        $where[] = $wpdb->prepare('tt.parent = %d', $args['parent']);
    }
    $where = implode(' AND ', $where);
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE {$where} {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } elseif ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } elseif ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms           An array of terms for the given object or objects.
     * @param array $object_id_array Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomy_array  Array of taxonomies from which `$terms` were retrieved.
     * @param array $args            An array of arguments for retrieving terms for the given
     *                               object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_id_array, $taxonomy_array, $args);
    /**
     * Filter the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See {@see wp_get_object_terms()} for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 2.2

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args {
 *     Array of arguments.
 *     @type string $orderby Field by which results should be sorted. Accepts 'name', 'count', 'slug', 'term_group',
 *                           'term_order', 'taxonomy', 'parent', or 'term_taxonomy_id'. Default 'name'.
 *     @type string $order   Sort order. Accepts 'ASC' or 'DESC'. Default 'ASC'.
 *     @type string $fields  Fields to return for matched terms. Accepts 'all', 'ids', 'names', and
 *                           'all_with_object_id'. Note that 'all' or 'all_with_object_id' will result in an array of
 *                           term objects being returned, 'ids' will return an array of integers, and 'names' an array
 *                           of strings.
 *     @type int    $parent  Optional. Limit results to the direct children of a given term ID.
 * }
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'parent' => '');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if (in_array($orderby, array('term_id', 'name', 'slug', 'term_group'))) {
        $orderby = "t.{$orderby}";
    } else if (in_array($orderby, array('count', 'parent', 'taxonomy', 'term_taxonomy_id'))) {
        $orderby = "tt.{$orderby}";
    } else if ('term_order' === $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' === $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomy_array = $taxonomies;
    $object_id_array = $object_ids;
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } elseif ('ids' == $fields) {
        $select_this = 't.term_id';
    } elseif ('names' == $fields) {
        $select_this = 't.name';
    } elseif ('slugs' == $fields) {
        $select_this = 't.slug';
    } elseif ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $where = array("tt.taxonomy IN ({$taxonomies})", "tr.object_id IN ({$object_ids})");
    if ('' !== $args['parent']) {
        $where[] = $wpdb->prepare('tt.parent = %d', $args['parent']);
    }
    $where = implode(' AND ', $where);
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE {$where} {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } elseif ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } elseif ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms           An array of terms for the given object or objects.
     * @param array $object_id_array Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomy_array  Array of taxonomies from which `$terms` were retrieved.
     * @param array $args            An array of arguments for retrieving terms for the given
     *                               object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_id_array, $taxonomy_array, $args);
    /**
     * Filter the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See {@see wp_get_object_terms()} for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .10

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args {
 *     Array of arguments.
 *     @type string $orderby Field by which results should be sorted. Accepts 'name', 'count', 'slug', 'term_group',
 *                           'term_order', 'taxonomy', 'parent', or 'term_taxonomy_id'. Default 'name'.
 *     @type string $order   Sort order. Accepts 'ASC' or 'DESC'. Default 'ASC'.
 *     @type string $fields  Fields to return for matched terms. Accepts 'all', 'ids', 'names', and
 *                           'all_with_object_id'. Note that 'all' or 'all_with_object_id' will result in an array of
 *                           term objects being returned, 'ids' will return an array of integers, and 'names' an array
 *                           of strings.
 *     @type int    $parent  Optional. Limit results to the direct children of a given term ID.
 * }
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'parent' => '');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if (in_array($orderby, array('term_id', 'name', 'slug', 'term_group'))) {
        $orderby = "t.{$orderby}";
    } else if (in_array($orderby, array('count', 'parent', 'taxonomy', 'term_taxonomy_id'))) {
        $orderby = "tt.{$orderby}";
    } else if ('term_order' === $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' === $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomy_array = $taxonomies;
    $object_id_array = $object_ids;
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } elseif ('ids' == $fields) {
        $select_this = 't.term_id';
    } elseif ('names' == $fields) {
        $select_this = 't.name';
    } elseif ('slugs' == $fields) {
        $select_this = 't.slug';
    } elseif ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $where = array("tt.taxonomy IN ({$taxonomies})", "tr.object_id IN ({$object_ids})");
    if ('' !== $args['parent']) {
        $where[] = $wpdb->prepare('tt.parent = %d', $args['parent']);
    }
    $where = implode(' AND ', $where);
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE {$where} {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } elseif ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } elseif ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms           An array of terms for the given object or objects.
     * @param array $object_id_array Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomy_array  Array of taxonomies from which `$terms` were retrieved.
     * @param array $args            An array of arguments for retrieving terms for the given
     *                               object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_id_array, $taxonomy_array, $args);
    /**
     * Filter the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See {@see wp_get_object_terms()} for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 4.2

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * @since 2.3.0
 * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
 *              Introduced `$parent` argument.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array    $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args {
 *     Array of arguments.
 *     @type string $orderby Field by which results should be sorted. Accepts 'name', 'count', 'slug', 'term_group',
 *                           'term_order', 'taxonomy', 'parent', or 'term_taxonomy_id'. Default 'name'.
 *     @type string $order   Sort order. Accepts 'ASC' or 'DESC'. Default 'ASC'.
 *     @type string $fields  Fields to return for matched terms. Accepts 'all', 'ids', 'names', and
 *                           'all_with_object_id'. Note that 'all' or 'all_with_object_id' will result in an array of
 *                           term objects being returned, 'ids' will return an array of integers, and 'names' an array
 *                           of strings.
 *     @type int    $parent  Optional. Limit results to the direct children of a given term ID.
 * }
 * @return array|WP_Error The requested term data or empty array if no terms found.
 *                        WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all', 'parent' => '');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if (in_array($orderby, array('term_id', 'name', 'slug', 'term_group'))) {
        $orderby = "t.{$orderby}";
    } else if (in_array($orderby, array('count', 'parent', 'taxonomy', 'term_taxonomy_id'))) {
        $orderby = "tt.{$orderby}";
    } else if ('term_order' === $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' === $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomy_array = $taxonomies;
    $object_id_array = $object_ids;
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } elseif ('ids' == $fields) {
        $select_this = 't.term_id';
    } elseif ('names' == $fields) {
        $select_this = 't.name';
    } elseif ('slugs' == $fields) {
        $select_this = 't.slug';
    } elseif ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $where = array("tt.taxonomy IN ({$taxonomies})", "tr.object_id IN ({$object_ids})");
    if ('' !== $args['parent']) {
        $where[] = $wpdb->prepare('tt.parent = %d', $args['parent']);
    }
    $where = implode(' AND ', $where);
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE {$where} {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } elseif ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } elseif ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 4.2.0
     *
     * @param array $terms           An array of terms for the given object or objects.
     * @param array $object_id_array Array of object IDs for which `$terms` were retrieved.
     * @param array $taxonomy_array  Array of taxonomies from which `$terms` were retrieved.
     * @param array $args            An array of arguments for retrieving terms for the given
     *                               object(s). See wp_get_object_terms() for details.
     */
    $terms = apply_filters('get_object_terms', $terms, $object_id_array, $taxonomy_array, $args);
    /**
     * Filter the terms for a given object or objects.
     *
     * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
     * {@see 'get_object_terms'} filter is recommended as an alternative.
     *
     * @since 2.8.0
     *
     * @param array     $terms      An array of terms for the given object or objects.
     * @param int|array $object_ids Object ID or array of IDs.
     * @param string    $taxonomies SQL-formatted (comma-separated and quoted) list of taxonomy names.
     * @param array     $args       An array of arguments for retrieving terms for the given object(s).
     *                              See {@see wp_get_object_terms()} for details.
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 1.5

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @since 2.3.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 2.8.0
     *
     * @param array        $terms      An array of terms for the given object or objects.
     * @param array|int    $object_ids Object ID or array of IDs.
     * @param array|string $taxonomies A taxonomy or array of taxonomies.
     * @param array        $args       An array of arguments for retrieving terms for
     *                                 the given object(s).
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .40

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @since 2.3.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 2.8.0
     *
     * @param array        $terms      An array of terms for the given object or objects.
     * @param array|int    $object_ids Object ID or array of IDs.
     * @param array|string $taxonomies A taxonomy or array of taxonomies.
     * @param array        $args       An array of arguments for retrieving terms for
     *                                 the given object(s).
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 1.4

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @since 2.3.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 2.8.0
     *
     * @param array        $terms      An array of terms for the given object or objects.
     * @param array|int    $object_ids Object ID or array of IDs.
     * @param array|string $taxonomies A taxonomy or array of taxonomies.
     * @param array        $args       An array of arguments for retrieving terms for
     *                                 the given object(s).
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .30

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @since 2.3.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 2.8.0
     *
     * @param array        $terms      An array of terms for the given object or objects.
     * @param array|int    $object_ids Object ID or array of IDs.
     * @param array|string $taxonomies A taxonomy or array of taxonomies.
     * @param array        $args       An array of arguments for retrieving terms for
     *                                 the given object(s).
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 1.3

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @since 2.3.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 2.8.0
     *
     * @param array        $terms      An array of terms for the given object or objects.
     * @param array|int    $object_ids Object ID or array of IDs.
     * @param array|string $taxonomies A taxonomy or array of taxonomies.
     * @param array        $args       An array of arguments for retrieving terms for
     *                                 the given object(s).
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .20

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @since 2.3.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 2.8.0
     *
     * @param array        $terms      An array of terms for the given object or objects.
     * @param array|int    $object_ids Object ID or array of IDs.
     * @param array|string $taxonomies A taxonomy or array of taxonomies.
     * @param array        $args       An array of arguments for retrieving terms for
     *                                 the given object(s).
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 1.2

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @since 2.3.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 2.8.0
     *
     * @param array        $terms      An array of terms for the given object or objects.
     * @param array|int    $object_ids Object ID or array of IDs.
     * @param array|string $taxonomies A taxonomy or array of taxonomies.
     * @param array        $args       An array of arguments for retrieving terms for
     *                                 the given object(s).
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .11

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @since 2.3.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 2.8.0
     *
     * @param array        $terms      An array of terms for the given object or objects.
     * @param array|int    $object_ids Object ID or array of IDs.
     * @param array|string $taxonomies A taxonomy or array of taxonomies.
     * @param array        $args       An array of arguments for retrieving terms for
     *                                 the given object(s).
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 4.1

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @since 2.3.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 2.8.0
     *
     * @param array        $terms      An array of terms for the given object or objects.
     * @param array|int    $object_ids Object ID or array of IDs.
     * @param array|string $taxonomies A taxonomy or array of taxonomies.
     * @param array        $args       An array of arguments for retrieving terms for
     *                                 the given object(s).
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 0.4

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 2.8.0
     *
     * @param array        $terms      An array of terms for the given object or objects.
     * @param array|int    $object_ids Object ID or array of IDs.
     * @param array|string $taxonomies A taxonomy or array of taxonomies.
     * @param array        $args       An array of arguments for retrieving terms for
     *                                 the given object(s).
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .30

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 2.8.0
     *
     * @param array        $terms      An array of terms for the given object or objects.
     * @param array|int    $object_ids Object ID or array of IDs.
     * @param array|string $taxonomies A taxonomy or array of taxonomies.
     * @param array        $args       An array of arguments for retrieving terms for
     *                                 the given object(s).
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 0.3

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 2.8.0
     *
     * @param array        $terms      An array of terms for the given object or objects.
     * @param array|int    $object_ids Object ID or array of IDs.
     * @param array|string $taxonomies A taxonomy or array of taxonomies.
     * @param array        $args       An array of arguments for retrieving terms for
     *                                 the given object(s).
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .20

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 2.8.0
     *
     * @param array        $terms      An array of terms for the given object or objects.
     * @param array|int    $object_ids Object ID or array of IDs.
     * @param array|string $taxonomies A taxonomy or array of taxonomies.
     * @param array        $args       An array of arguments for retrieving terms for
     *                                 the given object(s).
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 0.2

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 2.8.0
     *
     * @param array        $terms      An array of terms for the given object or objects.
     * @param array|int    $object_ids Object ID or array of IDs.
     * @param array|string $taxonomies A taxonomy or array of taxonomies.
     * @param array        $args       An array of arguments for retrieving terms for
     *                                 the given object(s).
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .11

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 2.8.0
     *
     * @param array        $terms      An array of terms for the given object or objects.
     * @param array|int    $object_ids Object ID or array of IDs.
     * @param array|string $taxonomies A taxonomy or array of taxonomies.
     * @param array        $args       An array of arguments for retrieving terms for
     *                                 the given object(s).
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 4.0

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    $orderby = $args['orderby'];
    $order = $args['order'];
    $fields = $args['fields'];
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    $objects = false;
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
        $objects = true;
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    } elseif ($objects && 'all_with_object_id' !== $fields) {
        $_tt_ids = array();
        $_terms = array();
        foreach ($terms as $term) {
            if (in_array($term->term_taxonomy_id, $_tt_ids)) {
                continue;
            }
            $_tt_ids[] = $term->term_taxonomy_id;
            $_terms[] = $term;
        }
        $terms = $_terms;
    } elseif (!$objects) {
        $terms = array_values(array_unique($terms));
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 2.8.0
     *
     * @param array        $terms      An array of terms for the given object or objects.
     * @param array|int    $object_ids Object ID or array of IDs.
     * @param array|string $taxonomies A taxonomy or array of taxonomies.
     * @param array        $args       An array of arguments for retrieving terms for
     *                                 the given object(s).
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 9.2

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    extract($args, EXTR_SKIP);
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 2.8.0
     *
     * @param array        $terms      An array of terms for the given object or objects.
     * @param array|int    $object_ids Object ID or array of IDs.
     * @param array|string $taxonomies A taxonomy or array of taxonomies.
     * @param array        $args       An array of arguments for retrieving terms for
     *                                 the given object(s).
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .12

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    extract($args, EXTR_SKIP);
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 2.8.0
     *
     * @param array        $terms      An array of terms for the given object or objects.
     * @param array|int    $object_ids Object ID or array of IDs.
     * @param array|string $taxonomies A taxonomy or array of taxonomies.
     * @param array        $args       An array of arguments for retrieving terms for
     *                                 the given object(s).
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 3.9

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ($taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    extract($args, EXTR_SKIP);
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    }
    /**
     * Filter the terms for a given object or objects.
     *
     * @since 2.8.0
     *
     * @param array        $terms      An array of terms for the given object or objects.
     * @param array|int    $object_ids Object ID or array of IDs.
     * @param array|string $taxonomies A taxonomy or array of taxonomies.
     * @param array        $args       An array of arguments for retrieving terms for
     *                                 the given object(s).
     */
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 8.4

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @package WordPress
 * @subpackage Taxonomy
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ((array) $taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    extract($args, EXTR_SKIP);
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    }
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .30

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @package WordPress
 * @subpackage Taxonomy
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ((array) $taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    extract($args, EXTR_SKIP);
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    }
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 8.3

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @package WordPress
 * @subpackage Taxonomy
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ((array) $taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    extract($args, EXTR_SKIP);
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    }
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .20

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @package WordPress
 * @subpackage Taxonomy
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ((array) $taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    extract($args, EXTR_SKIP);
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    }
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 8.2

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @package WordPress
 * @subpackage Taxonomy
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ((array) $taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    extract($args, EXTR_SKIP);
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    }
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .14

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @package WordPress
 * @subpackage Taxonomy
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ((array) $taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    extract($args, EXTR_SKIP);
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    }
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 3.8

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @package WordPress
 * @subpackage Taxonomy
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ((array) $taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    extract($args, EXTR_SKIP);
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $_terms = $wpdb->get_results($query);
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term($term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
        update_term_cache($terms);
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $_terms = $wpdb->get_col($query);
        $_field = ('ids' == $fields) ? 'term_id' : 'name';
        foreach ($_terms as $key => $term) {
            $_terms[$key] = sanitize_term_field($_field, $term, $term, $taxonomy, 'raw');
        }
        $terms = array_merge($terms, $_terms);
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
        foreach ($terms as $key => $tt_id) {
            $terms[$key] = sanitize_term_field('term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw');
            // 0 should be the term id, however is not needed when using raw context.
        }
    }
    if (!$terms) {
        $terms = array();
    }
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 7.5

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @package WordPress
 * @subpackage Taxonomy
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ((array) $taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    extract($args, EXTR_SKIP);
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $terms = array_merge($terms, $wpdb->get_results($query));
        update_term_cache($terms);
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $terms = array_merge($terms, $wpdb->get_col($query));
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
    }
    if (!$terms) {
        $terms = array();
    }
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .40

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @package WordPress
 * @subpackage Taxonomy
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ((array) $taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    extract($args, EXTR_SKIP);
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $terms = array_merge($terms, $wpdb->get_results($query));
        update_term_cache($terms);
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $terms = array_merge($terms, $wpdb->get_col($query));
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
    }
    if (!$terms) {
        $terms = array();
    }
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 7.4

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @package WordPress
 * @subpackage Taxonomy
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ((array) $taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    extract($args, EXTR_SKIP);
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $terms = array_merge($terms, $wpdb->get_results($query));
        update_term_cache($terms);
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $terms = array_merge($terms, $wpdb->get_col($query));
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
    }
    if (!$terms) {
        $terms = array();
    }
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .30

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @package WordPress
 * @subpackage Taxonomy
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ((array) $taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    extract($args, EXTR_SKIP);
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $terms = array_merge($terms, $wpdb->get_results($query));
        update_term_cache($terms);
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $terms = array_merge($terms, $wpdb->get_col($query));
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
    }
    if (!$terms) {
        $terms = array();
    }
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 7.3

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @package WordPress
 * @subpackage Taxonomy
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ((array) $taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    extract($args, EXTR_SKIP);
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $terms = array_merge($terms, $wpdb->get_results($query));
        update_term_cache($terms);
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $terms = array_merge($terms, $wpdb->get_col($query));
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
    }
    if (!$terms) {
        $terms = array();
    }
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .20

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @package WordPress
 * @subpackage Taxonomy
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ((array) $taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    extract($args, EXTR_SKIP);
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $terms = array_merge($terms, $wpdb->get_results($query));
        update_term_cache($terms);
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $terms = array_merge($terms, $wpdb->get_col($query));
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
    }
    if (!$terms) {
        $terms = array();
    }
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 7.2

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @package WordPress
 * @subpackage Taxonomy
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ((array) $taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    extract($args, EXTR_SKIP);
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $terms = array_merge($terms, $wpdb->get_results($query));
        update_term_cache($terms);
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $terms = array_merge($terms, $wpdb->get_col($query));
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
    }
    if (!$terms) {
        $terms = array();
    }
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: .14

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @package WordPress
 * @subpackage Taxonomy
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ((array) $taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    extract($args, EXTR_SKIP);
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", array_map('esc_sql', $taxonomies)) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $terms = array_merge($terms, $wpdb->get_results($query));
        update_term_cache($terms);
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $terms = array_merge($terms, $wpdb->get_col($query));
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
    }
    if (!$terms) {
        $terms = array();
    }
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}

WordPress Version: 3.7

/**
 * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
 *
 * The following information has to do the $args parameter and for what can be
 * contained in the string or array of that parameter, if it exists.
 *
 * The first argument is called, 'orderby' and has the default value of 'name'.
 * The other value that is supported is 'count'.
 *
 * The second argument is called, 'order' and has the default value of 'ASC'.
 * The only other value that will be acceptable is 'DESC'.
 *
 * The final argument supported is called, 'fields' and has the default value of
 * 'all'. There are multiple other options that can be used instead. Supported
 * values are as follows: 'all', 'ids', 'names', and finally
 * 'all_with_object_id'.
 *
 * The fields argument also decides what will be returned. If 'all' or
 * 'all_with_object_id' is chosen or the default kept intact, then all matching
 * terms objects will be returned. If either 'ids' or 'names' is used, then an
 * array of all matching term ids or term names will be returned respectively.
 *
 * @package WordPress
 * @subpackage Taxonomy
 * @since 2.3.0
 * @uses $wpdb
 *
 * @param int|array $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|array $taxonomies The taxonomies to retrieve terms from.
 * @param array|string $args Change what is returned
 * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist.
 */
function wp_get_object_terms($object_ids, $taxonomies, $args = array())
{
    global $wpdb;
    if (empty($object_ids) || empty($taxonomies)) {
        return array();
    }
    if (!is_array($taxonomies)) {
        $taxonomies = array($taxonomies);
    }
    foreach ((array) $taxonomies as $taxonomy) {
        if (!taxonomy_exists($taxonomy)) {
            return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
        }
    }
    if (!is_array($object_ids)) {
        $object_ids = array($object_ids);
    }
    $object_ids = array_map('intval', $object_ids);
    $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all');
    $args = wp_parse_args($args, $defaults);
    $terms = array();
    if (count($taxonomies) > 1) {
        foreach ($taxonomies as $index => $taxonomy) {
            $t = get_taxonomy($taxonomy);
            if (isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args)) {
                unset($taxonomies[$index]);
                $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args)));
            }
        }
    } else {
        $t = get_taxonomy($taxonomies[0]);
        if (isset($t->args) && is_array($t->args)) {
            $args = array_merge($args, $t->args);
        }
    }
    extract($args, EXTR_SKIP);
    if ('count' == $orderby) {
        $orderby = 'tt.count';
    } else if ('name' == $orderby) {
        $orderby = 't.name';
    } else if ('slug' == $orderby) {
        $orderby = 't.slug';
    } else if ('term_group' == $orderby) {
        $orderby = 't.term_group';
    } else if ('term_order' == $orderby) {
        $orderby = 'tr.term_order';
    } else if ('none' == $orderby) {
        $orderby = '';
        $order = '';
    } else {
        $orderby = 't.term_id';
    }
    // tt_ids queries can only be none or tr.term_taxonomy_id
    if ('tt_ids' == $fields && !empty($orderby)) {
        $orderby = 'tr.term_taxonomy_id';
    }
    if (!empty($orderby)) {
        $orderby = "ORDER BY {$orderby}";
    }
    $order = strtoupper($order);
    if ('' !== $order && !in_array($order, array('ASC', 'DESC'))) {
        $order = 'ASC';
    }
    $taxonomies = "'" . implode("', '", $taxonomies) . "'";
    $object_ids = implode(', ', $object_ids);
    $select_this = '';
    if ('all' == $fields) {
        $select_this = 't.*, tt.*';
    } else if ('ids' == $fields) {
        $select_this = 't.term_id';
    } else if ('names' == $fields) {
        $select_this = 't.name';
    } else if ('slugs' == $fields) {
        $select_this = 't.slug';
    } else if ('all_with_object_id' == $fields) {
        $select_this = 't.*, tt.*, tr.object_id';
    }
    $query = "SELECT {$select_this} FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ({$taxonomies}) AND tr.object_id IN ({$object_ids}) {$orderby} {$order}";
    if ('all' == $fields || 'all_with_object_id' == $fields) {
        $terms = array_merge($terms, $wpdb->get_results($query));
        update_term_cache($terms);
    } else if ('ids' == $fields || 'names' == $fields || 'slugs' == $fields) {
        $terms = array_merge($terms, $wpdb->get_col($query));
    } else if ('tt_ids' == $fields) {
        $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ({$object_ids}) AND tt.taxonomy IN ({$taxonomies}) {$orderby} {$order}");
    }
    if (!$terms) {
        $terms = array();
    }
    return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
}