>
  • }
  • /**
  • * Fires immediately before an object-term relationship is added.
  • *
  • * @since 2.9.0
  • * @since 4.7.0 Added the `$taxonomy` parameter.
  • *
  • * @param int $object_id Object ID.
  • * @param int $tt_id Term taxonomy ID.
  • * @param string $taxonomy Taxonomy slug.
  • */
  • do_action( 'add_term_relationship', $object_id, $tt_id, $taxonomy );
  • $wpdb->insert(
  • $wpdb->term_relationships,
  • array(
  • 'object_id' => $object_id,
  • 'term_taxonomy_id' => $tt_id,
  • )
  • );
  • /**
  • * Fires immediately after an object-term relationship is added.
  • *
  • * @since 2.9.0
  • * @since 4.7.0 Added the `$taxonomy` parameter.
  • *
  • * @param int $object_id Object ID.
  • * @param int $tt_id Term taxonomy ID.
  • * @param string $taxonomy Taxonomy slug.
  • */
  • do_action( 'added_term_relationship', $object_id, $tt_id, $taxonomy );
  • $new_tt_ids[] = $tt_id;
  • }
  • if ( $new_tt_ids ) {
  • wp_update_term_count( $new_tt_ids, $taxonomy );
  • }
  • if ( ! $append ) {
  • $delete_tt_ids = array_diff( $old_tt_ids, $tt_ids );
  • if ( $delete_tt_ids ) {
  • $in_delete_tt_ids = "'" . implode( "', '", $delete_tt_ids ) . "'";
  • $delete_term_ids = $wpdb->get_col( $wpdb->prepare( "SELECT tt.term_id FROM $wpdb->term_taxonomy AS tt WHERE tt.taxonomy = %s AND tt.term_taxonomy_id IN ($in_delete_tt_ids)", $taxonomy ) );
  • $delete_term_ids = array_map( 'intval', $delete_term_ids );
  • $remove = wp_remove_object_terms( $object_id, $delete_term_ids, $taxonomy );
  • if ( is_wp_error( $remove ) ) {
  • return $remove;
  • }
  • }
  • }
  • $t = get_taxonomy( $taxonomy );
  • if ( ! $append && isset( $t->sort ) && $t->sort ) {
  • $values = array();
  • $term_order = 0;
  • $final_tt_ids = wp_get_object_terms(
  • $object_id,
  • $taxonomy,
  • array(
  • 'fields' => 'tt_ids',
  • 'update_term_meta_cache' => false,
  • )
  • );
  • foreach ( $tt_ids as $tt_id ) {
  • if ( in_array( (int) $tt_id, $final_tt_ids, true ) ) {
  • $values[] = $wpdb->prepare( '(%d, %d, %d)', $object_id, $tt_id, ++$term_order );
  • }
  • }
  • if ( $values ) {
  • if ( false === $wpdb->query( "INSERT INTO $wpdb->term_relationships (object_id, term_taxonomy_id, term_order) VALUES " . implode( ',', $values ) . ' ON DUPLICATE KEY UPDATE term_order = VALUES(term_order)' ) ) {
  • return new WP_Error( 'db_insert_error', __( 'Could not insert term relationship into the database.' ), $wpdb->last_error );
  • }
  • }
  • }
  • wp_cache_delete( $object_id, $taxonomy . '_relationships' );
  • wp_cache_delete( 'last_changed', 'terms' );
  • /**
  • * Fires after an object's terms have been set.
  • *
  • * @since 2.8.0
  • *
  • * @param int $object_id Object ID.
  • * @param array $terms An array of object term IDs or slugs.
  • * @param array $tt_ids An array of term taxonomy IDs.
  • * @param string $taxonomy Taxonomy slug.
  • * @param bool $append Whether to append new terms to the old terms.
  • * @param array $old_tt_ids Old array of term taxonomy IDs.
  • */
  • do_action( 'set_object_terms', $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids );
  • return $tt_ids;
  • }
  • /**
  • * Add term(s) associated with a given object.
  • *
  • * @since 3.6.0
  • *
  • * @param int $object_id The ID of the object to which the terms will be added.
  • * @param string|int|array $terms The slug(s) or ID(s) of the term(s) to add.
  • * @param array|string $taxonomy Taxonomy name.
  • * @return array|WP_Error Term taxonomy IDs of the affected terms.
  • */
  • function wp_add_object_terms( $object_id, $terms, $taxonomy ) {
  • return wp_set_object_terms( $object_id, $terms, $taxonomy, true );
  • }
  • /**
  • * Remove term(s) associated with a given object.
  • *
  • * @since 3.6.0
  • *
  • * @global wpdb $wpdb WordPress database abstraction object.
  • *
  • * @param int $object_id The ID of the object from which the terms will be removed.
  • * @param string|int|array $terms The slug(s) or ID(s) of the term(s) to remove.
  • * @param array|string $taxonomy Taxonomy name.
  • * @return bool|WP_Error True on success, false or WP_Error on failure.
  • */
  • function wp_remove_object_terms( $object_id, $terms, $taxonomy ) {
  • global $wpdb;
  • $object_id = (int) $object_id;
  • if ( ! taxonomy_exists( $taxonomy ) ) {
  • return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy.' ) );
  • }
  • if ( ! is_array( $terms ) ) {
  • $terms = array( $terms );
  • }
  • $tt_ids = array();
  • foreach ( (array) $terms as $term ) {
  • if ( '' === trim( $term ) ) {
  • continue;
  • }
  • $term_info = term_exists( $term, $taxonomy );
  • if ( ! $term_info ) {
  • // Skip if a non-existent term ID is passed.
  • if ( is_int( $term ) ) {
  • continue;
  • }
  • }
  • if ( is_wp_error( $term_info ) ) {
  • return $term_info;
  • }
  • $tt_ids[] = $term_info['term_taxonomy_id'];
  • }
  • if ( $tt_ids ) {
  • $in_tt_ids = "'" . implode( "', '", $tt_ids ) . "'";
  • /**
  • * Fires immediately before an object-term relationship is deleted.
  • *
  • * @since 2.9.0
  • * @since 4.7.0 Added the `$taxonomy` parameter.
  • *
  • * @param int $object_id Object ID.
  • * @param array $tt_ids An array of term taxonomy IDs.
  • * @param string $taxonomy Taxonomy slug.
  • */
  • do_action( 'delete_term_relationships', $object_id, $tt_ids, $taxonomy );
  • $deleted = $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->term_relationships WHERE object_id = %d AND term_taxonomy_id IN ($in_tt_ids)", $object_id ) );
  • wp_cache_delete( $object_id, $taxonomy . '_relationships' );
  • wp_cache_delete( 'last_changed', 'terms' );
  • /**
  • * Fires immediately after an object-term relationship is deleted.
  • *
  • * @since 2.9.0
  • * @since 4.7.0 Added the `$taxonomy` parameter.
  • *
  • * @param int $object_id Object ID.
  • * @param array $tt_ids An array of term taxonomy IDs.
  • * @param string $taxonomy Taxonomy slug.
  • */
  • do_action( 'deleted_term_relationships', $object_id, $tt_ids, $taxonomy );
  • wp_update_term_count( $tt_ids, $taxonomy );
  • return (bool) $deleted;
  • }
  • return false;
  • }
  • /**
  • * Will make slug unique, if it isn't already.
  • *
  • * The `$slug` has to be unique global to every taxonomy, meaning that one
  • * taxonomy term can't have a matching slug with another taxonomy term. Each
  • * slug has to be globally unique for every taxonomy.
  • *
  • * The way this works is that if the taxonomy that the term belongs to is
  • * hierarchical and has a parent, it will append that parent to the $slug.
  • *
  • * If that still doesn't return a unique slug, then it tries to append a number
  • * until it finds a number that is truly unique.
  • *
  • * The only purpose for `$term` is for appending a parent, if one exists.
  • *
  • * @since 2.3.0
  • *
  • * @global wpdb $wpdb WordPress database abstraction object.
  • *
  • * @param string $slug The string that will be tried for a unique slug.
  • * @param object $term The term object that the `$slug` will belong to.
  • * @return string Will return a true unique slug.
  • */
  • function wp_unique_term_slug( $slug, $term ) {
  • global $wpdb;
  • $needs_suffix = true;
  • $original_slug = $slug;
  • // As of 4.1, duplicate slugs are allowed as long as they're in different taxonomies.
  • if ( ! term_exists( $slug ) || get_option( 'db_version' ) >= 30133 && ! get_term_by( 'slug', $slug, $term->taxonomy ) ) {
  • $needs_suffix = false;
  • }
  • /*
  • * If the taxonomy supports hierarchy and the term has a parent, make the slug unique
  • * by incorporating parent slugs.
  • */
  • $parent_suffix = '';
  • if ( $needs_suffix && is_taxonomy_hierarchical( $term->taxonomy ) && ! empty( $term->parent ) ) {
  • $the_parent = $term->parent;
  • while ( ! empty( $the_parent ) ) {
  • $parent_term = get_term( $the_parent, $term->taxonomy );
  • if ( is_wp_error( $parent_term ) || empty( $parent_term ) ) {
  • break;
  • }
  • $parent_suffix .= '-' . $parent_term->slug;
  • if ( ! term_exists( $slug . $parent_suffix ) ) {
  • break;
  • }
  • if ( empty( $parent_term->parent ) ) {
  • break;
  • }
  • $the_parent = $parent_term->parent;
  • }
  • }
  • // If we didn't get a unique slug, try appending a number to make it unique.
  • /**
  • * Filters whether the proposed unique term slug is bad.
  • *
  • * @since 4.3.0
  • *
  • * @param bool $needs_suffix Whether the slug needs to be made unique with a suffix.
  • * @param string $slug The slug.
  • * @param object $term Term object.
  • */
  • if ( apply_filters( 'wp_unique_term_slug_is_bad_slug', $needs_suffix, $slug, $term ) ) {
  • if ( $parent_suffix ) {
  • $slug .= $parent_suffix;
  • }
  • if ( ! empty( $term->term_id ) ) {
  • $query = $wpdb->prepare( "SELECT slug FROM $wpdb->terms WHERE slug = %s AND term_id != %d", $slug, $term->term_id );
  • } else {
  • $query = $wpdb->prepare( "SELECT slug FROM $wpdb->terms WHERE slug = %s", $slug );
  • }
  • if ( $wpdb->get_var( $query ) ) { // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
  • $num = 2;
  • do {
  • $alt_slug = $slug . "-$num";
  • $num++;
  • $slug_check = $wpdb->get_var( $wpdb->prepare( "SELECT slug FROM $wpdb->terms WHERE slug = %s", $alt_slug ) );
  • } while ( $slug_check );
  • $slug = $alt_slug;
  • }
  • }
  • /**
  • * Filters the unique term slug.
  • *
  • * @since 4.3.0
  • *
  • * @param string $slug Unique term slug.
  • * @param object $term Term object.
  • * @param string $original_slug Slug originally passed to the function for testing.
  • */
  • return apply_filters( 'wp_unique_term_slug', $slug, $term, $original_slug );
  • }
  • /**
  • * Update term based on arguments provided.
  • *
  • * The `$args` will indiscriminately override all values with the same field name.
  • * Care must be taken to not override important information need to update or
  • * update will fail (or perhaps create a new term, neither would be acceptable).
  • *
  • * Defaults will set 'alias_of', 'description', 'parent', and 'slug' if not
  • * defined in `$args` already.
  • *
  • * 'alias_of' will create a term group, if it doesn't already exist, and
  • * update it for the `$term`.
  • *
  • * If the 'slug' argument in `$args` is missing, then the 'name' will be used.
  • * If you set 'slug' and it isn't unique, then a WP_Error is returned.
  • * If you don't pass any slug, then a unique one will be created.
  • *
  • * @since 2.3.0
  • *
  • * @global wpdb $wpdb WordPress database abstraction object.
  • *
  • * @param int $term_id The ID of the term.
  • * @param string $taxonomy The taxonomy of the term.
  • * @param array|string $args {
  • * Optional. Array or string of arguments for updating a term.
  • *
  • * @type string $alias_of Slug of the term to make this term an alias of.
  • * Default empty string. Accepts a term slug.
  • * @type string $description The term description. Default empty string.
  • * @type int $parent The id of the parent term. Default 0.
  • * @type string $slug The term slug to use. Default empty string.
  • * }
  • * @return array|WP_Error An array containing the `term_id` and `term_taxonomy_id`,
  • * WP_Error otherwise.
  • */
  • function wp_update_term( $term_id, $taxonomy, $args = array() ) {
  • global $wpdb;
  • if ( ! taxonomy_exists( $taxonomy ) ) {
  • return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy.' ) );
  • }
  • $term_id = (int) $term_id;
  • // First, get all of the original args.
  • $term = get_term( $term_id, $taxonomy );
  • if ( is_wp_error( $term ) ) {
  • return $term;
  • }
  • if ( ! $term ) {
  • return new WP_Error( 'invalid_term', __( 'Empty Term.' ) );
  • }
  • $term = (array) $term->data;
  • // Escape data pulled from DB.
  • $term = wp_slash( $term );
  • // Merge old and new args with new args overwriting old ones.
  • $args = array_merge( $term, $args );
  • $defaults = array(
  • 'alias_of' => '',
  • 'description' => '',
  • 'parent' => 0,
  • 'slug' => '',
  • );
  • $args = wp_parse_args( $args, $defaults );
  • $args = sanitize_term( $args, $taxonomy, 'db' );
  • $parsed_args = $args;
  • // expected_slashed ($name)
  • $name = wp_unslash( $args['name'] );
  • $description = wp_unslash( $args['description'] );
  • $parsed_args['name'] = $name;
  • $parsed_args['description'] = $description;
  • if ( '' === trim( $name ) ) {
  • return new WP_Error( 'empty_term_name', __( 'A name is required for this term.' ) );
  • }
  • if ( (int) $parsed_args['parent'] > 0 && ! term_exists( (int) $parsed_args['parent'] ) ) {
  • return new WP_Error( 'missing_parent', __( 'Parent term does not exist.' ) );
  • }
  • $empty_slug = false;
  • if ( empty( $args['slug'] ) ) {
  • $empty_slug = true;
  • $slug = sanitize_title( $name );
  • } else {
  • $slug = $args['slug'];
  • }
  • $parsed_args['slug'] = $slug;
  • $term_group = isset( $parsed_args['term_group'] ) ? $parsed_args['term_group'] : 0;
  • if ( $args['alias_of'] ) {
  • $alias = get_term_by( 'slug', $args['alias_of'], $taxonomy );
  • if ( ! empty( $alias->term_group ) ) {
  • // The alias we want is already in a group, so let's use that one.
  • $term_group = $alias->term_group;
  • } elseif ( ! empty( $alias->term_id ) ) {
  • /*
  • * The alias is not in a group, so we create a new one
  • * and add the alias to it.
  • */
  • $term_group = $wpdb->get_var( "SELECT MAX(term_group) FROM $wpdb->terms" ) + 1;
  • wp_update_term(
  • $alias->term_id,
  • $taxonomy,
  • array(
  • 'term_group' => $term_group,
  • )
  • );
  • }
  • $parsed_args['term_group'] = $term_group;
  • }
  • /**
  • * Filters the term parent.
  • *
  • * Hook to this filter to see if it will cause a hierarchy loop.
  • *
  • * @since 3.1.0
  • *
  • * @param int $parent ID of the parent term.
  • * @param int $term_id Term ID.
  • * @param string $taxonomy Taxonomy slug.
  • * @param array $parsed_args An array of potentially altered update arguments for the given term.
  • * @param array $args An array of update arguments for the given term.
  • */
  • $parent = (int) apply_filters( 'wp_update_term_parent', $args['parent'], $term_id, $taxonomy, $parsed_args, $args );
  • // Check for duplicate slug.
  • $duplicate = get_term_by( 'slug', $slug, $taxonomy );
  • if ( $duplicate && $duplicate->term_id !== $term_id ) {
  • // If an empty slug was passed or the parent changed, reset the slug to something unique.
  • // Otherwise, bail.
  • if ( $empty_slug || ( $parent !== (int) $term['parent'] ) ) {
  • $slug = wp_unique_term_slug( $slug, (object) $args );
  • } else {
  • /* translators: %s: Taxonomy term slug. */
  • return new WP_Error( 'duplicate_term_slug', sprintf( __( 'The slug “%s” is already in use by another term.' ), $slug ) );
  • }
  • }
  • $tt_id = (int) $wpdb->get_var( $wpdb->prepare( "SELECT tt.term_taxonomy_id FROM $wpdb->term_taxonomy AS tt INNER JOIN $wpdb->terms AS t ON tt.term_id = t.term_id WHERE tt.taxonomy = %s AND t.term_id = %d", $taxonomy, $term_id ) );
  • // Check whether this is a shared term that needs splitting.
  • $_term_id = _split_shared_term( $term_id, $tt_id );
  • if ( ! is_wp_error( $_term_id ) ) {
  • $term_id = $_term_id;
  • }
  • /**
  • * Fires immediately before the given terms are edited.
  • *
  • * @since 2.9.0
  • *
  • * @param int $term_id Term ID.
  • * @param string $taxonomy Taxonomy slug.
  • */
  • do_action( 'edit_terms', $term_id, $taxonomy );
  • $data = compact( 'name', 'slug', 'term_group' );
  • /**
  • * Filters term data before it is updated in the database.
  • *
  • * @since 4.7.0
  • *
  • * @param array $data Term data to be updated.
  • * @param int $term_id Term ID.
  • * @param string $taxonomy Taxonomy slug.
  • * @param array $args Arguments passed to wp_update_term().
  • */
  • $data = apply_filters( 'wp_update_term_data', $data, $term_id, $taxonomy, $args );
  • $wpdb->update( $wpdb->terms, $data, compact( 'term_id' ) );
  • if ( empty( $slug ) ) {
  • $slug = sanitize_title( $name, $term_id );
  • $wpdb->update( $wpdb->terms, compact( 'slug' ), compact( 'term_id' ) );
  • }
  • /**
  • * Fires immediately after a term is updated in the database, but before its
  • * term-taxonomy relationship is updated.
  • *
  • * @since 2.9.0
  • *
  • * @param int $term_id Term ID
  • * @param string $taxonomy Taxonomy slug.
  • */
  • do_action( 'edited_terms', $term_id, $taxonomy );
  • /**
  • * Fires immediate before a term-taxonomy relationship is updated.
  • *
  • * @since 2.9.0
  • *
  • * @param int $tt_id Term taxonomy ID.
  • * @param string $taxonomy Taxonomy slug.
  • */
  • do_action( 'edit_term_taxonomy', $tt_id, $taxonomy );
  • $wpdb->update( $wpdb->term_taxonomy, compact( 'term_id', 'taxonomy', 'description', 'parent' ), array( 'term_taxonomy_id' => $tt_id ) );
  • /**
  • * Fires immediately after a term-taxonomy relationship is updated.
  • *
  • * @since 2.9.0
  • *
  • * @param int $tt_id Term taxonomy ID.
  • * @param string $taxonomy Taxonomy slug.
  • */
  • do_action( 'edited_term_taxonomy', $tt_id, $taxonomy );
  • /**
  • * Fires after a term has been updated, but before the term cache has been cleaned.
  • *
  • * The {@see 'edit_$taxonomy'} hook is also available for targeting a specific
  • * taxonomy.
  • *
  • * @since 2.3.0
  • *
  • * @param int $term_id Term ID.
  • * @param int $tt_id Term taxonomy ID.
  • * @param string $taxonomy Taxonomy slug.
  • */
  • do_action( 'edit_term', $term_id, $tt_id, $taxonomy );
  • /**
  • * Fires after a term in a specific taxonomy has been updated, but before the term
  • * cache has been cleaned.
  • *
  • * The dynamic portion of the hook name, `$taxonomy`, refers to the taxonomy slug.
  • *
  • * Possible hook names include:
  • *
  • * - `edit_category`
  • * - `edit_post_tag`
  • *
  • * @since 2.3.0
  • *
  • * @param int $term_id Term ID.
  • * @param int $tt_id Term taxonomy ID.
  • */
  • do_action( "edit_{$taxonomy}", $term_id, $tt_id );
  • /** This filter is documented in wp-includes/taxonomy.php */
  • $term_id = apply_filters( 'term_id_filter', $term_id, $tt_id );
  • clean_term_cache( $term_id, $taxonomy );
  • /**
  • * Fires after a term has been updated, and the term cache has been cleaned.
  • *
  • * The {@see 'edited_$taxonomy'} hook is also available for targeting a specific
  • * taxonomy.
  • *
  • * @since 2.3.0
  • *
  • * @param int $term_id Term ID.
  • * @param int $tt_id Term taxonomy ID.
  • * @param string $taxonomy Taxonomy slug.
  • */
  • do_action( 'edited_term', $term_id, $tt_id, $taxonomy );
  • /**
  • * Fires after a term for a specific taxonomy has been updated, and the term
  • * cache has been cleaned.
  • *
  • * The dynamic portion of the hook name, `$taxonomy`, refers to the taxonomy slug.
  • *
  • * Possible hook names include:
  • *
  • * - `edited_category`
  • * - `edited_post_tag`
  • *
  • * @since 2.3.0
  • *
  • * @param int $term_id Term ID.
  • * @param int $tt_id Term taxonomy ID.
  • */
  • do_action( "edited_{$taxonomy}", $term_id, $tt_id );
  • /** This action is documented in wp-includes/taxonomy.php */
  • do_action( 'saved_term', $term_id, $tt_id, $taxonomy, true );
  • /** This action is documented in wp-includes/taxonomy.php */
  • do_action( "saved_{$taxonomy}", $term_id, $tt_id, true );
  • return array(
  • 'term_id' => $term_id,
  • 'term_taxonomy_id' => $tt_id,
  • );
  • }
  • /**
  • * Enable or disable term counting.
  • *
  • * @since 2.5.0
  • *
  • * @param bool $defer Optional. Enable if true, disable if false.
  • * @return bool Whether term counting is enabled or disabled.
  • */
  • function wp_defer_term_counting( $defer = null ) {
  • static $_defer = false;
  • if ( is_bool( $defer ) ) {
  • $_defer = $defer;
  • // Flush any deferred counts.
  • if ( ! $defer ) {
  • wp_update_term_count( null, null, true );
  • }
  • }
  • return $_defer;
  • }
  • /**
  • * Updates the amount of terms in taxonomy.
  • *
  • * If there is a taxonomy callback applied, then it will be called for updating
  • * the count.
  • *
  • * The default action is to count what the amount of terms have the relationship
  • * of term ID. Once that is done, then update the database.
  • *
  • * @since 2.3.0
  • *
  • * @param int|array $terms The term_taxonomy_id of the terms.
  • * @param string $taxonomy The context of the term.
  • * @param bool $do_deferred Whether to flush the deferred term counts too. Default false.
  • * @return bool If no terms will return false, and if successful will return true.
  • */
  • function wp_update_term_count( $terms, $taxonomy, $do_deferred = false ) {
  • static $_deferred = array();
  • if ( $do_deferred ) {
  • foreach ( (array) array_keys( $_deferred ) as $tax ) {
  • wp_update_term_count_now( $_deferred[ $tax ], $tax );
  • unset( $_deferred[ $tax ] );
  • }
  • }
  • if ( empty( $terms ) ) {
  • return false;
  • }
  • if ( ! is_array( $terms ) ) {
  • $terms = array( $terms );
  • }
  • if ( wp_defer_term_counting() ) {
  • if ( ! isset( $_deferred[ $taxonomy ] ) ) {
  • $_deferred[ $taxonomy ] = array();
  • }
  • $_deferred[ $taxonomy ] = array_unique( array_merge( $_deferred[ $taxonomy ], $terms ) );
  • return true;
  • }
  • return wp_update_term_count_now( $terms, $taxonomy );
  • }
  • /**
  • * Perform term count update immediately.
  • *
  • * @since 2.5.0
  • *
  • * @param array $terms The term_taxonomy_id of terms to update.
  • * @param string $taxonomy The context of the term.
  • * @return true Always true when complete.
  • */
  • function wp_update_term_count_now( $terms, $taxonomy ) {
  • $terms = array_map( 'intval', $terms );
  • $taxonomy = get_taxonomy( $taxonomy );
  • if ( ! empty( $taxonomy->update_count_callback ) ) {
  • call_user_func( $taxonomy->update_count_callback, $terms, $taxonomy );
  • } else {
  • $object_types = (array) $taxonomy->object_type;
  • foreach ( $object_types as &$object_type ) {
  • if ( 0 === strpos( $object_type, 'attachment:' ) ) {
  • list( $object_type ) = explode( ':', $object_type );
  • }
  • }
  • if ( array_filter( $object_types, 'post_type_exists' ) == $object_types ) {
  • // Only post types are attached to this taxonomy.
  • _update_post_term_count( $terms, $taxonomy );
  • } else {
  • // Default count updater.
  • _update_generic_term_count( $terms, $taxonomy );
  • }
  • }
  • clean_term_cache( $terms, '', false );
  • return true;
  • }
  • //
  • // Cache.
  • //
  • /**
  • * Removes the taxonomy relationship to terms from the cache.
  • *
  • * Will remove the entire taxonomy relationship containing term `$object_id`. The
  • * term IDs have to exist within the taxonomy `$object_type` for the deletion to
  • * take place.
  • *
  • * @since 2.3.0
  • *
  • * @global bool $_wp_suspend_cache_invalidation
  • *
  • * @see get_object_taxonomies() for more on $object_type.
  • *
  • * @param int|array $object_ids Single or list of term object ID(s).
  • * @param array|string $object_type The taxonomy object type.
  • */
  • function clean_object_term_cache( $object_ids, $object_type ) {
  • global $_wp_suspend_cache_invalidation;
  • if ( ! empty( $_wp_suspend_cache_invalidation ) ) {
  • return;
  • }
  • if ( ! is_array( $object_ids ) ) {
  • $object_ids = array( $object_ids );
  • }
  • $taxonomies = get_object_taxonomies( $object_type );
  • foreach ( $object_ids as $id ) {
  • foreach ( $taxonomies as $taxonomy ) {
  • wp_cache_delete( $id, "{$taxonomy}_relationships" );
  • }
  • }
  • /**
  • * Fires after the object term cache has been cleaned.
  • *
  • * @since 2.5.0
  • *
  • * @param array $object_ids An array of object IDs.
  • * @param string $object_type Object type.
  • */
  • do_action( 'clean_object_term_cache', $object_ids, $object_type );
  • }
  • /**
  • * Will remove all of the term IDs from the cache.
  • *
  • * @since 2.3.0
  • *
  • * @global wpdb $wpdb WordPress database abstraction object.
  • * @global bool $_wp_suspend_cache_invalidation
  • *
  • * @param int|int[] $ids Single or array of term IDs.
  • * @param string $taxonomy Optional. Taxonomy slug. Can be empty, in which case the taxonomies of the passed
  • * term IDs will be used. Default empty.
  • * @param bool $clean_taxonomy Optional. Whether to clean taxonomy wide caches (true), or just individual
  • * term object caches (false). Default true.
  • */
  • function clean_term_cache( $ids, $taxonomy = '', $clean_taxonomy = true ) {
  • global $wpdb, $_wp_suspend_cache_invalidation;
  • if ( ! empty( $_wp_suspend_cache_invalidation ) ) {
  • return;
  • }
  • if ( ! is_array( $ids ) ) {
  • $ids = array( $ids );
  • }
  • $taxonomies = array();
  • // If no taxonomy, assume tt_ids.
  • if ( empty( $taxonomy ) ) {
  • $tt_ids = array_map( 'intval', $ids );
  • $tt_ids = implode( ', ', $tt_ids );
  • $terms = $wpdb->get_results( "SELECT term_id, taxonomy FROM $wpdb->term_taxonomy WHERE term_taxonomy_id IN ($tt_ids)" );
  • $ids = array();
  • foreach ( (array) $terms as $term ) {
  • $taxonomies[] = $term->taxonomy;
  • $ids[] = $term->term_id;
  • wp_cache_delete( $term->term_id, 'terms' );
  • }
  • $taxonomies = array_unique( $taxonomies );
  • } else {
  • $taxonomies = array( $taxonomy );
  • foreach ( $taxonomies as $taxonomy ) {
  • foreach ( $ids as $id ) {
  • wp_cache_delete( $id, 'terms' );
  • }
  • }
  • }
  • foreach ( $taxonomies as $taxonomy ) {
  • if ( $clean_taxonomy ) {
  • clean_taxonomy_cache( $taxonomy );
  • }
  • /**
  • * Fires once after each taxonomy's term cache has been cleaned.
  • *
  • * @since 2.5.0
  • * @since 4.5.0 Added the `$clean_taxonomy` parameter.
  • *
  • * @param array $ids An array of term IDs.
  • * @param string $taxonomy Taxonomy slug.
  • * @param bool $clean_taxonomy Whether or not to clean taxonomy-wide caches
  • */
  • do_action( 'clean_term_cache', $ids, $taxonomy, $clean_taxonomy );
  • }
  • wp_cache_set( 'last_changed', microtime(), 'terms' );
  • }
  • /**
  • * Clean the caches for a taxonomy.
  • *
  • * @since 4.9.0
  • *
  • * @param string $taxonomy Taxonomy slug.
  • */
  • function clean_taxonomy_cache( $taxonomy ) {
  • wp_cache_delete( 'all_ids', $taxonomy );
  • wp_cache_delete( 'get', $taxonomy );
  • // Regenerate cached hierarchy.
  • delete_option( "{$taxonomy}_children" );
  • _get_term_hierarchy( $taxonomy );
  • /**
  • * Fires after a taxonomy's caches have been cleaned.
  • *
  • * @since 4.9.0
  • *
  • * @param string $taxonomy Taxonomy slug.
  • */
  • do_action( 'clean_taxonomy_cache', $taxonomy );
  • }
  • /**
  • * Retrieves the cached term objects for the given object ID.
  • *
  • * Upstream functions (like get_the_terms() and is_object_in_term()) are
  • * responsible for populating the object-term relationship cache. The current
  • * function only fetches relationship data that is already in the cache.
  • *
  • * @since 2.3.0
  • * @since 4.7.0 Returns a `WP_Error` object if there's an error with
  • * any of the matched terms.
  • *
  • * @param int $id Term object ID, for example a post, comment, or user ID.
  • * @param string $taxonomy Taxonomy name.
  • * @return bool|WP_Term[]|WP_Error Array of `WP_Term` objects, if cached.
  • * False if cache is empty for `$taxonomy` and `$id`.
  • * WP_Error if get_term() returns an error object for any term.
  • */
  • function get_object_term_cache( $id, $taxonomy ) {
  • $_term_ids = wp_cache_get( $id, "{$taxonomy}_relationships" );
  • // We leave the priming of relationship caches to upstream functions.
  • if ( false === $_term_ids ) {
  • return false;
  • }
  • // Backward compatibility for if a plugin is putting objects into the cache, rather than IDs.
  • $term_ids = array();
  • foreach ( $_term_ids as $term_id ) {
  • if ( is_numeric( $term_id ) ) {
  • $term_ids[] = (int) $term_id;
  • } elseif ( isset( $term_id->term_id ) ) {
  • $term_ids[] = (int) $term_id->term_id;
  • }
  • }
  • // Fill the term objects.
  • _prime_term_caches( $term_ids );
  • $terms = array();
  • foreach ( $term_ids as $term_id ) {
  • $term = get_term( $term_id, $taxonomy );
  • if ( is_wp_error( $term ) ) {
  • return $term;
  • }
  • $terms[] = $term;
  • }
  • return $terms;
  • }
  • /**
  • * Updates the cache for the given term object ID(s).
  • *
  • * Note: Due to performance concerns, great care should be taken to only update
  • * term caches when necessary. Processing time can increase exponentially depending
  • * on both the number of passed term IDs and the number of taxonomies those terms
  • * belong to.
  • *
  • * Caches will only be updated for terms not already cached.
  • *
  • * @since 2.3.0
  • *
  • * @param string|int[] $object_ids Comma-separated list or array of term object IDs.
  • * @param string|string[] $object_type The taxonomy object type or array of the same.
  • * @return void|false Void on success or if the `$object_ids` parameter is empty,
  • * false if all of the terms in `$object_ids` are already cached.
  • */
  • function update_object_term_cache( $object_ids, $object_type ) {
  • if ( empty( $object_ids ) ) {
  • return;
  • }
  • if ( ! is_array( $object_ids ) ) {
  • $object_ids = explode( ',', $object_ids );
  • }
  • $object_ids = array_map( 'intval', $object_ids );
  • $non_cached_ids = array();
  • $taxonomies = get_object_taxonomies( $object_type );
  • foreach ( $taxonomies as $taxonomy ) {
  • $cache_values = wp_cache_get_multiple( (array) $object_ids, "{$taxonomy}_relationships" );
  • foreach ( $cache_values as $id => $value ) {
  • if ( false === $value ) {
  • $non_cached_ids[] = $id;
  • }
  • }
  • }
  • if ( empty( $non_cached_ids ) ) {
  • return false;
  • }
  • $non_cached_ids = array_unique( $non_cached_ids );
  • $terms = wp_get_object_terms(
  • $non_cached_ids,
  • $taxonomies,
  • array(
  • 'fields' => 'all_with_object_id',
  • 'orderby' => 'name',
  • 'update_term_meta_cache' => false,
  • )
  • );
  • $object_terms = array();
  • foreach ( (array) $terms as $term ) {
  • $object_terms[ $term->object_id ][ $term->taxonomy ][] = $term->term_id;
  • }
  • foreach ( $non_cached_ids as $id ) {
  • foreach ( $taxonomies as $taxonomy ) {
  • if ( ! isset( $object_terms[ $id ][ $taxonomy ] ) ) {
  • if ( ! isset( $object_terms[ $id ] ) ) {
  • $object_terms[ $id ] = array();
  • }
  • $object_terms[ $id ][ $taxonomy ] = array();
  • }
  • }
  • }
  • foreach ( $object_terms as $id => $value ) {
  • foreach ( $value as $taxonomy => $terms ) {
  • wp_cache_add( $id, $terms, "{$taxonomy}_relationships" );
  • }
  • }
  • }
  • /**
  • * Updates Terms to Taxonomy in cache.
  • *
  • * @since 2.3.0
  • *
  • * @param WP_Term[] $terms Array of term objects to change.
  • * @param string $taxonomy Not used.
  • */
  • function update_term_cache( $terms, $taxonomy = '' ) {
  • foreach ( (array) $terms as $term ) {
  • // Create a copy in case the array was passed by reference.
  • $_term = clone $term;
  • // Object ID should not be cached.
  • unset( $_term->object_id );
  • wp_cache_add( $term->term_id, $_term, 'terms' );
  • }
  • }
  • //
  • // Private.
  • //
  • /**
  • * Retrieves children of taxonomy as Term IDs.
  • *
  • * @access private
  • * @since 2.3.0
  • *
  • * @param string $taxonomy Taxonomy name.
  • * @return array Empty if $taxonomy isn't hierarchical or returns children as Term IDs.
  • */
  • function _get_term_hierarchy( $taxonomy ) {
  • if ( ! is_taxonomy_hierarchical( $taxonomy ) ) {
  • return array();
  • }
  • $children = get_option( "{$taxonomy}_children" );
  • if ( is_array( $children ) ) {
  • return $children;
  • }
  • $children = array();
  • $terms = get_terms(
  • array(
  • 'taxonomy' => $taxonomy,
  • 'get' => 'all',
  • 'orderby' => 'id',
  • 'fields' => 'id=>parent',
  • 'update_term_meta_cache' => false,
  • )
  • );
  • foreach ( $terms as $term_id => $parent ) {
  • if ( $parent > 0 ) {
  • $children[ $parent ][] = $term_id;
  • }
  • }
  • update_option( "{$taxonomy}_children", $children );
  • return $children;
  • }
  • /**
  • * Get the subset of $terms that are descendants of $term_id.
  • *
  • * If `$terms` is an array of objects, then _get_term_children() returns an array of objects.
  • * If `$terms` is an array of IDs, then _get_term_children() returns an array of IDs.
  • *
  • * @access private
  • * @since 2.3.0
  • *
  • * @param int $term_id The ancestor term: all returned terms should be descendants of `$term_id`.
  • * @param array $terms The set of terms - either an array of term objects or term IDs - from which those that
  • * are descendants of $term_id will be chosen.
  • * @param string $taxonomy The taxonomy which determines the hierarchy of the terms.
  • * @param array $ancestors Optional. Term ancestors that have already been identified. Passed by reference, to keep
  • * track of found terms when recursing the hierarchy. The array of located ancestors is used
  • * to prevent infinite recursion loops. For performance, `term_ids` are used as array keys,
  • * with 1 as value. Default empty array.
  • * @return array|WP_Error The subset of $terms that are descendants of $term_id.
  • */
  • function _get_term_children( $term_id, $terms, $taxonomy, &$ancestors = array() ) {
  • $empty_array = array();
  • if ( empty( $terms ) ) {
  • return $empty_array;
  • }
  • $term_id = (int) $term_id;
  • $term_list = array();
  • $has_children = _get_term_hierarchy( $taxonomy );
  • if ( $term_id && ! isset( $has_children[ $term_id ] ) ) {
  • return $empty_array;
  • }
  • // Include the term itself in the ancestors array, so we can properly detect when a loop has occurred.
  • if ( empty( $ancestors ) ) {
  • $ancestors[ $term_id ] = 1;
  • }
  • foreach ( (array) $terms as $term ) {
  • $use_id = false;
  • if ( ! is_object( $term ) ) {
  • $term = get_term( $term, $taxonomy );
  • if ( is_wp_error( $term ) ) {
  • return $term;
  • }
  • $use_id = true;
  • }
  • // Don't recurse if we've already identified the term as a child - this indicates a loop.
  • if ( isset( $ancestors[ $term->term_id ] ) ) {
  • continue;
  • }
  • if ( (int) $term->parent === $term_id ) {
  • if ( $use_id ) {
  • $term_list[] = $term->term_id;
  • } else {
  • $term_list[] = $term;
  • }
  • if ( ! isset( $has_children[ $term->term_id ] ) ) {
  • continue;
  • }
  • $ancestors[ $term->term_id ] = 1;
  • $children = _get_term_children( $term->term_id, $terms, $taxonomy, $ancestors );
  • if ( $children ) {
  • $term_list = array_merge( $term_list, $children );
  • }
  • }
  • }
  • return $term_list;
  • }
  • /**
  • * Add count of children to parent count.
  • *
  • * Recalculates term counts by including items from child terms. Assumes all
  • * relevant children are already in the $terms argument.
  • *
  • * @access private
  • * @since 2.3.0
  • *
  • * @global wpdb $wpdb WordPress database abstraction object.
  • *
  • * @param object[]|WP_Term[] $terms List of term objects (passed by reference).
  • * @param string $taxonomy Term context.
  • */
  • function _pad_term_counts( &$terms, $taxonomy ) {
  • global $wpdb;
  • // This function only works for hierarchical taxonomies like post categories.
  • if ( ! is_taxonomy_hierarchical( $taxonomy ) ) {
  • return;
  • }
  • $term_hier = _get_term_hierarchy( $taxonomy );
  • if ( empty( $term_hier ) ) {
  • return;
  • }
  • $term_items = array();
  • $terms_by_id = array();
  • $term_ids = array();
  • foreach ( (array) $terms as $key => $term ) {
  • $terms_by_id[ $term->term_id ] = & $terms[ $key ];
  • $term_ids[ $term->term_taxonomy_id ] = $term->term_id;
  • }
  • // Get the object and term IDs and stick them in a lookup table.
  • $tax_obj = get_taxonomy( $taxonomy );
  • $object_types = esc_sql( $tax_obj->object_type );
  • $results = $wpdb->get_results( "SELECT object_id, term_taxonomy_id FROM $wpdb->term_relationships INNER JOIN $wpdb->posts ON object_id = ID WHERE term_taxonomy_id IN (" . implode( ',', array_keys( $term_ids ) ) . ") AND post_type IN ('" . implode( "', '", $object_types ) . "') AND post_status = 'publish'" );
  • foreach ( $results as $row ) {
  • $id = $term_ids[ $row->term_taxonomy_id ];
  • $term_items[ $id ][ $row->object_id ] = isset( $term_items[ $id ][ $row->object_id ] ) ? ++$term_items[ $id ][ $row->object_id ] : 1;
  • }
  • // Touch every ancestor's lookup row for each post in each term.
  • foreach ( $term_ids as $term_id ) {
  • $child = $term_id;
  • $ancestors = array();
  • while ( ! empty( $terms_by_id[ $child ] ) && $parent = $terms_by_id[ $child ]->parent ) {
  • $ancestors[] = $child;
  • if ( ! empty( $term_items[ $term_id ] ) ) {
  • foreach ( $term_items[ $term_id ] as $item_id => $touches ) {
  • $term_items[ $parent ][ $item_id ] = isset( $term_items[ $parent ][ $item_id ] ) ? ++$term_items[ $parent ][ $item_id ] : 1;
  • }
  • }
  • $child = $parent;
  • if ( in_array( $parent, $ancestors, true ) ) {
  • break;
  • }
  • }
  • }
  • // Transfer the touched cells.
  • foreach ( (array) $term_items as $id => $items ) {
  • if ( isset( $terms_by_id[ $id ] ) ) {
  • $terms_by_id[ $id ]->count = count( $items );
  • }
  • }
  • }
  • /**
  • * Adds any terms from the given IDs to the cache that do not already exist in cache.
  • *
  • * @since 4.6.0
  • * @access private
  • *
  • * @global wpdb $wpdb WordPress database abstraction object.
  • *
  • * @param array $term_ids Array of term IDs.
  • * @param bool $update_meta_cache Optional. Whether to update the meta cache. Default true.
  • */
  • function _prime_term_caches( $term_ids, $update_meta_cache = true ) {
  • global $wpdb;
  • $non_cached_ids = _get_non_cached_ids( $term_ids, 'terms' );
  • if ( ! empty( $non_cached_ids ) ) {
  • $fresh_terms = $wpdb->get_results( sprintf( "SELECT t.*, tt.* FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE t.term_id IN (%s)", implode( ',', array_map( 'intval', $non_cached_ids ) ) ) );
  • update_term_cache( $fresh_terms, $update_meta_cache );
  • if ( $update_meta_cache ) {
  • update_termmeta_cache( $non_cached_ids );
  • }
  • }
  • }
  • //
  • // Default callbacks.
  • //
  • /**
  • * Will update term count based on object types of the current taxonomy.
  • *
  • * Private function for the default callback for post_tag and category
  • * taxonomies.
  • *
  • * @access private
  • * @since 2.3.0
  • *
  • * @global wpdb $wpdb WordPress database abstraction object.
  • *
  • * @param int[] $terms List of Term taxonomy IDs.
  • * @param WP_Taxonomy $taxonomy Current taxonomy object of terms.
  • */
  • function _update_post_term_count( $terms, $taxonomy ) {
  • global $wpdb;
  • $object_types = (array) $taxonomy->object_type;
  • foreach ( $object_types as &$object_type ) {
  • list( $object_type ) = explode( ':', $object_type );
  • }
  • $object_types = array_unique( $object_types );
  • $check_attachments = array_search( 'attachment', $object_types, true );
  • if ( false !== $check_attachments ) {
  • unset( $object_types[ $check_attachments ] );
  • $check_attachments = true;
  • }
  • if ( $object_types ) {
  • $object_types = esc_sql( array_filter( $object_types, 'post_type_exists' ) );
  • }
  • $post_statuses = array( 'publish' );
  • /**
  • * Filters the post statuses for updating the term count.
  • *
  • * @since 5.7.0
  • *
  • * @param string[] $post_statuses List of post statuses to include in the count. Default is 'publish'.
  • * @param WP_Taxonomy $taxonomy Current taxonomy object.
  • */
  • $post_statuses = esc_sql( apply_filters( 'update_post_term_count_statuses', $post_statuses, $taxonomy ) );
  • foreach ( (array) $terms as $term ) {
  • $count = 0;
  • // Attachments can be 'inherit' status, we need to base count off the parent's status if so.
  • if ( $check_attachments ) {
  • // phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.QuotedDynamicPlaceholderGeneration
  • $count += (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_relationships, $wpdb->posts p1 WHERE p1.ID = $wpdb->term_relationships.object_id AND ( post_status IN ('" . implode( "', '", $post_statuses ) . "') OR ( post_status = 'inherit' AND post_parent > 0 AND ( SELECT post_status FROM $wpdb->posts WHERE ID = p1.post_parent ) IN ('" . implode( "', '", $post_statuses ) . "') ) ) AND post_type = 'attachment' AND term_taxonomy_id = %d", $term ) );
  • }
  • if ( $object_types ) {
  • // phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.QuotedDynamicPlaceholderGeneration
  • $count += (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_relationships, $wpdb->posts WHERE $wpdb->posts.ID = $wpdb->term_relationships.object_id AND post_status IN ('" . implode( "', '", $post_statuses ) . "') AND post_type IN ('" . implode( "', '", $object_types ) . "') AND term_taxonomy_id = %d", $term ) );
  • }
  • /** This action is documented in wp-includes/taxonomy.php */
  • do_action( 'edit_term_taxonomy', $term, $taxonomy->name );
  • $wpdb->update( $wpdb->term_taxonomy, compact( 'count' ), array( 'term_taxonomy_id' => $term ) );
  • /** This action is documented in wp-includes/taxonomy.php */
  • do_action( 'edited_term_taxonomy', $term, $taxonomy->name );
  • }
  • }
  • /**
  • * Will update term count based on number of objects.
  • *
  • * Default callback for the 'link_category' taxonomy.
  • *
  • * @since 3.3.0
  • *
  • * @global wpdb $wpdb WordPress database abstraction object.
  • *
  • * @param int[] $terms List of term taxonomy IDs.
  • * @param WP_Taxonomy $taxonomy Current taxonomy object of terms.
  • */
  • function _update_generic_term_count( $terms, $taxonomy ) {
  • global $wpdb;
  • foreach ( (array) $terms as $term ) {
  • $count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d", $term ) );
  • /** This action is documented in wp-includes/taxonomy.php */
  • do_action( 'edit_term_taxonomy', $term, $taxonomy->name );
  • $wpdb->update( $wpdb->term_taxonomy, compact( 'count' ), array( 'term_taxonomy_id' => $term ) );
  • /** This action is documented in wp-includes/taxonomy.php */
  • do_action( 'edited_term_taxonomy', $term, $taxonomy->name );
  • }
  • }
  • /**
  • * Create a new term for a term_taxonomy item that currently shares its term
  • * with another term_taxonomy.
  • *
  • * @ignore
  • * @since 4.2.0
  • * @since 4.3.0 Introduced `$record` parameter. Also, `$term_id` and
  • * `$term_taxonomy_id` can now accept objects.
  • *
  • * @global wpdb $wpdb WordPress database abstraction object.
  • *
  • * @param int|object $term_id ID of the shared term, or the shared term object.
  • * @param int|object $term_taxonomy_id ID of the term_taxonomy item to receive a new term, or the term_taxonomy object
  • * (corresponding to a row from the term_taxonomy table).
  • * @param bool $record Whether to record data about the split term in the options table. The recording
  • * process has the potential to be resource-intensive, so during batch operations
  • * it can be beneficial to skip inline recording and do it just once, after the
  • * batch is processed. Only set this to `false` if you know what you are doing.
  • * Default: true.
  • * @return int|WP_Error When the current term does not need to be split (or cannot be split on the current
  • * database schema), `$term_id` is returned. When the term is successfully split, the
  • * new term_id is returned. A WP_Error is returned for miscellaneous errors.
  • */
  • function _split_shared_term( $term_id, $term_taxonomy_id, $record = true ) {
  • global $wpdb;
  • if ( is_object( $term_id ) ) {
  • $shared_term = $term_id;
  • $term_id = (int) $shared_term->term_id;
  • }
  • if ( is_object( $term_taxonomy_id ) ) {
  • $term_taxonomy = $term_taxonomy_id;
  • $term_taxonomy_id = (int) $term_taxonomy->term_taxonomy_id;
  • }
  • // If there are no shared term_taxonomy rows, there's nothing to do here.
  • $shared_tt_count = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_taxonomy tt WHERE tt.term_id = %d AND tt.term_taxonomy_id != %d", $term_id, $term_taxonomy_id ) );
  • if ( ! $shared_tt_count ) {
  • return $term_id;
  • }
  • /*
  • * Verify that the term_taxonomy_id passed to the function is actually associated with the term_id.
  • * If there's a mismatch, it may mean that the term is already split. Return the actual term_id from the db.
  • */
  • $check_term_id = (int) $wpdb->get_var( $wpdb->prepare( "SELECT term_id FROM $wpdb->term_taxonomy WHERE term_taxonomy_id = %d", $term_taxonomy_id ) );
  • if ( $check_term_id !== $term_id ) {
  • return $check_term_id;
  • }
  • // Pull up data about the currently shared slug, which we'll use to populate the new one.
  • if ( empty( $shared_term ) ) {
  • $shared_term = $wpdb->get_row( $wpdb->prepare( "SELECT t.* FROM $wpdb->terms t WHERE t.term_id = %d", $term_id ) );
  • }
  • $new_term_data = array(
  • 'name' => $shared_term->name,
  • 'slug' => $shared_term->slug,
  • 'term_group' => $shared_term->term_group,
  • );
  • if ( false === $wpdb->insert( $wpdb->terms, $new_term_data ) ) {
  • return new WP_Error( 'db_insert_error', __( 'Could not split shared term.' ), $wpdb->last_error );
  • }
  • $new_term_id = (int) $wpdb->insert_id;
  • // Update the existing term_taxonomy to point to the newly created term.
  • $wpdb->update(
  • $wpdb->term_taxonomy,
  • array( 'term_id' => $new_term_id ),
  • array( 'term_taxonomy_id' => $term_taxonomy_id )
  • );
  • // Reassign child terms to the new parent.
  • if ( empty( $term_taxonomy ) ) {
  • $term_taxonomy = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->term_taxonomy WHERE term_taxonomy_id = %d", $term_taxonomy_id ) );
  • }
  • $children_tt_ids = $wpdb->get_col( $wpdb->prepare( "SELECT term_taxonomy_id FROM $wpdb->term_taxonomy WHERE parent = %d AND taxonomy = %s", $term_id, $term_taxonomy->taxonomy ) );
  • if ( ! empty( $children_tt_ids ) ) {
  • foreach ( $children_tt_ids as $child_tt_id ) {
  • $wpdb->update(
  • $wpdb->term_taxonomy,
  • array( 'parent' => $new_term_id ),
  • array( 'term_taxonomy_id' => $child_tt_id )
  • );
  • clean_term_cache( (int) $child_tt_id, '', false );
  • }
  • } else {
  • // If the term has no children, we must force its taxonomy cache to be rebuilt separately.
  • clean_term_cache( $new_term_id, $term_taxonomy->taxonomy, false );
  • }
  • clean_term_cache( $term_id, $term_taxonomy->taxonomy, false );
  • /*
  • * Taxonomy cache clearing is delayed to avoid race conditions that may occur when
  • * regenerating the taxonomy's hierarchy tree.
  • */
  • $taxonomies_to_clean = array( $term_taxonomy->taxonomy );
  • // Clean the cache for term taxonomies formerly shared with the current term.
  • $shared_term_taxonomies = $wpdb->get_col( $wpdb->prepare( "SELECT taxonomy FROM $wpdb->term_taxonomy WHERE term_id = %d", $term_id ) );
  • $taxonomies_to_clean = array_merge( $taxonomies_to_clean, $shared_term_taxonomies );
  • foreach ( $taxonomies_to_clean as $taxonomy_to_clean ) {
  • clean_taxonomy_cache( $taxonomy_to_clean );
  • }
  • // Keep a record of term_ids that have been split, keyed by old term_id. See wp_get_split_term().
  • if ( $record ) {
  • $split_term_data = get_option( '_split_terms', array() );
  • if ( ! isset( $split_term_data[ $term_id ] ) ) {
  • $split_term_data[ $term_id ] = array();
  • }
  • $split_term_data[ $term_id ][ $term_taxonomy->taxonomy ] = $new_term_id;
  • update_option( '_split_terms', $split_term_data );
  • }
  • // If we've just split the final shared term, set the "finished" flag.
  • $shared_terms_exist = $wpdb->get_results(
  • "SELECT tt.term_id, t.*, count(*) as term_tt_count FROM {$wpdb->term_taxonomy} tt
  • LEFT JOIN {$wpdb->terms} t ON t.term_id = tt.term_id
  • GROUP BY t.term_id
  • HAVING term_tt_count > 1
  • LIMIT 1"
  • );
  • if ( ! $shared_terms_exist ) {
  • update_option( 'finished_splitting_shared_terms', true );
  • }
  • /**
  • * Fires after a previously shared taxonomy term is split into two separate terms.
  • *
  • * @since 4.2.0
  • *
  • * @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.
  • */
  • do_action( 'split_shared_term', $term_id, $new_term_id, $term_taxonomy_id, $term_taxonomy->taxonomy );
  • return $new_term_id;
  • }
  • /**
  • * Splits a batch of shared taxonomy terms.
  • *
  • * @since 4.3.0
  • *
  • * @global wpdb $wpdb WordPress database abstraction object.
  • */
  • function _wp_batch_split_terms() {
  • global $wpdb;
  • $lock_name = 'term_split.lock';
  • // Try to lock.
  • $lock_result = $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO `$wpdb->options` ( `option_name`, `option_value`, `autoload` ) VALUES (%s, %s, 'no') /* LOCK */", $lock_name, time() ) );
  • if ( ! $lock_result ) {
  • $lock_result = get_option( $lock_name );
  • // Bail if we were unable to create a lock, or if the existing lock is still valid.
  • if ( ! $lock_result || ( $lock_result > ( time() - HOUR_IN_SECONDS ) ) ) {
  • wp_schedule_single_event( time() + ( 5 * MINUTE_IN_SECONDS ), 'wp_split_shared_term_batch' );
  • return;
  • }
  • }
  • // Update the lock, as by this point we've definitely got a lock, just need to fire the actions.
  • update_option( $lock_name, time() );
  • // Get a list of shared terms (those with more than one associated row in term_taxonomy).
  • $shared_terms = $wpdb->get_results(
  • "SELECT tt.term_id, t.*, count(*) as term_tt_count FROM {$wpdb->term_taxonomy} tt
  • LEFT JOIN {$wpdb->terms} t ON t.term_id = tt.term_id
  • GROUP BY t.term_id
  • HAVING term_tt_count > 1
  • LIMIT 10"
  • );
  • // No more terms, we're done here.
  • if ( ! $shared_terms ) {
  • update_option( 'finished_splitting_shared_terms', true );
  • delete_option( $lock_name );
  • return;
  • }
  • // Shared terms found? We'll need to run this script again.
  • wp_schedule_single_event( time() + ( 2 * MINUTE_IN_SECONDS ), 'wp_split_shared_term_batch' );
  • // Rekey shared term array for faster lookups.
  • $_shared_terms = array();
  • foreach ( $shared_terms as $shared_term ) {
  • $term_id = (int) $shared_term->term_id;
  • $_shared_terms[ $term_id ] = $shared_term;
  • }
  • $shared_terms = $_shared_terms;
  • // Get term taxonomy data for all shared terms.
  • $shared_term_ids = implode( ',', array_keys( $shared_terms ) );
  • $shared_tts = $wpdb->get_results( "SELECT * FROM {$wpdb->term_taxonomy} WHERE `term_id` IN ({$shared_term_ids})" );
  • // Split term data recording is slow, so we do it just once, outside the loop.
  • $split_term_data = get_option( '_split_terms', array() );
  • $skipped_first_term = array();
  • $taxonomies = array();
  • foreach ( $shared_tts as $shared_tt ) {
  • $term_id = (int) $shared_tt->term_id;
  • // Don't split the first tt belonging to a given term_id.
  • if ( ! isset( $skipped_first_term[ $term_id ] ) ) {
  • $skipped_first_term[ $term_id ] = 1;
  • continue;
  • }
  • if ( ! isset( $split_term_data[ $term_id ] ) ) {
  • $split_term_data[ $term_id ] = array();
  • }
  • // Keep track of taxonomies whose hierarchies need flushing.
  • if ( ! isset( $taxonomies[ $shared_tt->taxonomy ] ) ) {
  • $taxonomies[ $shared_tt->taxonomy ] = 1;
  • }
  • // Split the term.
  • $split_term_data[ $term_id ][ $shared_tt->taxonomy ] = _split_shared_term( $shared_terms[ $term_id ], $shared_tt, false );
  • }
  • // Rebuild the cached hierarchy for each affected taxonomy.
  • foreach ( array_keys( $taxonomies ) as $tax ) {
  • delete_option( "{$tax}_children" );
  • _get_term_hierarchy( $tax );
  • }
  • update_option( '_split_terms', $split_term_data );
  • delete_option( $lock_name );
  • }
  • /**
  • * In order to avoid the _wp_batch_split_terms() job being accidentally removed,
  • * check that it's still scheduled while we haven't finished splitting terms.
  • *
  • * @ignore
  • * @since 4.3.0
  • */
  • function _wp_check_for_scheduled_split_terms() {
  • if ( ! get_option( 'finished_splitting_shared_terms' ) && ! wp_next_scheduled( 'wp_split_shared_term_batch' ) ) {
  • wp_schedule_single_event( time() + MINUTE_IN_SECONDS, 'wp_split_shared_term_batch' );
  • }
  • }
  • /**
  • * Check default categories when a term gets split to see if any of them need to be updated.
  • *
  • * @ignore
  • * @since 4.2.0
  • *
  • * @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_default_terms( $term_id, $new_term_id, $term_taxonomy_id, $taxonomy ) {
  • if ( 'category' !== $taxonomy ) {
  • return;
  • }
  • foreach ( array( 'default_category', 'default_link_category', 'default_email_category' ) as $option ) {
  • if ( (int) get_option( $option, -1 ) === $term_id ) {
  • update_option( $option, $new_term_id );
  • }
  • }
  • }
  • /**
  • * Check menu items when a term gets split to see if any of them need to be updated.
  • *
  • * @ignore
  • * @since 4.2.0
  • *
  • * @global wpdb $wpdb WordPress database abstraction object.
  • *
  • * @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_terms_in_menus( $term_id, $new_term_id, $term_taxonomy_id, $taxonomy ) {
  • global $wpdb;
  • $post_ids = $wpdb->get_col(
  • $wpdb->prepare(
  • "SELECT m1.post_id
  • 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 )",
  • $taxonomy,
  • $term_id
  • )
  • );
  • if ( $post_ids ) {
  • 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, change associations.
  • *
  • * @ignore
  • * @since 4.3.0
  • *
  • * @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 ) {
  • return;
  • }
  • // 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 );
  • }
  • /**
  • * Get data about terms that previously shared a single term_id, but have since been split.
  • *
  • * @since 4.2.0
  • *
  • * @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() );
  • $terms = array();
  • if ( isset( $split_terms[ $old_term_id ] ) ) {
  • $terms = $split_terms[ $old_term_id ];
  • }
  • return $terms;
  • }
  • /**
  • * Get the new term ID corresponding to a previously split term.
  • *
  • * @since 4.2.0
  • *
  • * @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 );
  • $term_id = false;
  • if ( isset( $split_terms[ $taxonomy ] ) ) {
  • $term_id = (int) $split_terms[ $taxonomy ];
  • }
  • return $term_id;
  • }
  • /**
  • * Determine 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.
  • *
  • * @since 4.4.0
  • *
  • * @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 ) {
  • global $wpdb;
  • if ( get_option( 'finished_splitting_shared_terms' ) ) {
  • return false;
  • }
  • $tt_count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_taxonomy WHERE term_id = %d", $term_id ) );
  • return $tt_count > 1;
  • }
  • /**
  • * Generate a permalink for a taxonomy term archive.
  • *
  • * @since 2.5.0
  • *
  • * @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 = '' ) {
  • global $wp_rewrite;
  • if ( ! is_object( $term ) ) {
  • if ( is_int( $term ) ) {
  • $term = get_term( $term, $taxonomy );
  • } else {
  • $term = get_term_by( 'slug', $term, $taxonomy );
  • }
  • }
  • if ( ! is_object( $term ) ) {
  • $term = new WP_Error( 'invalid_term', __( 'Empty Term.' ) );
  • }
  • if ( is_wp_error( $term ) ) {
  • return $term;
  • }
  • $taxonomy = $term->taxonomy;
  • $termlink = $wp_rewrite->get_extra_permastruct( $taxonomy );
  • /**
  • * Filters the permalink structure for a term before token replacement occurs.
  • *
  • * @since 4.9.0
  • *
  • * @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 );
  • $slug = $term->slug;
  • $t = get_taxonomy( $taxonomy );
  • if ( empty( $termlink ) ) {
  • if ( 'category' === $taxonomy ) {
  • $termlink = '?cat=' . $term->term_id;
  • } elseif ( $t->query_var ) {
  • $termlink = "?$t->query_var=$slug";
  • } else {
  • $termlink = "?taxonomy=$taxonomy&term=$slug";
  • }
  • $termlink = home_url( $termlink );
  • } else {
  • 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 );
  • } else {
  • $termlink = str_replace( "%$taxonomy%", $slug, $termlink );
  • }
  • $termlink = home_url( user_trailingslashit( $termlink, 'category' ) );
  • }
  • // Back compat filters.
  • if ( 'post_tag' === $taxonomy ) {
  • /**
  • * Filters the tag link.
  • *
  • * @since 2.3.0
  • * @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 1.5.0
  • * @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 );
  • }
  • /**
  • * Filters the term link.
  • *
  • * @since 2.5.0
  • *
  • * @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 );
  • }
  • /**
  • * Display 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.
  • *
  • * @since 2.5.0
  • *
  • * @param array $args {
  • * 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() ) {
  • $defaults = array(
  • 'post' => 0,
  • 'before' => '',
  • 'sep' => ' ',
  • 'after' => '',
  • );
  • $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'];
  • }
  • /**
  • * Retrieve 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.
  • *
  • * @since 2.5.0
  • *
  • * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post.
  • * @param array $args {
  • * 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
  • * linked to its archive.
  • * }
  • * @return array List of taxonomies.
  • */
  • function get_the_taxonomies( $post = 0, $args = array() ) {
  • $post = get_post( $post );
  • $args = wp_parse_args(
  • $args,
  • array(
  • /* 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>',
  • )
  • );
  • $taxonomies = array();
  • if ( ! $post ) {
  • return $taxonomies;
  • }
  • foreach ( get_object_taxonomies( $post ) as $taxonomy ) {
  • $t = (array) get_taxonomy( $taxonomy );
  • if ( empty( $t['label'] ) ) {
  • $t['label'] = $taxonomy;
  • }
  • if ( empty( $t['args'] ) ) {
  • $t['args'] = array();
  • }
  • 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'] );
  • }
  • $links = array();
  • foreach ( $terms as $term ) {
  • $links[] = wp_sprintf( $t['term_template'], esc_attr( get_term_link( $term ) ), $term->name );
  • }
  • if ( $links ) {
  • $taxonomies[ $taxonomy ] = wp_sprintf( $t['template'], $t['label'], $links, $terms );
  • }
  • }
  • return $taxonomies;
  • }
  • /**
  • * Retrieve all taxonomy names for the given post.
  • *
  • * @since 2.5.0
  • *
  • * @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 );
  • }
  • /**
  • * Determine 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.
  • *
  • * @since 2.7.0
  • *
  • * @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;
  • if ( ! $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 ) ) {
  • return $object_terms;
  • }
  • wp_cache_set( $object_id, wp_list_pluck( $object_terms, 'term_id' ), "{$taxonomy}_relationships" );
  • }
  • if ( is_wp_error( $object_terms ) ) {
  • return $object_terms;
  • }
  • if ( empty( $object_terms ) ) {
  • return false;
  • }
  • if ( empty( $terms ) ) {
  • return ( ! empty( $object_terms ) );
  • }
  • $terms = (array) $terms;
  • $ints = array_filter( $terms, 'is_int' );
  • if ( $ints ) {
  • $strs = array_diff( $terms, $ints );
  • } else {
  • $strs =& $terms;
  • }
  • 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 ) ) {
  • return true;
  • }
  • if ( $strs ) {
  • // 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 ) ) {
  • return true;
  • }
  • if ( in_array( $object_term->name, $strs, true ) ) {
  • return true;
  • }
  • if ( in_array( $object_term->slug, $strs, true ) ) {
  • return true;
  • }
  • }
  • }
  • return false;
  • }
  • /**
  • * Determine if the given object type is associated with the given taxonomy.
  • *
  • * @since 3.0.0
  • *
  • * @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 false;
  • }
  • return in_array( $taxonomy, $taxonomies, true );
  • }
  • /**
  • * Get an array of ancestor IDs for a given object.
  • *
  • * @since 3.1.0
  • * @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;
  • $ancestors = array();
  • 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 3.1.0
  • * @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.
  • *
  • * @since 3.1.0
  • *
  • * @param int $term_id Term ID.
  • * @param string $taxonomy Taxonomy name.
  • * @return int|false Parent term ID on success, false on failure.
  • */
  • function wp_get_term_taxonomy_parent_id( $term_id, $taxonomy ) {
  • $term = get_term( $term_id, $taxonomy );
  • if ( ! $term || is_wp_error( $term ) ) {
  • return false;
  • }
  • return (int) $term->parent;
  • }
  • /**
  • * Checks the given subset of the term hierarchy for hierarchy loops.
  • * Prevents loops from forming and breaks those that it finds.
  • *
  • * Attached to the {@see 'wp_update_term_parent'} filter.
  • *
  • * @since 3.1.0
  • *
  • * @param int $parent `term_id` of the parent for the term we're checking.
  • * @param int $term_id The term we're checking.
  • * @param string $taxonomy The taxonomy of the term we're checking.
  • * @return int The new parent for the term.
  • */
  • function wp_check_term_hierarchy_for_loops( $parent, $term_id, $taxonomy ) {
  • // Nothing fancy here - bail.
  • if ( ! $parent ) {
  • return 0;
  • }
  • // Can't be its own parent.
  • if ( $parent === $term_id ) {
  • return 0;
  • }
  • // Now look for larger loops.
  • $loop = wp_find_hierarchy_loop( 'wp_get_term_taxonomy_parent_id', $term_id, $parent, array( $taxonomy ) );
  • if ( ! $loop ) {
  • return $parent; // No loop.
  • }
  • // Setting $parent to the given value causes a loop.
  • if ( isset( $loop[ $term_id ] ) ) {
  • return 0;
  • }
  • // There's a loop, but it doesn't contain $term_id. Break the loop.
  • foreach ( array_keys( $loop ) as $loop_member ) {
  • wp_update_term( $loop_member, $taxonomy, array( 'parent' => 0 ) );
  • }
  • return $parent;
  • }
  • /**
  • * Determines whether a taxonomy is considered "viewable".
  • *
  • * @since 5.1.0
  • *
  • * @param string|WP_Taxonomy $taxonomy Taxonomy name or object.
  • * @return bool Whether the taxonomy should be considered viewable.
  • */
  • function is_taxonomy_viewable( $taxonomy ) {
  • if ( is_scalar( $taxonomy ) ) {
  • $taxonomy = get_taxonomy( $taxonomy );
  • if ( ! $taxonomy ) {
  • return false;
  • }
  • }
  • return $taxonomy->publicly_queryable;
  • }
  • /**
  • * Sets the last changed time for the 'terms' cache group.
  • *
  • * @since 5.0.0
  • */
  • function wp_cache_set_terms_last_changed() {
  • wp_cache_set( 'last_changed', microtime(), 'terms' );
  • }
  • /**
  • * Aborts calls to term meta if it is not supported.
  • *
  • * @since 5.0.0
  • *
  • * @param mixed $check Skip-value for whether to proceed term meta function execution.
  • * @return mixed Original value of $check, or false if term meta is not supported.
  • */
  • function wp_check_term_meta_support_prefilter( $check ) {
  • if ( get_option( 'db_version' ) < 34370 ) {
  • return false;
  • }
  • return $check;
  • }
  • tum/whitesports - Gogs: Simplico Git Service

    暂无描述

    Tum cc318a25cd template 4 年之前
    ..
    css cc318a25cd template 4 年之前
    fonts cc318a25cd template 4 年之前
    images cc318a25cd template 4 年之前
    js cc318a25cd template 4 年之前
    languages cc318a25cd template 4 年之前
    tum/shaqfindbeds - Gogs: Simplico Git Service

    Açıklama Yok

    3381 0B

    tum/whitesports - Gogs: Simplico Git Service

    1 Commits (d6fa6293d8be4c09902396507370746df847dfc4)

    Autore SHA1 Messaggio Data
      Tum d01d7cf85d first commit 4 anni fa