'update_term_meta_cache' => false,
'suppress_filter' => true,
$args['term_taxonomy_id'] = $value;
unset( $args['taxonomy'] );
$terms = get_terms( $args );
if ( is_wp_error( $terms ) || empty( $terms ) ) {
$term = array_shift( $terms );
// In the case of 'term_taxonomy_id', override the provided `$taxonomy` with whatever we find in the DB.
if ( 'term_taxonomy_id' === $field ) {
$taxonomy = $term->taxonomy;
return get_term( $term, $taxonomy, $output, $filter );
* Merge all term children into a single array of their IDs.
* This recursive function will merge all of the children of $term into the same
* array of term IDs. Only useful for taxonomies which are hierarchical.
* Will return an empty array if $term does not exist in $taxonomy.
* @param int $term_id ID of Term to get children.
* @param string $taxonomy Taxonomy Name.
* @return array|WP_Error List of Term IDs. WP_Error returned if `$taxonomy` does not exist.
function get_term_children( $term_id, $taxonomy ) {
if ( ! taxonomy_exists( $taxonomy ) ) {
return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy.' ) );
$term_id = (int) $term_id;
$terms = _get_term_hierarchy( $taxonomy );
if ( ! isset( $terms[ $term_id ] ) ) {
$children = $terms[ $term_id ];
foreach ( (array) $terms[ $term_id ] as $child ) {
if ( $term_id === $child ) {
if ( isset( $terms[ $child ] ) ) {
$children = array_merge( $children, get_term_children( $child, $taxonomy ) );
* Get sanitized Term field.
* The function is for contextual reasons and for simplicity of usage.
* @since 4.4.0 The `$taxonomy` parameter was made optional. `$term` can also now accept a WP_Term object.
* @see sanitize_term_field()
* @param string $field Term field to fetch.
* @param int|WP_Term $term Term ID or object.
* @param string $taxonomy Optional. Taxonomy Name. Default empty.
* @param string $context Optional. How to sanitize term fields. Look at sanitize_term_field() for available options.
* @return string|int|null|WP_Error Will return an empty string if $term is not an object or if $field is not set in $term.
function get_term_field( $field, $term, $taxonomy = '', $context = 'display' ) {
$term = get_term( $term, $taxonomy );
if ( is_wp_error( $term ) ) {
if ( ! is_object( $term ) ) {
if ( ! isset( $term->$field ) ) {
return sanitize_term_field( $field, $term->$field, $term->term_id, $term->taxonomy, $context );
* Sanitizes Term for editing.
* Return value is sanitize_term() and usage is for sanitizing the term for
* editing. Function is for contextual and simplicity.
* @param int|object $id Term ID or object.
* @param string $taxonomy Taxonomy name.
* @return string|int|null|WP_Error Will return empty string if $term is not an object.
function get_term_to_edit( $id, $taxonomy ) {
$term = get_term( $id, $taxonomy );
if ( is_wp_error( $term ) ) {
if ( ! is_object( $term ) ) {
return sanitize_term( $term, $taxonomy, 'edit' );
* Retrieves the terms in a given taxonomy or list of taxonomies.
* You can fully inject any customizations to the query before it is sent, as
* well as control the output with a filter.
* The return type varies depending on the value passed to `$args['fields']`. See
* WP_Term_Query::get_terms() for details. In all cases, a `WP_Error` object will
* be returned if an invalid taxonomy is requested.
* The {@see 'get_terms'} filter will be called when the cache has the term and will
* pass the found term along with the array of $taxonomies and array of $args.
* This filter is also called before the array of terms is passed and will pass
* the array of terms, along with the $taxonomies and $args.
* The {@see 'list_terms_exclusions'} filter passes the compiled exclusions along with
* The {@see 'get_terms_orderby'} filter passes the `ORDER BY` clause for the query
* along with the $args array.
* Prior to 4.5.0, the first parameter of `get_terms()` was a taxonomy or list of taxonomies:
* $terms = get_terms( 'post_tag', array(
* Since 4.5.0, taxonomies should be passed via the 'taxonomy' argument in the `$args` array:
* $terms = get_terms( array(
* 'taxonomy' => 'post_tag',
* @since 4.2.0 Introduced 'name' and 'childless' parameters.
* @since 4.4.0 Introduced the ability to pass 'term_id' as an alias of 'id' for the `orderby` parameter.
* Introduced the 'meta_query' and 'update_term_meta_cache' parameters. Converted to return
* a list of WP_Term objects.
* @since 4.5.0 Changed the function signature so that the `$args` array can be provided as the first parameter.
* Introduced 'meta_key' and 'meta_value' parameters. Introduced the ability to order results by metadata.
* @since 4.8.0 Introduced 'suppress_filter' parameter.
* @internal The `$deprecated` parameter is parsed for backward compatibility only.
* @param array|string $args Optional. Array or string of arguments. See WP_Term_Query::__construct()
* for information on accepted arguments. Default empty array.
* @param array|string $deprecated Optional. Argument array, when using the legacy function parameter format.
* If present, this parameter will be interpreted as `$args`, and the first
* function parameter will be parsed as a taxonomy or array of taxonomies.
* @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 the function description for more information.
function get_terms( $args = array(), $deprecated = '' ) {
$term_query = new WP_Term_Query();
'suppress_filter' => false,
* Legacy argument format ($taxonomy, $args) takes precedence.
* We detect legacy argument format by checking if
* (a) a second non-empty parameter is passed, or
* (b) the first parameter shares no keys with the default array (ie, it's a list of taxonomies)
$_args = wp_parse_args( $args );
$key_intersect = array_intersect_key( $term_query->query_var_defaults, (array) $_args );
$do_legacy_args = $deprecated || empty( $key_intersect );
$taxonomies = (array) $args;
$args = wp_parse_args( $deprecated, $defaults );
$args['taxonomy'] = $taxonomies;
$args = wp_parse_args( $args, $defaults );
if ( isset( $args['taxonomy'] ) && null !== $args['taxonomy'] ) {
$args['taxonomy'] = (array) $args['taxonomy'];
if ( ! empty( $args['taxonomy'] ) ) {
foreach ( $args['taxonomy'] as $taxonomy ) {
if ( ! taxonomy_exists( $taxonomy ) ) {
return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy.' ) );
// Don't pass suppress_filter to WP_Term_Query.
$suppress_filter = $args['suppress_filter'];
unset( $args['suppress_filter'] );
$terms = $term_query->query( $args );
// Count queries are not filtered, for legacy reasons.
if ( ! is_array( $terms ) ) {
if ( $suppress_filter ) {
* Filters the found terms.
* @since 4.6.0 Added the `$term_query` parameter.
* @param array $terms Array of found terms.
* @param array $taxonomies An array of taxonomies.
* @param array $args An array of get_terms() arguments.
* @param WP_Term_Query $term_query The WP_Term_Query object.
return apply_filters( 'get_terms', $terms, $term_query->query_vars['taxonomy'], $term_query->query_vars, $term_query );
* Adds metadata to a term.
* @param int $term_id Term ID.
* @param string $meta_key Metadata name.
* @param mixed $meta_value Metadata value. Must be serializable if non-scalar.
* @param bool $unique Optional. Whether the same key should not be added.
* @return int|false|WP_Error Meta ID on success, false on failure.
* WP_Error when term_id is ambiguous between taxonomies.
function add_term_meta( $term_id, $meta_key, $meta_value, $unique = false ) {
if ( wp_term_is_shared( $term_id ) ) {
return new WP_Error( 'ambiguous_term_id', __( 'Term meta cannot be added to terms that are shared between taxonomies.' ), $term_id );
return add_metadata( 'term', $term_id, $meta_key, $meta_value, $unique );
* Removes metadata matching criteria from a term.
* @param int $term_id Term ID.
* @param string $meta_key Metadata name.
* @param mixed $meta_value Optional. Metadata value. If provided,
* rows will only be removed that match the value.
* Must be serializable if non-scalar. Default empty.
* @return bool True on success, false on failure.
function delete_term_meta( $term_id, $meta_key, $meta_value = '' ) {
return delete_metadata( 'term', $term_id, $meta_key, $meta_value );
* Retrieves metadata for a term.
* @param int $term_id Term ID.
* @param string $key Optional. The meta key to retrieve. By default,
* returns data for all keys. Default empty.
* @param bool $single Optional. Whether to return a single value.
* This parameter has no effect if $key is not specified.
* @return mixed An array if $single is false. The value of the meta field
* if $single is true. False for an invalid $term_id.
function get_term_meta( $term_id, $key = '', $single = false ) {
return get_metadata( 'term', $term_id, $key, $single );
* Use the `$prev_value` parameter to differentiate between meta fields with the same key and term ID.
* If the meta field for the term does not exist, it will be added.
* @param int $term_id Term ID.
* @param string $meta_key Metadata key.
* @param mixed $meta_value Metadata value. Must be serializable if non-scalar.
* @param mixed $prev_value Optional. Previous value to check before updating.
* If specified, only update existing metadata entries with
* this value. Otherwise, update all entries. Default empty.
* @return int|bool|WP_Error Meta ID if the key didn't exist. true on successful update,
* false on failure or if the value passed to the function
* is the same as the one that is already in the database.
* WP_Error when term_id is ambiguous between taxonomies.
function update_term_meta( $term_id, $meta_key, $meta_value, $prev_value = '' ) {
if ( wp_term_is_shared( $term_id ) ) {
return new WP_Error( 'ambiguous_term_id', __( 'Term meta cannot be added to terms that are shared between taxonomies.' ), $term_id );
return update_metadata( 'term', $term_id, $meta_key, $meta_value, $prev_value );
* Updates metadata cache for list of term IDs.
* Performs SQL query to retrieve all metadata for the terms matching `$term_ids` and stores them in the cache.
* Subsequent calls to `get_term_meta()` will not need to query the database.
* @param array $term_ids List of term IDs.
* @return array|false An array of metadata on success, false if there is nothing to update.
function update_termmeta_cache( $term_ids ) {
return update_meta_cache( 'term', $term_ids );
* Get all meta data, including meta IDs, for the given term ID.
* @global wpdb $wpdb WordPress database abstraction object.
* @param int $term_id Term ID.
* @return array|false Array with meta data, or false when the meta table is not installed.
function has_term_meta( $term_id ) {
$check = wp_check_term_meta_support_prefilter( null );
return $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value, meta_id, term_id FROM $wpdb->termmeta WHERE term_id = %d ORDER BY meta_key,meta_id", $term_id ), ARRAY_A );
* Registers a meta key for terms.
* @param string $taxonomy Taxonomy to register a meta key for. Pass an empty string
* to register the meta key across all existing taxonomies.
* @param string $meta_key The meta key to register.
* @param array $args Data used to describe the meta key when registered. See
* {@see register_meta()} for a list of supported arguments.
* @return bool True if the meta key was successfully registered, false if not.
function register_term_meta( $taxonomy, $meta_key, array $args ) {
$args['object_subtype'] = $taxonomy;
return register_meta( 'term', $meta_key, $args );
* Unregisters a meta key for terms.
* @param string $taxonomy Taxonomy the meta key is currently registered for. Pass
* an empty string if the meta key is registered across all
* @param string $meta_key The meta key to unregister.
* @return bool True on success, false if the meta key was not previously registered.
function unregister_term_meta( $taxonomy, $meta_key ) {
return unregister_meta_key( 'term', $meta_key, $taxonomy );
* Determines whether a taxonomy term exists.
* Formerly is_term(), introduced in 2.3.0.
* For more information on this and similar theme functions, check out
* the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
* Conditional Tags} article in the Theme Developer Handbook.
* @global wpdb $wpdb WordPress database abstraction object.
* @param int|string $term The term to check. Accepts term ID, slug, or name.
* @param string $taxonomy Optional. The taxonomy name to use.
* @param int $parent Optional. ID of parent term under which to confine the exists search.
* @return mixed Returns null if the term does not exist.
* Returns the term ID if no taxonomy is specified and the term ID exists.
* Returns an array of the term ID and the term taxonomy ID if the taxonomy is specified and the pairing exists.
* Returns 0 if term ID 0 is passed to the function.
function term_exists( $term, $taxonomy = '', $parent = null ) {
$select = "SELECT term_id FROM $wpdb->terms as t WHERE ";
$tax_select = "SELECT tt.term_id, tt.term_taxonomy_id FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy as tt ON tt.term_id = t.term_id WHERE ";
$where = 't.term_id = %d';
if ( ! empty( $taxonomy ) ) {
// phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
return $wpdb->get_row( $wpdb->prepare( $tax_select . $where . ' AND tt.taxonomy = %s', $term, $taxonomy ), ARRAY_A );
return $wpdb->get_var( $wpdb->prepare( $select . $where, $term ) );
$term = trim( wp_unslash( $term ) );
$slug = sanitize_title( $term );
$else_where = 't.name = %s';
$where_fields = array( $slug );
$else_where_fields = array( $term );
$orderby = 'ORDER BY t.term_id ASC';
if ( ! empty( $taxonomy ) ) {
if ( is_numeric( $parent ) ) {
$where_fields[] = $parent;
$else_where_fields[] = $parent;
$where .= ' AND tt.parent = %d';
$else_where .= ' AND tt.parent = %d';
$where_fields[] = $taxonomy;
$else_where_fields[] = $taxonomy;
$result = $wpdb->get_row( $wpdb->prepare( "SELECT tt.term_id, tt.term_taxonomy_id FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy as tt ON tt.term_id = t.term_id WHERE $where AND tt.taxonomy = %s $orderby $limit", $where_fields ), ARRAY_A );
return $wpdb->get_row( $wpdb->prepare( "SELECT tt.term_id, tt.term_taxonomy_id FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy as tt ON tt.term_id = t.term_id WHERE $else_where AND tt.taxonomy = %s $orderby $limit", $else_where_fields ), ARRAY_A );
// phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
$result = $wpdb->get_var( $wpdb->prepare( "SELECT term_id FROM $wpdb->terms as t WHERE $where $orderby $limit", $where_fields ) );
// phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
return $wpdb->get_var( $wpdb->prepare( "SELECT term_id FROM $wpdb->terms as t WHERE $else_where $orderby $limit", $else_where_fields ) );
* Check if a term is an ancestor of another term.
* You can use either an ID or the term object for both parameters.
* @param int|object $term1 ID or object to check if this is the parent term.