: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* attached to other object types, such as users.
* @type string|array $default_term {
* Default term to be used for the taxonomy.
* @type string $name Name of default term.
* @type string $slug Slug for default term. Default empty.
* @type string $description Description for default term. Default empty.
* @type bool $sort Whether terms in this taxonomy should be sorted in the order they are
* provided to `wp_set_object_terms()`. Default null which equates to false.
* @type array $args Array of arguments to automatically use inside `wp_get_object_terms()`
* @type bool $_builtin This taxonomy is a "built-in" taxonomy. INTERNAL USE ONLY!
* @return WP_Taxonomy|WP_Error The registered taxonomy object on success, WP_Error object on failure.
function register_taxonomy( $taxonomy, $object_type, $args = array() ) {
if ( ! is_array( $wp_taxonomies ) ) {
$wp_taxonomies = array();
$args = wp_parse_args( $args );
if ( empty( $taxonomy ) || strlen( $taxonomy ) > 32 ) {
_doing_it_wrong( __FUNCTION__, __( 'Taxonomy names must be between 1 and 32 characters in length.' ), '4.2.0' );
return new WP_Error( 'taxonomy_length_invalid', __( 'Taxonomy names must be between 1 and 32 characters in length.' ) );
$taxonomy_object = new WP_Taxonomy( $taxonomy, $object_type, $args );
$taxonomy_object->add_rewrite_rules();
$wp_taxonomies[ $taxonomy ] = $taxonomy_object;
$taxonomy_object->add_hooks();
if ( ! empty( $taxonomy_object->default_term ) ) {
$term = term_exists( $taxonomy_object->default_term['name'], $taxonomy );
update_option( 'default_term_' . $taxonomy_object->name, $term['term_id'] );
$taxonomy_object->default_term['name'],
'slug' => sanitize_title( $taxonomy_object->default_term['slug'] ),
'description' => $taxonomy_object->default_term['description'],
// Update `term_id` in options.
if ( ! is_wp_error( $term ) ) {
update_option( 'default_term_' . $taxonomy_object->name, $term['term_id'] );
* Fires after a taxonomy is registered.
* @param string $taxonomy Taxonomy slug.
* @param array|string $object_type Object type or array of object types.
* @param array $args Array of taxonomy registration arguments.
do_action( 'registered_taxonomy', $taxonomy, $object_type, (array) $taxonomy_object );
* Fires after a specific taxonomy is registered.
* The dynamic portion of the filter name, `$taxonomy`, refers to the taxonomy key.
* Possible hook names include:
* - `registered_taxonomy_category`
* - `registered_taxonomy_post_tag`
* @param string $taxonomy Taxonomy slug.
* @param array|string $object_type Object type or array of object types.
* @param array $args Array of taxonomy registration arguments.
do_action( "registered_taxonomy_{$taxonomy}", $taxonomy, $object_type, (array) $taxonomy_object );
* Unregisters a taxonomy.
* Can not be used to unregister built-in taxonomies.
* @global WP_Taxonomy[] $wp_taxonomies List of taxonomies.
* @param string $taxonomy Taxonomy name.
* @return true|WP_Error True on success, WP_Error on failure or if the taxonomy doesn't exist.
function unregister_taxonomy( $taxonomy ) {
if ( ! taxonomy_exists( $taxonomy ) ) {
return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy.' ) );
$taxonomy_object = get_taxonomy( $taxonomy );
// Do not allow unregistering internal taxonomies.
if ( $taxonomy_object->_builtin ) {
return new WP_Error( 'invalid_taxonomy', __( 'Unregistering a built-in taxonomy is not allowed.' ) );
$taxonomy_object->remove_rewrite_rules();
$taxonomy_object->remove_hooks();
unset( $wp_taxonomies[ $taxonomy ] );
* Fires after a taxonomy is unregistered.
* @param string $taxonomy Taxonomy name.
do_action( 'unregistered_taxonomy', $taxonomy );
* Builds an object with all taxonomy labels out of a taxonomy object.
* @since 4.3.0 Added the `no_terms` label.
* @since 4.4.0 Added the `items_list_navigation` and `items_list` labels.
* @since 4.9.0 Added the `most_used` and `back_to_items` labels.
* @since 5.7.0 Added the `filter_by_item` label.
* @since 5.8.0 Added the `item_link` and `item_link_description` labels.
* @since 5.9.0 Added the `name_field_description`, `slug_field_description`,
* `parent_field_description`, and `desc_field_description` labels.
* @since 6.6.0 Added the `template_name` label.
* @param WP_Taxonomy $tax Taxonomy object.
* Taxonomy labels object. The first default value is for non-hierarchical taxonomies
* (like tags) and the second one is for hierarchical taxonomies (like categories).
* @type string $name General name for the taxonomy, usually plural. The same
* as and overridden by `$tax->label`. Default 'Tags'/'Categories'.
* @type string $singular_name Name for one object of this taxonomy. Default 'Tag'/'Category'.
* @type string $search_items Default 'Search Tags'/'Search Categories'.
* @type string $popular_items This label is only used for non-hierarchical taxonomies.
* Default 'Popular Tags'.
* @type string $all_items Default 'All Tags'/'All Categories'.
* @type string $parent_item This label is only used for hierarchical taxonomies. Default
* @type string $parent_item_colon The same as `parent_item`, but with colon `:` in the end.
* @type string $name_field_description Description for the Name field on Edit Tags screen.
* Default 'The name is how it appears on your site'.
* @type string $slug_field_description Description for the Slug field on Edit Tags screen.
* Default 'The “slug” is the URL-friendly version
* of the name. It is usually all lowercase and contains
* only letters, numbers, and hyphens'.
* @type string $parent_field_description Description for the Parent field on Edit Tags screen.
* Default 'Assign a parent term to create a hierarchy.
* The term Jazz, for example, would be the parent
* of Bebop and Big Band'.
* @type string $desc_field_description Description for the Description field on Edit Tags screen.
* Default 'The description is not prominent by default;
* however, some themes may show it'.
* @type string $edit_item Default 'Edit Tag'/'Edit Category'.
* @type string $view_item Default 'View Tag'/'View Category'.
* @type string $update_item Default 'Update Tag'/'Update Category'.
* @type string $add_new_item Default 'Add New Tag'/'Add New Category'.
* @type string $new_item_name Default 'New Tag Name'/'New Category Name'.
* @type string $template_name Default 'Tag Archives'/'Category Archives'.
* @type string $separate_items_with_commas This label is only used for non-hierarchical taxonomies. Default
* 'Separate tags with commas', used in the meta box.
* @type string $add_or_remove_items This label is only used for non-hierarchical taxonomies. Default
* 'Add or remove tags', used in the meta box when JavaScript
* @type string $choose_from_most_used This label is only used on non-hierarchical taxonomies. Default
* 'Choose from the most used tags', used in the meta box.
* @type string $not_found Default 'No tags found'/'No categories found', used in
* the meta box and taxonomy list table.
* @type string $no_terms Default 'No tags'/'No categories', used in the posts and media
* @type string $filter_by_item This label is only used for hierarchical taxonomies. Default
* 'Filter by category', used in the posts list table.
* @type string $items_list_navigation Label for the table pagination hidden heading.
* @type string $items_list Label for the table hidden heading.
* @type string $most_used Title for the Most Used tab. Default 'Most Used'.
* @type string $back_to_items Label displayed after a term has been updated.
* @type string $item_link Used in the block editor. Title for a navigation link block variation.
* Default 'Tag Link'/'Category Link'.
* @type string $item_link_description Used in the block editor. Description for a navigation link block
* variation. Default 'A link to a tag'/'A link to a category'.
function get_taxonomy_labels( $tax ) {
$tax->labels = (array) $tax->labels;
if ( isset( $tax->helps ) && empty( $tax->labels['separate_items_with_commas'] ) ) {
$tax->labels['separate_items_with_commas'] = $tax->helps;
if ( isset( $tax->no_tagcloud ) && empty( $tax->labels['not_found'] ) ) {
$tax->labels['not_found'] = $tax->no_tagcloud;
$nohier_vs_hier_defaults = WP_Taxonomy::get_default_labels();
$nohier_vs_hier_defaults['menu_name'] = $nohier_vs_hier_defaults['name'];
$labels = _get_custom_object_labels( $tax, $nohier_vs_hier_defaults );
if ( ! isset( $tax->labels->template_name ) && isset( $labels->singular_name ) ) {
/* translators: %s: Taxonomy name. */
$labels->template_name = sprintf( _x( '%s Archives', 'taxonomy template name' ), $labels->singular_name );
$default_labels = clone $labels;
* Filters the labels of a specific taxonomy.
* The dynamic portion of the hook name, `$taxonomy`, refers to the taxonomy slug.
* Possible hook names include:
* - `taxonomy_labels_category`
* - `taxonomy_labels_post_tag`
* @see get_taxonomy_labels() for the full list of taxonomy labels.
* @param object $labels Object with labels for the taxonomy as member variables.
$labels = apply_filters( "taxonomy_labels_{$taxonomy}", $labels );
// Ensure that the filtered labels contain all required default values.
$labels = (object) array_merge( (array) $default_labels, (array) $labels );
* Adds an already registered taxonomy to an object type.
* @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies.
* @param string $taxonomy Name of taxonomy object.
* @param string $object_type Name of the object type.
* @return bool True if successful, false if not.
function register_taxonomy_for_object_type( $taxonomy, $object_type ) {
if ( ! isset( $wp_taxonomies[ $taxonomy ] ) ) {
if ( ! get_post_type_object( $object_type ) ) {
if ( ! in_array( $object_type, $wp_taxonomies[ $taxonomy ]->object_type, true ) ) {
$wp_taxonomies[ $taxonomy ]->object_type[] = $object_type;
$wp_taxonomies[ $taxonomy ]->object_type = array_filter( $wp_taxonomies[ $taxonomy ]->object_type );
* Fires after a taxonomy is registered for an object type.
* @param string $taxonomy Taxonomy name.
* @param string $object_type Name of the object type.
do_action( 'registered_taxonomy_for_object_type', $taxonomy, $object_type );
* Removes an already registered taxonomy from an object type.
* @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies.
* @param string $taxonomy Name of taxonomy object.
* @param string $object_type Name of the object type.
* @return bool True if successful, false if not.
function unregister_taxonomy_for_object_type( $taxonomy, $object_type ) {
if ( ! isset( $wp_taxonomies[ $taxonomy ] ) ) {
if ( ! get_post_type_object( $object_type ) ) {
$key = array_search( $object_type, $wp_taxonomies[ $taxonomy ]->object_type, true );
unset( $wp_taxonomies[ $taxonomy ]->object_type[ $key ] );
* Fires after a taxonomy is unregistered for an object type.
* @param string $taxonomy Taxonomy name.
* @param string $object_type Name of the object type.
do_action( 'unregistered_taxonomy_for_object_type', $taxonomy, $object_type );
* Retrieves object IDs of valid taxonomy and term.
* The strings of `$taxonomies` must exist before this function will continue.
* On failure of finding a valid taxonomy, it will return a WP_Error.
* The `$terms` aren't checked the same as `$taxonomies`, but still need to exist
* for object IDs to be returned.
* It is possible to change the order that object IDs are returned by using `$args`
* with either ASC or DESC array. The value should be in the key named 'order'.
* @global wpdb $wpdb WordPress database abstraction object.
* @param int|int[] $term_ids Term ID or array of term IDs of terms that will be used.
* @param string|string[] $taxonomies String of taxonomy name or Array of string values of taxonomy names.
* @param array|string $args {
* Change the order of the object IDs.
* @type string $order Order to retrieve terms. Accepts 'ASC' or 'DESC'. Default 'ASC'.
* @return string[]|WP_Error An array of object IDs as numeric strings on success,
* WP_Error if the taxonomy does not exist.
function get_objects_in_term( $term_ids, $taxonomies, $args = array() ) {
if ( ! is_array( $term_ids ) ) {
$term_ids = array( $term_ids );
if ( ! is_array( $taxonomies ) ) {
$taxonomies = array( $taxonomies );
foreach ( (array) $taxonomies as $taxonomy ) {
if ( ! taxonomy_exists( $taxonomy ) ) {
return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy.' ) );
$defaults = array( 'order' => 'ASC' );
$args = wp_parse_args( $args, $defaults );
$order = ( 'desc' === strtolower( $args['order'] ) ) ? 'DESC' : 'ASC';
$term_ids = array_map( 'intval', $term_ids );
$taxonomies = "'" . implode( "', '", array_map( 'esc_sql', $taxonomies ) ) . "'";
$term_ids = "'" . implode( "', '", $term_ids ) . "'";
$sql = "SELECT tr.object_id FROM $wpdb->term_relationships AS tr INNER JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ($taxonomies) AND tt.term_id IN ($term_ids) ORDER BY tr.object_id $order";
$last_changed = wp_cache_get_last_changed( 'terms' );
$cache_key = 'get_objects_in_term:' . md5( $sql ) . ":$last_changed";
$cache = wp_cache_get( $cache_key, 'term-queries' );
if ( false === $cache ) {
$object_ids = $wpdb->get_col( $sql );
wp_cache_set( $cache_key, $object_ids, 'term-queries' );
$object_ids = (array) $cache;
* Given a taxonomy query, generates SQL to be appended to a main query.
* @param array $tax_query A compact tax query
* @param string $primary_table
* @param string $primary_id_column
function get_tax_sql( $tax_query, $primary_table, $primary_id_column ) {
$tax_query_obj = new WP_Tax_Query( $tax_query );
return $tax_query_obj->get_sql( $primary_table, $primary_id_column );
* Gets all term data from database by term ID.
* The usage of the get_term function is to apply filters to a term object. It
* is possible to get a term object from the database before applying the
* $term ID must be part of $taxonomy, to get from the database. Failure, might
* be able to be captured by the hooks. Failure would be the same value as $wpdb
* returns for the get_row method.
* There are two hooks, one is specifically for each term, named 'get_term', and
* the second is for the taxonomy name, 'term_$taxonomy'. Both hooks gets the
* term object, and the taxonomy name as parameters. Both hooks are expected to
* {@see 'get_term'} hook - Takes two parameters the term Object and the taxonomy name.
* Must return term object. Used in get_term() as a catch-all filter for every
* {@see 'get_$taxonomy'} hook - Takes two parameters the term Object and the taxonomy
* name. Must return term object. $taxonomy will be the taxonomy name, so for
* example, if 'category', it would be 'get_category' as the filter name. Useful
* for custom taxonomies or plugging into default taxonomies.
* @todo Better formatting for DocBlock
* @since 4.4.0 Converted to return a WP_Term object if `$output` is `OBJECT`.
* The `$taxonomy` parameter was made optional.
* @see sanitize_term_field() The $context param lists the available values for get_term_by() $filter param.
* @param int|WP_Term|object $term If integer, term data will be fetched from the database,
* or from the cache if available.
* If stdClass object (as in the results of a database query),
* will apply filters and return a `WP_Term` object with the `$term` data.
* If `WP_Term`, will return `$term`.
* @param string $taxonomy Optional. Taxonomy name that `$term` is part of.
* @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which
* correspond to a WP_Term object, an associative array, or a numeric array,
* respectively. Default OBJECT.
* @param string $filter Optional. How to sanitize term fields. Default 'raw'.
* @return WP_Term|array|WP_Error|null WP_Term instance (or array) on success, depending on the `$output` value.
* WP_Error if `$taxonomy` does not exist. Null for miscellaneous failure.
function get_term( $term, $taxonomy = '', $output = OBJECT, $filter = 'raw' ) {
return new WP_Error( 'invalid_term', __( 'Empty Term.' ) );
if ( $taxonomy && ! taxonomy_exists( $taxonomy ) ) {
return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy.' ) );
if ( $term instanceof WP_Term ) {
} elseif ( is_object( $term ) ) {
if ( empty( $term->filter ) || 'raw' === $term->filter ) {
$_term = sanitize_term( $term, $taxonomy, 'raw' );
$_term = new WP_Term( $_term );
$_term = WP_Term::get_instance( $term->term_id );
$_term = WP_Term::get_instance( $term, $taxonomy );
if ( is_wp_error( $_term ) ) {