: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* @param int $new_term_id ID of the new term created for the $term_taxonomy_id.
* @param int $term_taxonomy_id ID for the term_taxonomy row affected by the split.
* @param string $taxonomy Taxonomy for the split term.
function _wp_check_split_terms_in_menus( $term_id, $new_term_id, $term_taxonomy_id, $taxonomy ) {
$post_ids = $wpdb->get_col(
FROM {$wpdb->postmeta} AS m1
INNER JOIN {$wpdb->postmeta} AS m2 ON ( m2.post_id = m1.post_id )
INNER JOIN {$wpdb->postmeta} AS m3 ON ( m3.post_id = m1.post_id )
WHERE ( m1.meta_key = '_menu_item_type' AND m1.meta_value = 'taxonomy' )
AND ( m2.meta_key = '_menu_item_object' AND m2.meta_value = %s )
AND ( m3.meta_key = '_menu_item_object_id' AND m3.meta_value = %d )",
foreach ( $post_ids as $post_id ) {
update_post_meta( $post_id, '_menu_item_object_id', $new_term_id, $term_id );
* If the term being split is a nav_menu, changes associations.
* @param int $term_id ID of the formerly shared term.
* @param int $new_term_id ID of the new term created for the $term_taxonomy_id.
* @param int $term_taxonomy_id ID for the term_taxonomy row affected by the split.
* @param string $taxonomy Taxonomy for the split term.
function _wp_check_split_nav_menu_terms( $term_id, $new_term_id, $term_taxonomy_id, $taxonomy ) {
if ( 'nav_menu' !== $taxonomy ) {
// Update menu locations.
$locations = get_nav_menu_locations();
foreach ( $locations as $location => $menu_id ) {
if ( $term_id === $menu_id ) {
$locations[ $location ] = $new_term_id;
set_theme_mod( 'nav_menu_locations', $locations );
* Gets data about terms that previously shared a single term_id, but have since been split.
* @param int $old_term_id Term ID. This is the old, pre-split term ID.
* @return array Array of new term IDs, keyed by taxonomy.
function wp_get_split_terms( $old_term_id ) {
$split_terms = get_option( '_split_terms', array() );
if ( isset( $split_terms[ $old_term_id ] ) ) {
$terms = $split_terms[ $old_term_id ];
* Gets the new term ID corresponding to a previously split term.
* @param int $old_term_id Term ID. This is the old, pre-split term ID.
* @param string $taxonomy Taxonomy that the term belongs to.
* @return int|false If a previously split term is found corresponding to the old term_id and taxonomy,
* the new term_id will be returned. If no previously split term is found matching
* the parameters, returns false.
function wp_get_split_term( $old_term_id, $taxonomy ) {
$split_terms = wp_get_split_terms( $old_term_id );
if ( isset( $split_terms[ $taxonomy ] ) ) {
$term_id = (int) $split_terms[ $taxonomy ];
* Determines whether a term is shared between multiple taxonomies.
* Shared taxonomy terms began to be split in 4.3, but failed cron tasks or
* other delays in upgrade routines may cause shared terms to remain.
* @global wpdb $wpdb WordPress database abstraction object.
* @param int $term_id Term ID.
* @return bool Returns false if a term is not shared between multiple taxonomies or
* if splitting shared taxonomy terms is finished.
function wp_term_is_shared( $term_id ) {
if ( get_option( 'finished_splitting_shared_terms' ) ) {
$tt_count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_taxonomy WHERE term_id = %d", $term_id ) );
* Generates a permalink for a taxonomy term archive.
* @global WP_Rewrite $wp_rewrite WordPress rewrite component.
* @param WP_Term|int|string $term The term object, ID, or slug whose link will be retrieved.
* @param string $taxonomy Optional. Taxonomy. Default empty.
* @return string|WP_Error URL of the taxonomy term archive on success, WP_Error if term does not exist.
function get_term_link( $term, $taxonomy = '' ) {
if ( ! is_object( $term ) ) {
$term = get_term( $term, $taxonomy );
$term = get_term_by( 'slug', $term, $taxonomy );
if ( ! is_object( $term ) ) {
$term = new WP_Error( 'invalid_term', __( 'Empty Term.' ) );
if ( is_wp_error( $term ) ) {
$taxonomy = $term->taxonomy;
$termlink = $wp_rewrite->get_extra_permastruct( $taxonomy );
* Filters the permalink structure for a term before token replacement occurs.
* @param string $termlink The permalink structure for the term's taxonomy.
* @param WP_Term $term The term object.
$termlink = apply_filters( 'pre_term_link', $termlink, $term );
$t = get_taxonomy( $taxonomy );
if ( empty( $termlink ) ) {
if ( 'category' === $taxonomy ) {
$termlink = '?cat=' . $term->term_id;
} elseif ( $t->query_var ) {
$termlink = "?$t->query_var=$slug";
$termlink = "?taxonomy=$taxonomy&term=$slug";
$termlink = home_url( $termlink );
if ( ! empty( $t->rewrite['hierarchical'] ) ) {
$hierarchical_slugs = array();
$ancestors = get_ancestors( $term->term_id, $taxonomy, 'taxonomy' );
foreach ( (array) $ancestors as $ancestor ) {
$ancestor_term = get_term( $ancestor, $taxonomy );
$hierarchical_slugs[] = $ancestor_term->slug;
$hierarchical_slugs = array_reverse( $hierarchical_slugs );
$hierarchical_slugs[] = $slug;
$termlink = str_replace( "%$taxonomy%", implode( '/', $hierarchical_slugs ), $termlink );
$termlink = str_replace( "%$taxonomy%", $slug, $termlink );
$termlink = home_url( user_trailingslashit( $termlink, 'category' ) );
if ( 'post_tag' === $taxonomy ) {
* @since 2.5.0 Deprecated in favor of {@see 'term_link'} filter.
* @since 5.4.1 Restored (un-deprecated).
* @param string $termlink Tag link URL.
* @param int $term_id Term ID.
$termlink = apply_filters( 'tag_link', $termlink, $term->term_id );
} elseif ( 'category' === $taxonomy ) {
* Filters the category link.
* @since 2.5.0 Deprecated in favor of {@see 'term_link'} filter.
* @since 5.4.1 Restored (un-deprecated).
* @param string $termlink Category link URL.
* @param int $term_id Term ID.
$termlink = apply_filters( 'category_link', $termlink, $term->term_id );
* @param string $termlink Term link URL.
* @param WP_Term $term Term object.
* @param string $taxonomy Taxonomy slug.
return apply_filters( 'term_link', $termlink, $term, $taxonomy );
* Displays the taxonomies of a post with available options.
* This function can be used within the loop to display the taxonomies for a
* post without specifying the Post ID. You can also use it outside the Loop to
* display the taxonomies for a specific post.
* Arguments about which post to use and how to format the output. Shares all of the arguments
* supported by get_the_taxonomies(), in addition to the following.
* @type int|WP_Post $post Post ID or object to get taxonomies of. Default current post.
* @type string $before Displays before the taxonomies. Default empty string.
* @type string $sep Separates each taxonomy. Default is a space.
* @type string $after Displays after the taxonomies. Default empty string.
function the_taxonomies( $args = array() ) {
$parsed_args = wp_parse_args( $args, $defaults );
echo $parsed_args['before'] . implode( $parsed_args['sep'], get_the_taxonomies( $parsed_args['post'], $parsed_args ) ) . $parsed_args['after'];
* Retrieves all taxonomies associated with a post.
* This function can be used within the loop. It will also return an array of
* the taxonomies with links to the taxonomy and name.
* @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post.
* Optional. Arguments about how to format the list of taxonomies. Default empty array.
* @type string $template Template for displaying a taxonomy label and list of terms.
* Default is "Label: Terms."
* @type string $term_template Template for displaying a single term in the list. Default is the term name
* @return string[] List of taxonomies.
function get_the_taxonomies( $post = 0, $args = array() ) {
$post = get_post( $post );
/* translators: %s: Taxonomy label, %l: List of terms formatted as per $term_template. */
'template' => __( '%s: %l.' ),
'term_template' => '<a href="%1$s">%2$s</a>',
foreach ( get_object_taxonomies( $post ) as $taxonomy ) {
$t = (array) get_taxonomy( $taxonomy );
if ( empty( $t['label'] ) ) {
if ( empty( $t['args'] ) ) {
if ( empty( $t['template'] ) ) {
$t['template'] = $args['template'];
if ( empty( $t['term_template'] ) ) {
$t['term_template'] = $args['term_template'];
$terms = get_object_term_cache( $post->ID, $taxonomy );
if ( false === $terms ) {
$terms = wp_get_object_terms( $post->ID, $taxonomy, $t['args'] );
foreach ( $terms as $term ) {
$links[] = wp_sprintf( $t['term_template'], esc_attr( get_term_link( $term ) ), $term->name );
$taxonomies[ $taxonomy ] = wp_sprintf( $t['template'], $t['label'], $links, $terms );
* Retrieves all taxonomy names for the given post.
* @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post.
* @return string[] An array of all taxonomy names for the given post.
function get_post_taxonomies( $post = 0 ) {
$post = get_post( $post );
return get_object_taxonomies( $post );
* Determines if the given object is associated with any of the given terms.
* The given terms are checked against the object's terms' term_ids, names and slugs.
* Terms given as integers will only be checked against the object's terms' term_ids.
* If no terms are given, determines if object is associated with any terms in the given taxonomy.
* @param int $object_id ID of the object (post ID, link ID, ...).
* @param string $taxonomy Single taxonomy name.
* @param int|string|int[]|string[] $terms Optional. Term ID, name, slug, or array of such
* to check against. Default null.
* @return bool|WP_Error WP_Error on input error.
function is_object_in_term( $object_id, $taxonomy, $terms = null ) {
$object_id = (int) $object_id;
return new WP_Error( 'invalid_object', __( 'Invalid object ID.' ) );
$object_terms = get_object_term_cache( $object_id, $taxonomy );
if ( false === $object_terms ) {
$object_terms = wp_get_object_terms( $object_id, $taxonomy, array( 'update_term_meta_cache' => false ) );
if ( is_wp_error( $object_terms ) ) {
wp_cache_set( $object_id, wp_list_pluck( $object_terms, 'term_id' ), "{$taxonomy}_relationships" );
if ( is_wp_error( $object_terms ) ) {
if ( empty( $object_terms ) ) {
return ( ! empty( $object_terms ) );
$ints = array_filter( $terms, 'is_int' );
$strs = array_diff( $terms, $ints );
foreach ( $object_terms as $object_term ) {
// If term is an int, check against term_ids only.
if ( $ints && in_array( $object_term->term_id, $ints, true ) ) {
// Only check numeric strings against term_id, to avoid false matches due to type juggling.
$numeric_strs = array_map( 'intval', array_filter( $strs, 'is_numeric' ) );
if ( in_array( $object_term->term_id, $numeric_strs, true ) ) {
if ( in_array( $object_term->name, $strs, true ) ) {
if ( in_array( $object_term->slug, $strs, true ) ) {
* Determines if the given object type is associated with the given taxonomy.
* @param string $object_type Object type string.
* @param string $taxonomy Single taxonomy name.
* @return bool True if object is associated with the taxonomy, otherwise false.
function is_object_in_taxonomy( $object_type, $taxonomy ) {
$taxonomies = get_object_taxonomies( $object_type );
if ( empty( $taxonomies ) ) {
return in_array( $taxonomy, $taxonomies, true );
* Gets an array of ancestor IDs for a given object.
* @since 4.1.0 Introduced the `$resource_type` argument.
* @param int $object_id Optional. The ID of the object. Default 0.
* @param string $object_type Optional. The type of object for which we'll be retrieving
* ancestors. Accepts a post type or a taxonomy name. Default empty.
* @param string $resource_type Optional. Type of resource $object_type is. Accepts 'post_type'
* or 'taxonomy'. Default empty.
* @return int[] An array of IDs of ancestors from lowest to highest in the hierarchy.
function get_ancestors( $object_id = 0, $object_type = '', $resource_type = '' ) {
$object_id = (int) $object_id;
if ( empty( $object_id ) ) {
/** This filter is documented in wp-includes/taxonomy.php */
return apply_filters( 'get_ancestors', $ancestors, $object_id, $object_type, $resource_type );
if ( ! $resource_type ) {
if ( is_taxonomy_hierarchical( $object_type ) ) {
$resource_type = 'taxonomy';
} elseif ( post_type_exists( $object_type ) ) {
$resource_type = 'post_type';
if ( 'taxonomy' === $resource_type ) {
$term = get_term( $object_id, $object_type );
while ( ! is_wp_error( $term ) && ! empty( $term->parent ) && ! in_array( $term->parent, $ancestors, true ) ) {
$ancestors[] = (int) $term->parent;
$term = get_term( $term->parent, $object_type );
} elseif ( 'post_type' === $resource_type ) {
$ancestors = get_post_ancestors( $object_id );
* Filters a given object's ancestors.
* @since 4.1.1 Introduced the `$resource_type` parameter.
* @param int[] $ancestors An array of IDs of object ancestors.
* @param int $object_id Object ID.
* @param string $object_type Type of object.
* @param string $resource_type Type of resource $object_type is.
return apply_filters( 'get_ancestors', $ancestors, $object_id, $object_type, $resource_type );
* Returns the term's parent's term ID.