wp/wp-includes/taxonomy.php
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
child 22 8c2e4d02f4ef
equal deleted inserted replaced
20:7b1b88e27a20 21:48c4eec2b7e6
   220 			'_builtin'          => true,
   220 			'_builtin'          => true,
   221 			'show_in_nav_menus' => false,
   221 			'show_in_nav_menus' => false,
   222 			'show_in_rest'      => false,
   222 			'show_in_rest'      => false,
   223 		)
   223 		)
   224 	);
   224 	);
       
   225 
       
   226 	register_taxonomy(
       
   227 		'wp_pattern_category',
       
   228 		array( 'wp_block' ),
       
   229 		array(
       
   230 			'public'             => false,
       
   231 			'publicly_queryable' => false,
       
   232 			'hierarchical'       => false,
       
   233 			'labels'             => array(
       
   234 				'name'                       => _x( 'Pattern Categories', 'taxonomy general name' ),
       
   235 				'singular_name'              => _x( 'Pattern Category', 'taxonomy singular name' ),
       
   236 				'add_new_item'               => __( 'Add New Category' ),
       
   237 				'add_or_remove_items'        => __( 'Add or remove pattern categories' ),
       
   238 				'back_to_items'              => __( '← Go to Pattern Categories' ),
       
   239 				'choose_from_most_used'      => __( 'Choose from the most used pattern categories' ),
       
   240 				'edit_item'                  => __( 'Edit Pattern Category' ),
       
   241 				'item_link'                  => __( 'Pattern Category Link' ),
       
   242 				'item_link_description'      => __( 'A link to a pattern category.' ),
       
   243 				'items_list'                 => __( 'Pattern Categories list' ),
       
   244 				'items_list_navigation'      => __( 'Pattern Categories list navigation' ),
       
   245 				'new_item_name'              => __( 'New Pattern Category Name' ),
       
   246 				'no_terms'                   => __( 'No pattern categories' ),
       
   247 				'not_found'                  => __( 'No pattern categories found.' ),
       
   248 				'popular_items'              => __( 'Popular Pattern Categories' ),
       
   249 				'search_items'               => __( 'Search Pattern Categories' ),
       
   250 				'separate_items_with_commas' => __( 'Separate pattern categories with commas' ),
       
   251 				'update_item'                => __( 'Update Pattern Category' ),
       
   252 				'view_item'                  => __( 'View Pattern Category' ),
       
   253 			),
       
   254 			'query_var'          => false,
       
   255 			'rewrite'            => false,
       
   256 			'show_ui'            => true,
       
   257 			'_builtin'           => true,
       
   258 			'show_in_nav_menus'  => false,
       
   259 			'show_in_rest'       => true,
       
   260 			'show_admin_column'  => true,
       
   261 			'show_tagcloud'      => false,
       
   262 		)
       
   263 	);
   225 }
   264 }
   226 
   265 
   227 /**
   266 /**
   228  * Retrieves a list of registered taxonomy names or objects.
   267  * Retrieves a list of registered taxonomy names or objects.
   229  *
   268  *
   231  *
   270  *
   232  * @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies.
   271  * @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies.
   233  *
   272  *
   234  * @param array  $args     Optional. An array of `key => value` arguments to match against the taxonomy objects.
   273  * @param array  $args     Optional. An array of `key => value` arguments to match against the taxonomy objects.
   235  *                         Default empty array.
   274  *                         Default empty array.
   236  * @param string $output   Optional. The type of output to return in the array. Accepts either taxonomy 'names'
   275  * @param string $output   Optional. The type of output to return in the array. Either 'names'
   237  *                         or 'objects'. Default 'names'.
   276  *                         or 'objects'. Default 'names'.
   238  * @param string $operator Optional. The logical operation to perform. Accepts 'and' or 'or'. 'or' means only
   277  * @param string $operator Optional. The logical operation to perform. Accepts 'and' or 'or'. 'or' means only
   239  *                         one element from the array needs to match; 'and' means all elements must match.
   278  *                         one element from the array needs to match; 'and' means all elements must match.
   240  *                         Default 'and'.
   279  *                         Default 'and'.
   241  * @return string[]|WP_Taxonomy[] An array of taxonomy names or objects.
   280  * @return string[]|WP_Taxonomy[] An array of taxonomy names or objects.
   262  *
   301  *
   263  * @since 2.3.0
   302  * @since 2.3.0
   264  *
   303  *
   265  * @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies.
   304  * @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies.
   266  *
   305  *
   267  * @param string|string[]|WP_Post $object Name of the type of taxonomy object, or an object (row from posts)
   306  * @param string|string[]|WP_Post $object_type Name of the type of taxonomy object, or an object (row from posts).
   268  * @param string                  $output Optional. The type of output to return in the array. Accepts either
   307  * @param string                  $output      Optional. The type of output to return in the array. Accepts either
   269  *                                        'names' or 'objects'. Default 'names'.
   308  *                                             'names' or 'objects'. Default 'names'.
   270  * @return string[]|WP_Taxonomy[] The names or objects of all taxonomies of `$object_type`.
   309  * @return string[]|WP_Taxonomy[] The names or objects of all taxonomies of `$object_type`.
   271  */
   310  */
   272 function get_object_taxonomies( $object, $output = 'names' ) {
   311 function get_object_taxonomies( $object_type, $output = 'names' ) {
   273 	global $wp_taxonomies;
   312 	global $wp_taxonomies;
   274 
   313 
   275 	if ( is_object( $object ) ) {
   314 	if ( is_object( $object_type ) ) {
   276 		if ( 'attachment' === $object->post_type ) {
   315 		if ( 'attachment' === $object_type->post_type ) {
   277 			return get_attachment_taxonomies( $object, $output );
   316 			return get_attachment_taxonomies( $object_type, $output );
   278 		}
   317 		}
   279 		$object = $object->post_type;
   318 		$object_type = $object_type->post_type;
   280 	}
   319 	}
   281 
   320 
   282 	$object = (array) $object;
   321 	$object_type = (array) $object_type;
   283 
   322 
   284 	$taxonomies = array();
   323 	$taxonomies = array();
   285 	foreach ( (array) $wp_taxonomies as $tax_name => $tax_obj ) {
   324 	foreach ( (array) $wp_taxonomies as $tax_name => $tax_obj ) {
   286 		if ( array_intersect( $object, (array) $tax_obj->object_type ) ) {
   325 		if ( array_intersect( $object_type, (array) $tax_obj->object_type ) ) {
   287 			if ( 'names' === $output ) {
   326 			if ( 'names' === $output ) {
   288 				$taxonomies[] = $tax_name;
   327 				$taxonomies[] = $tax_name;
   289 			} else {
   328 			} else {
   290 				$taxonomies[ $tax_name ] = $tax_obj;
   329 				$taxonomies[ $tax_name ] = $tax_obj;
   291 			}
   330 			}
   335  * @return bool Whether the taxonomy exists.
   374  * @return bool Whether the taxonomy exists.
   336  */
   375  */
   337 function taxonomy_exists( $taxonomy ) {
   376 function taxonomy_exists( $taxonomy ) {
   338 	global $wp_taxonomies;
   377 	global $wp_taxonomies;
   339 
   378 
   340 	return isset( $wp_taxonomies[ $taxonomy ] );
   379 	return is_string( $taxonomy ) && isset( $wp_taxonomies[ $taxonomy ] );
   341 }
   380 }
   342 
   381 
   343 /**
   382 /**
   344  * Determines whether the taxonomy object is hierarchical.
   383  * Determines whether the taxonomy object is hierarchical.
   345  *
   384  *
   388  * @since 5.5.0 Introduced `default_term` argument.
   427  * @since 5.5.0 Introduced `default_term` argument.
   389  * @since 5.9.0 Introduced `rest_namespace` argument.
   428  * @since 5.9.0 Introduced `rest_namespace` argument.
   390  *
   429  *
   391  * @global WP_Taxonomy[] $wp_taxonomies Registered taxonomies.
   430  * @global WP_Taxonomy[] $wp_taxonomies Registered taxonomies.
   392  *
   431  *
   393  * @param string       $taxonomy    Taxonomy key, must not exceed 32 characters.
   432  * @param string       $taxonomy    Taxonomy key. Must not exceed 32 characters and may only contain
       
   433  *                                  lowercase alphanumeric characters, dashes, and underscores. See sanitize_key().
   394  * @param array|string $object_type Object type or array of object types with which the taxonomy should be associated.
   434  * @param array|string $object_type Object type or array of object types with which the taxonomy should be associated.
   395  * @param array|string $args        {
   435  * @param array|string $args        {
   396  *     Optional. Array or query string of arguments for registering a taxonomy.
   436  *     Optional. Array or query string of arguments for registering a taxonomy.
   397  *
   437  *
   398  *     @type string[]      $labels                An array of labels for this taxonomy. By default, Tag labels are
   438  *     @type string[]      $labels                An array of labels for this taxonomy. By default, Tag labels are
   555  *
   595  *
   556  * Can not be used to unregister built-in taxonomies.
   596  * Can not be used to unregister built-in taxonomies.
   557  *
   597  *
   558  * @since 4.5.0
   598  * @since 4.5.0
   559  *
   599  *
   560  * @global WP    $wp            Current WordPress environment instance.
       
   561  * @global WP_Taxonomy[] $wp_taxonomies List of taxonomies.
   600  * @global WP_Taxonomy[] $wp_taxonomies List of taxonomies.
   562  *
   601  *
   563  * @param string $taxonomy Taxonomy name.
   602  * @param string $taxonomy Taxonomy name.
   564  * @return true|WP_Error True on success, WP_Error on failure or if the taxonomy doesn't exist.
   603  * @return true|WP_Error True on success, WP_Error on failure or if the taxonomy doesn't exist.
   565  */
   604  */
   566 function unregister_taxonomy( $taxonomy ) {
   605 function unregister_taxonomy( $taxonomy ) {
       
   606 	global $wp_taxonomies;
       
   607 
   567 	if ( ! taxonomy_exists( $taxonomy ) ) {
   608 	if ( ! taxonomy_exists( $taxonomy ) ) {
   568 		return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy.' ) );
   609 		return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy.' ) );
   569 	}
   610 	}
   570 
   611 
   571 	$taxonomy_object = get_taxonomy( $taxonomy );
   612 	$taxonomy_object = get_taxonomy( $taxonomy );
   573 	// Do not allow unregistering internal taxonomies.
   614 	// Do not allow unregistering internal taxonomies.
   574 	if ( $taxonomy_object->_builtin ) {
   615 	if ( $taxonomy_object->_builtin ) {
   575 		return new WP_Error( 'invalid_taxonomy', __( 'Unregistering a built-in taxonomy is not allowed.' ) );
   616 		return new WP_Error( 'invalid_taxonomy', __( 'Unregistering a built-in taxonomy is not allowed.' ) );
   576 	}
   617 	}
   577 
   618 
   578 	global $wp_taxonomies;
       
   579 
       
   580 	$taxonomy_object->remove_rewrite_rules();
   619 	$taxonomy_object->remove_rewrite_rules();
   581 	$taxonomy_object->remove_hooks();
   620 	$taxonomy_object->remove_hooks();
   582 
       
   583 	// Remove custom taxonomy default term option.
       
   584 	if ( ! empty( $taxonomy_object->default_term ) ) {
       
   585 		delete_option( 'default_term_' . $taxonomy_object->name );
       
   586 	}
       
   587 
   621 
   588 	// Remove the taxonomy.
   622 	// Remove the taxonomy.
   589 	unset( $wp_taxonomies[ $taxonomy ] );
   623 	unset( $wp_taxonomies[ $taxonomy ] );
   590 
   624 
   591 	/**
   625 	/**
   609  * @since 4.9.0 Added the `most_used` and `back_to_items` labels.
   643  * @since 4.9.0 Added the `most_used` and `back_to_items` labels.
   610  * @since 5.7.0 Added the `filter_by_item` label.
   644  * @since 5.7.0 Added the `filter_by_item` label.
   611  * @since 5.8.0 Added the `item_link` and `item_link_description` labels.
   645  * @since 5.8.0 Added the `item_link` and `item_link_description` labels.
   612  * @since 5.9.0 Added the `name_field_description`, `slug_field_description`,
   646  * @since 5.9.0 Added the `name_field_description`, `slug_field_description`,
   613  *              `parent_field_description`, and `desc_field_description` labels.
   647  *              `parent_field_description`, and `desc_field_description` labels.
       
   648  * @since 6.6.0 Added the `template_name` label.
   614  *
   649  *
   615  * @param WP_Taxonomy $tax Taxonomy object.
   650  * @param WP_Taxonomy $tax Taxonomy object.
   616  * @return object {
   651  * @return object {
   617  *     Taxonomy labels object. The first default value is for non-hierarchical taxonomies
   652  *     Taxonomy labels object. The first default value is for non-hierarchical taxonomies
   618  *     (like tags) and the second one is for hierarchical taxonomies (like categories).
   653  *     (like tags) and the second one is for hierarchical taxonomies (like categories).
   643  *     @type string $edit_item                  Default 'Edit Tag'/'Edit Category'.
   678  *     @type string $edit_item                  Default 'Edit Tag'/'Edit Category'.
   644  *     @type string $view_item                  Default 'View Tag'/'View Category'.
   679  *     @type string $view_item                  Default 'View Tag'/'View Category'.
   645  *     @type string $update_item                Default 'Update Tag'/'Update Category'.
   680  *     @type string $update_item                Default 'Update Tag'/'Update Category'.
   646  *     @type string $add_new_item               Default 'Add New Tag'/'Add New Category'.
   681  *     @type string $add_new_item               Default 'Add New Tag'/'Add New Category'.
   647  *     @type string $new_item_name              Default 'New Tag Name'/'New Category Name'.
   682  *     @type string $new_item_name              Default 'New Tag Name'/'New Category Name'.
       
   683  *     @type string $template_name              Default 'Tag Archives'/'Category Archives'.
   648  *     @type string $separate_items_with_commas This label is only used for non-hierarchical taxonomies. Default
   684  *     @type string $separate_items_with_commas This label is only used for non-hierarchical taxonomies. Default
   649  *                                              'Separate tags with commas', used in the meta box.
   685  *                                              'Separate tags with commas', used in the meta box.
   650  *     @type string $add_or_remove_items        This label is only used for non-hierarchical taxonomies. Default
   686  *     @type string $add_or_remove_items        This label is only used for non-hierarchical taxonomies. Default
   651  *                                              'Add or remove tags', used in the meta box when JavaScript
   687  *                                              'Add or remove tags', used in the meta box when JavaScript
   652  *                                              is disabled.
   688  *                                              is disabled.
   683 
   719 
   684 	$nohier_vs_hier_defaults['menu_name'] = $nohier_vs_hier_defaults['name'];
   720 	$nohier_vs_hier_defaults['menu_name'] = $nohier_vs_hier_defaults['name'];
   685 
   721 
   686 	$labels = _get_custom_object_labels( $tax, $nohier_vs_hier_defaults );
   722 	$labels = _get_custom_object_labels( $tax, $nohier_vs_hier_defaults );
   687 
   723 
       
   724 	if ( ! isset( $tax->labels->template_name ) && isset( $labels->singular_name ) ) {
       
   725 		/* translators: %s: Taxonomy name. */
       
   726 		$labels->template_name = sprintf( _x( '%s Archives', 'taxonomy template name' ), $labels->singular_name );
       
   727 	}
       
   728 
   688 	$taxonomy = $tax->name;
   729 	$taxonomy = $tax->name;
   689 
   730 
   690 	$default_labels = clone $labels;
   731 	$default_labels = clone $labels;
   691 
   732 
   692 	/**
   733 	/**
   817  *
   858  *
   818  * @global wpdb $wpdb WordPress database abstraction object.
   859  * @global wpdb $wpdb WordPress database abstraction object.
   819  *
   860  *
   820  * @param int|int[]       $term_ids   Term ID or array of term IDs of terms that will be used.
   861  * @param int|int[]       $term_ids   Term ID or array of term IDs of terms that will be used.
   821  * @param string|string[] $taxonomies String of taxonomy name or Array of string values of taxonomy names.
   862  * @param string|string[] $taxonomies String of taxonomy name or Array of string values of taxonomy names.
   822  * @param array|string    $args       Change the order of the object IDs, either ASC or DESC.
   863  * @param array|string    $args       {
       
   864  *     Change the order of the object IDs.
       
   865  *
       
   866  *     @type string $order Order to retrieve terms. Accepts 'ASC' or 'DESC'. Default 'ASC'.
       
   867  * }
   823  * @return string[]|WP_Error An array of object IDs as numeric strings on success,
   868  * @return string[]|WP_Error An array of object IDs as numeric strings on success,
   824  *                           WP_Error if the taxonomy does not exist.
   869  *                           WP_Error if the taxonomy does not exist.
   825  */
   870  */
   826 function get_objects_in_term( $term_ids, $taxonomies, $args = array() ) {
   871 function get_objects_in_term( $term_ids, $taxonomies, $args = array() ) {
   827 	global $wpdb;
   872 	global $wpdb;
   850 
   895 
   851 	$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";
   896 	$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";
   852 
   897 
   853 	$last_changed = wp_cache_get_last_changed( 'terms' );
   898 	$last_changed = wp_cache_get_last_changed( 'terms' );
   854 	$cache_key    = 'get_objects_in_term:' . md5( $sql ) . ":$last_changed";
   899 	$cache_key    = 'get_objects_in_term:' . md5( $sql ) . ":$last_changed";
   855 	$cache        = wp_cache_get( $cache_key, 'terms' );
   900 	$cache        = wp_cache_get( $cache_key, 'term-queries' );
   856 	if ( false === $cache ) {
   901 	if ( false === $cache ) {
   857 		$object_ids = $wpdb->get_col( $sql );
   902 		$object_ids = $wpdb->get_col( $sql );
   858 		wp_cache_set( $cache_key, $object_ids, 'terms' );
   903 		wp_cache_set( $cache_key, $object_ids, 'term-queries' );
   859 	} else {
   904 	} else {
   860 		$object_ids = (array) $cache;
   905 		$object_ids = (array) $cache;
   861 	}
   906 	}
   862 
   907 
   863 	if ( ! $object_ids ) {
   908 	if ( ! $object_ids ) {
   958 	}
  1003 	}
   959 
  1004 
   960 	// Ensure for filters that this is not empty.
  1005 	// Ensure for filters that this is not empty.
   961 	$taxonomy = $_term->taxonomy;
  1006 	$taxonomy = $_term->taxonomy;
   962 
  1007 
       
  1008 	$old_term = $_term;
   963 	/**
  1009 	/**
   964 	 * Filters a taxonomy term object.
  1010 	 * Filters a taxonomy term object.
   965 	 *
  1011 	 *
   966 	 * The {@see 'get_$taxonomy'} hook is also available for targeting a specific
  1012 	 * The {@see 'get_$taxonomy'} hook is also available for targeting a specific
   967 	 * taxonomy.
  1013 	 * taxonomy.
   997 	if ( ! ( $_term instanceof WP_Term ) ) {
  1043 	if ( ! ( $_term instanceof WP_Term ) ) {
   998 		return $_term;
  1044 		return $_term;
   999 	}
  1045 	}
  1000 
  1046 
  1001 	// Sanitize term, according to the specified filter.
  1047 	// Sanitize term, according to the specified filter.
  1002 	$_term->filter( $filter );
  1048 	if ( $_term !== $old_term || $_term->filter !== $filter ) {
       
  1049 		$_term->filter( $filter );
       
  1050 	}
  1003 
  1051 
  1004 	if ( ARRAY_A === $output ) {
  1052 	if ( ARRAY_A === $output ) {
  1005 		return $_term->to_array();
  1053 		return $_term->to_array();
  1006 	} elseif ( ARRAY_N === $output ) {
  1054 	} elseif ( ARRAY_N === $output ) {
  1007 		return array_values( $_term->to_array() );
  1055 		return array_values( $_term->to_array() );
  1232  * the $args.
  1280  * the $args.
  1233  *
  1281  *
  1234  * The {@see 'get_terms_orderby'} filter passes the `ORDER BY` clause for the query
  1282  * The {@see 'get_terms_orderby'} filter passes the `ORDER BY` clause for the query
  1235  * along with the $args array.
  1283  * along with the $args array.
  1236  *
  1284  *
  1237  * Prior to 4.5.0, the first parameter of `get_terms()` was a taxonomy or list of taxonomies:
  1285  * Taxonomy or an array of taxonomies should be passed via the 'taxonomy' argument
  1238  *
  1286  * in the `$args` array:
  1239  *     $terms = get_terms( 'post_tag', array(
  1287  *
       
  1288  *     $terms = get_terms( array(
       
  1289  *         'taxonomy'   => 'post_tag',
  1240  *         'hide_empty' => false,
  1290  *         'hide_empty' => false,
  1241  *     ) );
  1291  *     ) );
  1242  *
  1292  *
  1243  * Since 4.5.0, taxonomies should be passed via the 'taxonomy' argument in the `$args` array:
  1293  * Prior to 4.5.0, taxonomy was passed as the first parameter of `get_terms()`.
  1244  *
       
  1245  *     $terms = get_terms( array(
       
  1246  *         'taxonomy' => 'post_tag',
       
  1247  *         'hide_empty' => false,
       
  1248  *     ) );
       
  1249  *
  1294  *
  1250  * @since 2.3.0
  1295  * @since 2.3.0
  1251  * @since 4.2.0 Introduced 'name' and 'childless' parameters.
  1296  * @since 4.2.0 Introduced 'name' and 'childless' parameters.
  1252  * @since 4.4.0 Introduced the ability to pass 'term_id' as an alias of 'id' for the `orderby` parameter.
  1297  * @since 4.4.0 Introduced the ability to pass 'term_id' as an alias of 'id' for the `orderby` parameter.
  1253  *              Introduced the 'meta_query' and 'update_term_meta_cache' parameters. Converted to return
  1298  *              Introduced the 'meta_query' and 'update_term_meta_cache' parameters. Converted to return
  1432  */
  1477  */
  1433 function update_termmeta_cache( $term_ids ) {
  1478 function update_termmeta_cache( $term_ids ) {
  1434 	return update_meta_cache( 'term', $term_ids );
  1479 	return update_meta_cache( 'term', $term_ids );
  1435 }
  1480 }
  1436 
  1481 
       
  1482 
       
  1483 /**
       
  1484  * Queue term meta for lazy-loading.
       
  1485  *
       
  1486  * @since 6.3.0
       
  1487  *
       
  1488  * @param array $term_ids List of term IDs.
       
  1489  */
       
  1490 function wp_lazyload_term_meta( array $term_ids ) {
       
  1491 	if ( empty( $term_ids ) ) {
       
  1492 		return;
       
  1493 	}
       
  1494 	$lazyloader = wp_metadata_lazyloader();
       
  1495 	$lazyloader->queue_objects( 'term', $term_ids );
       
  1496 }
       
  1497 
  1437 /**
  1498 /**
  1438  * Gets all meta data, including meta IDs, for the given term ID.
  1499  * Gets all meta data, including meta IDs, for the given term ID.
  1439  *
  1500  *
  1440  * @since 4.9.0
  1501  * @since 4.9.0
  1441  *
  1502  *
  1500  * @since 3.0.0
  1561  * @since 3.0.0
  1501  * @since 6.0.0 Converted to use `get_terms()`.
  1562  * @since 6.0.0 Converted to use `get_terms()`.
  1502  *
  1563  *
  1503  * @global bool $_wp_suspend_cache_invalidation
  1564  * @global bool $_wp_suspend_cache_invalidation
  1504  *
  1565  *
  1505  * @param int|string $term     The term to check. Accepts term ID, slug, or name.
  1566  * @param int|string $term        The term to check. Accepts term ID, slug, or name.
  1506  * @param string     $taxonomy Optional. The taxonomy name to use.
  1567  * @param string     $taxonomy    Optional. The taxonomy name to use.
  1507  * @param int        $parent   Optional. ID of parent term under which to confine the exists search.
  1568  * @param int        $parent_term Optional. ID of parent term under which to confine the exists search.
  1508  * @return mixed Returns null if the term does not exist.
  1569  * @return mixed Returns null if the term does not exist.
  1509  *               Returns the term ID if no taxonomy is specified and the term ID exists.
  1570  *               Returns the term ID if no taxonomy is specified and the term ID exists.
  1510  *               Returns an array of the term ID and the term taxonomy ID if the taxonomy is specified and the pairing exists.
  1571  *               Returns an array of the term ID and the term taxonomy ID if the taxonomy is specified and the pairing exists.
  1511  *               Returns 0 if term ID 0 is passed to the function.
  1572  *               Returns 0 if term ID 0 is passed to the function.
  1512  */
  1573  */
  1513 function term_exists( $term, $taxonomy = '', $parent = null ) {
  1574 function term_exists( $term, $taxonomy = '', $parent_term = null ) {
  1514 	global $_wp_suspend_cache_invalidation;
  1575 	global $_wp_suspend_cache_invalidation;
  1515 
  1576 
  1516 	if ( null === $term ) {
  1577 	if ( null === $term ) {
  1517 		return null;
  1578 		return null;
  1518 	}
  1579 	}
  1527 		'suppress_filter'        => true,
  1588 		'suppress_filter'        => true,
  1528 	);
  1589 	);
  1529 
  1590 
  1530 	// Ensure that while importing, queries are not cached.
  1591 	// Ensure that while importing, queries are not cached.
  1531 	if ( ! empty( $_wp_suspend_cache_invalidation ) ) {
  1592 	if ( ! empty( $_wp_suspend_cache_invalidation ) ) {
  1532 		// @todo Disable caching once #52710 is merged.
  1593 		$defaults['cache_results'] = false;
  1533 		$defaults['cache_domain'] = microtime();
       
  1534 	}
  1594 	}
  1535 
  1595 
  1536 	if ( ! empty( $taxonomy ) ) {
  1596 	if ( ! empty( $taxonomy ) ) {
  1537 		$defaults['taxonomy'] = $taxonomy;
  1597 		$defaults['taxonomy'] = $taxonomy;
  1538 		$defaults['fields']   = 'all';
  1598 		$defaults['fields']   = 'all';
  1541 	/**
  1601 	/**
  1542 	 * Filters default query arguments for checking if a term exists.
  1602 	 * Filters default query arguments for checking if a term exists.
  1543 	 *
  1603 	 *
  1544 	 * @since 6.0.0
  1604 	 * @since 6.0.0
  1545 	 *
  1605 	 *
  1546 	 * @param array      $defaults An array of arguments passed to get_terms().
  1606 	 * @param array      $defaults    An array of arguments passed to get_terms().
  1547 	 * @param int|string $term     The term to check. Accepts term ID, slug, or name.
  1607 	 * @param int|string $term        The term to check. Accepts term ID, slug, or name.
  1548 	 * @param string     $taxonomy The taxonomy name to use. An empty string indicates
  1608 	 * @param string     $taxonomy    The taxonomy name to use. An empty string indicates
  1549 	 *                             the search is against all taxonomies.
  1609 	 *                                the search is against all taxonomies.
  1550 	 * @param int|null   $parent   ID of parent term under which to confine the exists search.
  1610 	 * @param int|null   $parent_term ID of parent term under which to confine the exists search.
  1551 	 *                             Null indicates the search is unconfined.
  1611 	 *                                Null indicates the search is unconfined.
  1552 	 */
  1612 	 */
  1553 	$defaults = apply_filters( 'term_exists_default_query_args', $defaults, $term, $taxonomy, $parent );
  1613 	$defaults = apply_filters( 'term_exists_default_query_args', $defaults, $term, $taxonomy, $parent_term );
  1554 
  1614 
  1555 	if ( is_int( $term ) ) {
  1615 	if ( is_int( $term ) ) {
  1556 		if ( 0 === $term ) {
  1616 		if ( 0 === $term ) {
  1557 			return 0;
  1617 			return 0;
  1558 		}
  1618 		}
  1562 		$term = trim( wp_unslash( $term ) );
  1622 		$term = trim( wp_unslash( $term ) );
  1563 		if ( '' === $term ) {
  1623 		if ( '' === $term ) {
  1564 			return null;
  1624 			return null;
  1565 		}
  1625 		}
  1566 
  1626 
  1567 		if ( ! empty( $taxonomy ) && is_numeric( $parent ) ) {
  1627 		if ( ! empty( $taxonomy ) && is_numeric( $parent_term ) ) {
  1568 			$defaults['parent'] = (int) $parent;
  1628 			$defaults['parent'] = (int) $parent_term;
  1569 		}
  1629 		}
  1570 
  1630 
  1571 		$args  = wp_parse_args( array( 'slug' => sanitize_title( $term ) ), $defaults );
  1631 		$args  = wp_parse_args( array( 'slug' => sanitize_title( $term ) ), $defaults );
  1572 		$terms = get_terms( $args );
  1632 		$terms = get_terms( $args );
  1573 		if ( empty( $terms ) || is_wp_error( $terms ) ) {
  1633 		if ( empty( $terms ) || is_wp_error( $terms ) ) {
  1858  * @since 2.3.0
  1918  * @since 2.3.0
  1859  * @since 5.6.0 Changed the function signature so that the `$args` array can be provided as the first parameter.
  1919  * @since 5.6.0 Changed the function signature so that the `$args` array can be provided as the first parameter.
  1860  *
  1920  *
  1861  * @internal The `$deprecated` parameter is parsed for backward compatibility only.
  1921  * @internal The `$deprecated` parameter is parsed for backward compatibility only.
  1862  *
  1922  *
  1863  * @param array|string $args       Optional. Array of arguments that get passed to get_terms().
  1923  * @param array|string $args       Optional. Array or string of arguments. See WP_Term_Query::__construct()
  1864  *                                 Default empty array.
  1924  *                                 for information on accepted arguments. Default empty array.
  1865  * @param array|string $deprecated Optional. Argument array, when using the legacy function parameter format.
  1925  * @param array|string $deprecated Optional. Argument array, when using the legacy function parameter format.
  1866  *                                 If present, this parameter will be interpreted as `$args`, and the first
  1926  *                                 If present, this parameter will be interpreted as `$args`, and the first
  1867  *                                 function parameter will be parsed as a taxonomy or array of taxonomies.
  1927  *                                 function parameter will be parsed as a taxonomy or array of taxonomies.
  1868  *                                 Default empty.
  1928  *                                 Default empty.
  1869  * @return string|WP_Error Numeric string containing the number of terms in that
  1929  * @return string|WP_Error Numeric string containing the number of terms in that
  2160 /**
  2220 /**
  2161  * Deletes one existing category.
  2221  * Deletes one existing category.
  2162  *
  2222  *
  2163  * @since 2.0.0
  2223  * @since 2.0.0
  2164  *
  2224  *
  2165  * @param int $cat_ID Category term ID.
  2225  * @param int $cat_id Category term ID.
  2166  * @return bool|int|WP_Error Returns true if completes delete action; false if term doesn't exist;
  2226  * @return bool|int|WP_Error Returns true if completes delete action; false if term doesn't exist;
  2167  *  Zero on attempted deletion of default Category; WP_Error object is also a possibility.
  2227  *                           Zero on attempted deletion of default Category; WP_Error object is
  2168  */
  2228  *                           also a possibility.
  2169 function wp_delete_category( $cat_ID ) {
  2229  */
  2170 	return wp_delete_term( $cat_ID, 'category' );
  2230 function wp_delete_category( $cat_id ) {
       
  2231 	return wp_delete_term( $cat_id, 'category' );
  2171 }
  2232 }
  2172 
  2233 
  2173 /**
  2234 /**
  2174  * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
  2235  * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
  2175  *
  2236  *
  2177  * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
  2238  * @since 4.2.0 Added support for 'taxonomy', 'parent', and 'term_taxonomy_id' values of `$orderby`.
  2178  *              Introduced `$parent` argument.
  2239  *              Introduced `$parent` argument.
  2179  * @since 4.4.0 Introduced `$meta_query` and `$update_term_meta_cache` arguments. When `$fields` is 'all' or
  2240  * @since 4.4.0 Introduced `$meta_query` and `$update_term_meta_cache` arguments. When `$fields` is 'all' or
  2180  *              'all_with_object_id', an array of `WP_Term` objects will be returned.
  2241  *              'all_with_object_id', an array of `WP_Term` objects will be returned.
  2181  * @since 4.7.0 Refactored to use WP_Term_Query, and to support any WP_Term_Query arguments.
  2242  * @since 4.7.0 Refactored to use WP_Term_Query, and to support any WP_Term_Query arguments.
       
  2243  * @since 6.3.0 Passing `update_term_meta_cache` argument value false by default resulting in get_terms() to not
       
  2244  *              prime the term meta cache.
  2182  *
  2245  *
  2183  * @param int|int[]       $object_ids The ID(s) of the object(s) to retrieve.
  2246  * @param int|int[]       $object_ids The ID(s) of the object(s) to retrieve.
  2184  * @param string|string[] $taxonomies The taxonomy names to retrieve terms from.
  2247  * @param string|string[] $taxonomies The taxonomy names to retrieve terms from.
  2185  * @param array|string    $args       See WP_Term_Query::__construct() for supported arguments.
  2248  * @param array|string    $args       See WP_Term_Query::__construct() for supported arguments.
  2186  * @return WP_Term[]|WP_Error Array of terms or empty array if no terms found.
  2249  * @return WP_Term[]|int[]|string[]|string|WP_Error Array of terms, a count thereof as a numeric string,
  2187  *                            WP_Error if any of the taxonomies don't exist.
  2250  *                                                  or WP_Error if any of the taxonomies do not exist.
       
  2251  *                                                  See WP_Term_Query::get_terms() for more information.
  2188  */
  2252  */
  2189 function wp_get_object_terms( $object_ids, $taxonomies, $args = array() ) {
  2253 function wp_get_object_terms( $object_ids, $taxonomies, $args = array() ) {
  2190 	if ( empty( $object_ids ) || empty( $taxonomies ) ) {
  2254 	if ( empty( $object_ids ) || empty( $taxonomies ) ) {
  2191 		return array();
  2255 		return array();
  2192 	}
  2256 	}
  2204 	if ( ! is_array( $object_ids ) ) {
  2268 	if ( ! is_array( $object_ids ) ) {
  2205 		$object_ids = array( $object_ids );
  2269 		$object_ids = array( $object_ids );
  2206 	}
  2270 	}
  2207 	$object_ids = array_map( 'intval', $object_ids );
  2271 	$object_ids = array_map( 'intval', $object_ids );
  2208 
  2272 
  2209 	$args = wp_parse_args( $args );
  2273 	$defaults = array(
       
  2274 		'update_term_meta_cache' => false,
       
  2275 	);
       
  2276 
       
  2277 	$args = wp_parse_args( $args, $defaults );
  2210 
  2278 
  2211 	/**
  2279 	/**
  2212 	 * Filters arguments for retrieving object terms.
  2280 	 * Filters arguments for retrieving object terms.
  2213 	 *
  2281 	 *
  2214 	 * @since 4.9.0
  2282 	 * @since 4.9.0
  2246 	// Taxonomies registered without an 'args' param are handled here.
  2314 	// Taxonomies registered without an 'args' param are handled here.
  2247 	if ( ! empty( $taxonomies ) ) {
  2315 	if ( ! empty( $taxonomies ) ) {
  2248 		$terms_from_remaining_taxonomies = get_terms( $args );
  2316 		$terms_from_remaining_taxonomies = get_terms( $args );
  2249 
  2317 
  2250 		// Array keys should be preserved for values of $fields that use term_id for keys.
  2318 		// Array keys should be preserved for values of $fields that use term_id for keys.
  2251 		if ( ! empty( $args['fields'] ) && 0 === strpos( $args['fields'], 'id=>' ) ) {
  2319 		if ( ! empty( $args['fields'] ) && str_starts_with( $args['fields'], 'id=>' ) ) {
  2252 			$terms = $terms + $terms_from_remaining_taxonomies;
  2320 			$terms = $terms + $terms_from_remaining_taxonomies;
  2253 		} else {
  2321 		} else {
  2254 			$terms = array_merge( $terms, $terms_from_remaining_taxonomies );
  2322 			$terms = array_merge( $terms, $terms_from_remaining_taxonomies );
  2255 		}
  2323 		}
  2256 	}
  2324 	}
  2258 	/**
  2326 	/**
  2259 	 * Filters the terms for a given object or objects.
  2327 	 * Filters the terms for a given object or objects.
  2260 	 *
  2328 	 *
  2261 	 * @since 4.2.0
  2329 	 * @since 4.2.0
  2262 	 *
  2330 	 *
  2263 	 * @param WP_Term[] $terms      Array of terms for the given object or objects.
  2331 	 * @param WP_Term[]|int[]|string[]|string $terms      Array of terms or a count thereof as a numeric string.
  2264 	 * @param int[]     $object_ids Array of object IDs for which terms were retrieved.
  2332 	 * @param int[]                           $object_ids Array of object IDs for which terms were retrieved.
  2265 	 * @param string[]  $taxonomies Array of taxonomy names from which terms were retrieved.
  2333 	 * @param string[]                        $taxonomies Array of taxonomy names from which terms were retrieved.
  2266 	 * @param array     $args       Array of arguments for retrieving terms for the given
  2334 	 * @param array                           $args       Array of arguments for retrieving terms for the given
  2267 	 *                              object(s). See wp_get_object_terms() for details.
  2335 	 *                                                    object(s). See wp_get_object_terms() for details.
  2268 	 */
  2336 	 */
  2269 	$terms = apply_filters( 'get_object_terms', $terms, $object_ids, $taxonomies, $args );
  2337 	$terms = apply_filters( 'get_object_terms', $terms, $object_ids, $taxonomies, $args );
  2270 
  2338 
  2271 	$object_ids = implode( ',', $object_ids );
  2339 	$object_ids = implode( ',', $object_ids );
  2272 	$taxonomies = "'" . implode( "', '", array_map( 'esc_sql', $taxonomies ) ) . "'";
  2340 	$taxonomies = "'" . implode( "', '", array_map( 'esc_sql', $taxonomies ) ) . "'";
  2277 	 * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
  2345 	 * The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment. The
  2278 	 * {@see 'get_object_terms'} filter is recommended as an alternative.
  2346 	 * {@see 'get_object_terms'} filter is recommended as an alternative.
  2279 	 *
  2347 	 *
  2280 	 * @since 2.8.0
  2348 	 * @since 2.8.0
  2281 	 *
  2349 	 *
  2282 	 * @param WP_Term[] $terms      Array of terms for the given object or objects.
  2350 	 * @param WP_Term[]|int[]|string[]|string $terms      Array of terms or a count thereof as a numeric string.
  2283 	 * @param string    $object_ids Comma separated list of object IDs for which terms were retrieved.
  2351 	 * @param string                          $object_ids Comma separated list of object IDs for which terms were retrieved.
  2284 	 * @param string    $taxonomies SQL fragment of taxonomy names from which terms were retrieved.
  2352 	 * @param string                          $taxonomies SQL fragment of taxonomy names from which terms were retrieved.
  2285 	 * @param array     $args       Array of arguments for retrieving terms for the given
  2353 	 * @param array                           $args       Array of arguments for retrieving terms for the given
  2286 	 *                              object(s). See wp_get_object_terms() for details.
  2354 	 *                                                    object(s). See wp_get_object_terms() for details.
  2287 	 */
  2355 	 */
  2288 	return apply_filters( 'wp_get_object_terms', $terms, $object_ids, $taxonomies, $args );
  2356 	return apply_filters( 'wp_get_object_terms', $terms, $object_ids, $taxonomies, $args );
  2289 }
  2357 }
  2290 
  2358 
  2291 /**
  2359 /**
  2344 
  2412 
  2345 	/**
  2413 	/**
  2346 	 * Filters a term before it is sanitized and inserted into the database.
  2414 	 * Filters a term before it is sanitized and inserted into the database.
  2347 	 *
  2415 	 *
  2348 	 * @since 3.0.0
  2416 	 * @since 3.0.0
       
  2417 	 * @since 6.1.0 The `$args` parameter was added.
  2349 	 *
  2418 	 *
  2350 	 * @param string|WP_Error $term     The term name to add, or a WP_Error object if there's an error.
  2419 	 * @param string|WP_Error $term     The term name to add, or a WP_Error object if there's an error.
  2351 	 * @param string          $taxonomy Taxonomy slug.
  2420 	 * @param string          $taxonomy Taxonomy slug.
  2352 	 */
  2421 	 * @param array|string    $args     Array or query string of arguments passed to wp_insert_term().
  2353 	$term = apply_filters( 'pre_insert_term', $term, $taxonomy );
  2422 	 */
       
  2423 	$term = apply_filters( 'pre_insert_term', $term, $taxonomy, $args );
  2354 
  2424 
  2355 	if ( is_wp_error( $term ) ) {
  2425 	if ( is_wp_error( $term ) ) {
  2356 		return $term;
  2426 		return $term;
  2357 	}
  2427 	}
  2358 
  2428 
  2386 
  2456 
  2387 	// expected_slashed ($name)
  2457 	// expected_slashed ($name)
  2388 	$name        = wp_unslash( $args['name'] );
  2458 	$name        = wp_unslash( $args['name'] );
  2389 	$description = wp_unslash( $args['description'] );
  2459 	$description = wp_unslash( $args['description'] );
  2390 	$parent      = (int) $args['parent'];
  2460 	$parent      = (int) $args['parent'];
       
  2461 
       
  2462 	// Sanitization could clean the name to an empty string that must be checked again.
       
  2463 	if ( '' === $name ) {
       
  2464 		return new WP_Error( 'invalid_term_name', __( 'Invalid term name.' ) );
       
  2465 	}
  2391 
  2466 
  2392 	$slug_provided = ! empty( $args['slug'] );
  2467 	$slug_provided = ! empty( $args['slug'] );
  2393 	if ( ! $slug_provided ) {
  2468 	if ( ! $slug_provided ) {
  2394 		$slug = sanitize_title( $name );
  2469 		$slug = sanitize_title( $name );
  2395 	} else {
  2470 	} else {
  2526 	}
  2601 	}
  2527 
  2602 
  2528 	$tt_id = (int) $wpdb->insert_id;
  2603 	$tt_id = (int) $wpdb->insert_id;
  2529 
  2604 
  2530 	/*
  2605 	/*
  2531 	 * Sanity check: if we just created a term with the same parent + taxonomy + slug but a higher term_id than
  2606 	 * Confidence check: if we just created a term with the same parent + taxonomy + slug but a higher term_id than
  2532 	 * an existing term, then we have unwittingly created a duplicate term. Delete the dupe, and use the term_id
  2607 	 * an existing term, then we have unwittingly created a duplicate term. Delete the dupe, and use the term_id
  2533 	 * and term_taxonomy_id of the older term instead. Then return out of the function so that the "create" hooks
  2608 	 * and term_taxonomy_id of the older term instead. Then return out of the function so that the "create" hooks
  2534 	 * are not fired.
  2609 	 * are not fired.
  2535 	 */
  2610 	 */
  2536 	$duplicate_term = $wpdb->get_row( $wpdb->prepare( "SELECT t.term_id, t.slug, tt.term_taxonomy_id, tt.taxonomy FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON ( tt.term_id = t.term_id ) WHERE t.slug = %s AND tt.parent = %d AND tt.taxonomy = %s AND t.term_id < %d AND tt.term_taxonomy_id != %d", $slug, $parent, $taxonomy, $term_id, $tt_id ) );
  2611 	$duplicate_term = $wpdb->get_row( $wpdb->prepare( "SELECT t.term_id, t.slug, tt.term_taxonomy_id, tt.taxonomy FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON ( tt.term_id = t.term_id ) WHERE t.slug = %s AND tt.parent = %d AND tt.taxonomy = %s AND t.term_id < %d AND tt.term_taxonomy_id != %d", $slug, $parent, $taxonomy, $term_id, $tt_id ) );
  2546 	 * @since 5.1.0
  2621 	 * @since 5.1.0
  2547 	 *
  2622 	 *
  2548 	 * @param object $duplicate_term Duplicate term row from terms table, if found.
  2623 	 * @param object $duplicate_term Duplicate term row from terms table, if found.
  2549 	 * @param string $term           Term being inserted.
  2624 	 * @param string $term           Term being inserted.
  2550 	 * @param string $taxonomy       Taxonomy name.
  2625 	 * @param string $taxonomy       Taxonomy name.
  2551 	 * @param array  $args           Term arguments passed to the function.
  2626 	 * @param array  $args           Arguments passed to wp_insert_term().
  2552 	 * @param int    $tt_id          term_taxonomy_id for the newly created term.
  2627 	 * @param int    $tt_id          term_taxonomy_id for the newly created term.
  2553 	 */
  2628 	 */
  2554 	$duplicate_term = apply_filters( 'wp_insert_term_duplicate_term_check', $duplicate_term, $term, $taxonomy, $args, $tt_id );
  2629 	$duplicate_term = apply_filters( 'wp_insert_term_duplicate_term_check', $duplicate_term, $term, $taxonomy, $args, $tt_id );
  2555 
  2630 
  2556 	if ( $duplicate_term ) {
  2631 	if ( $duplicate_term ) {
  2572 	 *
  2647 	 *
  2573 	 * The {@see 'create_$taxonomy'} hook is also available for targeting a specific
  2648 	 * The {@see 'create_$taxonomy'} hook is also available for targeting a specific
  2574 	 * taxonomy.
  2649 	 * taxonomy.
  2575 	 *
  2650 	 *
  2576 	 * @since 2.3.0
  2651 	 * @since 2.3.0
       
  2652 	 * @since 6.1.0 The `$args` parameter was added.
  2577 	 *
  2653 	 *
  2578 	 * @param int    $term_id  Term ID.
  2654 	 * @param int    $term_id  Term ID.
  2579 	 * @param int    $tt_id    Term taxonomy ID.
  2655 	 * @param int    $tt_id    Term taxonomy ID.
  2580 	 * @param string $taxonomy Taxonomy slug.
  2656 	 * @param string $taxonomy Taxonomy slug.
  2581 	 */
  2657 	 * @param array  $args     Arguments passed to wp_insert_term().
  2582 	do_action( 'create_term', $term_id, $tt_id, $taxonomy );
  2658 	 */
       
  2659 	do_action( 'create_term', $term_id, $tt_id, $taxonomy, $args );
  2583 
  2660 
  2584 	/**
  2661 	/**
  2585 	 * Fires after a new term is created for a specific taxonomy.
  2662 	 * Fires after a new term is created for a specific taxonomy.
  2586 	 *
  2663 	 *
  2587 	 * The dynamic portion of the hook name, `$taxonomy`, refers
  2664 	 * The dynamic portion of the hook name, `$taxonomy`, refers
  2591 	 *
  2668 	 *
  2592 	 *  - `create_category`
  2669 	 *  - `create_category`
  2593 	 *  - `create_post_tag`
  2670 	 *  - `create_post_tag`
  2594 	 *
  2671 	 *
  2595 	 * @since 2.3.0
  2672 	 * @since 2.3.0
  2596 	 *
  2673 	 * @since 6.1.0 The `$args` parameter was added.
  2597 	 * @param int $term_id Term ID.
  2674 	 *
  2598 	 * @param int $tt_id   Term taxonomy ID.
  2675 	 * @param int   $term_id Term ID.
  2599 	 */
  2676 	 * @param int   $tt_id   Term taxonomy ID.
  2600 	do_action( "create_{$taxonomy}", $term_id, $tt_id );
  2677 	 * @param array $args    Arguments passed to wp_insert_term().
       
  2678 	 */
       
  2679 	do_action( "create_{$taxonomy}", $term_id, $tt_id, $args );
  2601 
  2680 
  2602 	/**
  2681 	/**
  2603 	 * Filters the term ID after a new term is created.
  2682 	 * Filters the term ID after a new term is created.
  2604 	 *
  2683 	 *
  2605 	 * @since 2.3.0
  2684 	 * @since 2.3.0
  2606 	 *
  2685 	 * @since 6.1.0 The `$args` parameter was added.
  2607 	 * @param int $term_id Term ID.
  2686 	 *
  2608 	 * @param int $tt_id   Term taxonomy ID.
  2687 	 * @param int   $term_id Term ID.
  2609 	 */
  2688 	 * @param int   $tt_id   Term taxonomy ID.
  2610 	$term_id = apply_filters( 'term_id_filter', $term_id, $tt_id );
  2689 	 * @param array $args    Arguments passed to wp_insert_term().
       
  2690 	 */
       
  2691 	$term_id = apply_filters( 'term_id_filter', $term_id, $tt_id, $args );
  2611 
  2692 
  2612 	clean_term_cache( $term_id, $taxonomy );
  2693 	clean_term_cache( $term_id, $taxonomy );
  2613 
  2694 
  2614 	/**
  2695 	/**
  2615 	 * Fires after a new term is created, and after the term cache has been cleaned.
  2696 	 * Fires after a new term is created, and after the term cache has been cleaned.
  2616 	 *
  2697 	 *
  2617 	 * The {@see 'created_$taxonomy'} hook is also available for targeting a specific
  2698 	 * The {@see 'created_$taxonomy'} hook is also available for targeting a specific
  2618 	 * taxonomy.
  2699 	 * taxonomy.
  2619 	 *
  2700 	 *
  2620 	 * @since 2.3.0
  2701 	 * @since 2.3.0
       
  2702 	 * @since 6.1.0 The `$args` parameter was added.
  2621 	 *
  2703 	 *
  2622 	 * @param int    $term_id  Term ID.
  2704 	 * @param int    $term_id  Term ID.
  2623 	 * @param int    $tt_id    Term taxonomy ID.
  2705 	 * @param int    $tt_id    Term taxonomy ID.
  2624 	 * @param string $taxonomy Taxonomy slug.
  2706 	 * @param string $taxonomy Taxonomy slug.
  2625 	 */
  2707 	 * @param array  $args     Arguments passed to wp_insert_term().
  2626 	do_action( 'created_term', $term_id, $tt_id, $taxonomy );
  2708 	 */
       
  2709 	do_action( 'created_term', $term_id, $tt_id, $taxonomy, $args );
  2627 
  2710 
  2628 	/**
  2711 	/**
  2629 	 * Fires after a new term in a specific taxonomy is created, and after the term
  2712 	 * Fires after a new term in a specific taxonomy is created, and after the term
  2630 	 * cache has been cleaned.
  2713 	 * cache has been cleaned.
  2631 	 *
  2714 	 *
  2635 	 *
  2718 	 *
  2636 	 *  - `created_category`
  2719 	 *  - `created_category`
  2637 	 *  - `created_post_tag`
  2720 	 *  - `created_post_tag`
  2638 	 *
  2721 	 *
  2639 	 * @since 2.3.0
  2722 	 * @since 2.3.0
  2640 	 *
  2723 	 * @since 6.1.0 The `$args` parameter was added.
  2641 	 * @param int $term_id Term ID.
  2724 	 *
  2642 	 * @param int $tt_id   Term taxonomy ID.
  2725 	 * @param int   $term_id Term ID.
  2643 	 */
  2726 	 * @param int   $tt_id   Term taxonomy ID.
  2644 	do_action( "created_{$taxonomy}", $term_id, $tt_id );
  2727 	 * @param array $args    Arguments passed to wp_insert_term().
       
  2728 	 */
       
  2729 	do_action( "created_{$taxonomy}", $term_id, $tt_id, $args );
  2645 
  2730 
  2646 	/**
  2731 	/**
  2647 	 * Fires after a term has been saved, and the term cache has been cleared.
  2732 	 * Fires after a term has been saved, and the term cache has been cleared.
  2648 	 *
  2733 	 *
  2649 	 * The {@see 'saved_$taxonomy'} hook is also available for targeting a specific
  2734 	 * The {@see 'saved_$taxonomy'} hook is also available for targeting a specific
  2650 	 * taxonomy.
  2735 	 * taxonomy.
  2651 	 *
  2736 	 *
  2652 	 * @since 5.5.0
  2737 	 * @since 5.5.0
       
  2738 	 * @since 6.1.0 The `$args` parameter was added.
  2653 	 *
  2739 	 *
  2654 	 * @param int    $term_id  Term ID.
  2740 	 * @param int    $term_id  Term ID.
  2655 	 * @param int    $tt_id    Term taxonomy ID.
  2741 	 * @param int    $tt_id    Term taxonomy ID.
  2656 	 * @param string $taxonomy Taxonomy slug.
  2742 	 * @param string $taxonomy Taxonomy slug.
  2657 	 * @param bool   $update   Whether this is an existing term being updated.
  2743 	 * @param bool   $update   Whether this is an existing term being updated.
  2658 	 */
  2744 	 * @param array  $args     Arguments passed to wp_insert_term().
  2659 	do_action( 'saved_term', $term_id, $tt_id, $taxonomy, false );
  2745 	 */
       
  2746 	do_action( 'saved_term', $term_id, $tt_id, $taxonomy, false, $args );
  2660 
  2747 
  2661 	/**
  2748 	/**
  2662 	 * Fires after a term in a specific taxonomy has been saved, and the term
  2749 	 * Fires after a term in a specific taxonomy has been saved, and the term
  2663 	 * cache has been cleared.
  2750 	 * cache has been cleared.
  2664 	 *
  2751 	 *
  2668 	 *
  2755 	 *
  2669 	 *  - `saved_category`
  2756 	 *  - `saved_category`
  2670 	 *  - `saved_post_tag`
  2757 	 *  - `saved_post_tag`
  2671 	 *
  2758 	 *
  2672 	 * @since 5.5.0
  2759 	 * @since 5.5.0
  2673 	 *
  2760 	 * @since 6.1.0 The `$args` parameter was added.
  2674 	 * @param int  $term_id Term ID.
  2761 	 *
  2675 	 * @param int  $tt_id   Term taxonomy ID.
  2762 	 * @param int   $term_id Term ID.
  2676 	 * @param bool $update  Whether this is an existing term being updated.
  2763 	 * @param int   $tt_id   Term taxonomy ID.
  2677 	 */
  2764 	 * @param bool  $update  Whether this is an existing term being updated.
  2678 	do_action( "saved_{$taxonomy}", $term_id, $tt_id, false );
  2765 	 * @param array $args    Arguments passed to wp_insert_term().
       
  2766 	 */
       
  2767 	do_action( "saved_{$taxonomy}", $term_id, $tt_id, false, $args );
  2679 
  2768 
  2680 	return array(
  2769 	return array(
  2681 		'term_id'          => $term_id,
  2770 		'term_id'          => $term_id,
  2682 		'term_taxonomy_id' => $tt_id,
  2771 		'term_taxonomy_id' => $tt_id,
  2683 	);
  2772 	);
  2699  * @global wpdb $wpdb WordPress database abstraction object.
  2788  * @global wpdb $wpdb WordPress database abstraction object.
  2700  *
  2789  *
  2701  * @param int              $object_id The object to relate to.
  2790  * @param int              $object_id The object to relate to.
  2702  * @param string|int|array $terms     A single term slug, single term ID, or array of either term slugs or IDs.
  2791  * @param string|int|array $terms     A single term slug, single term ID, or array of either term slugs or IDs.
  2703  *                                    Will replace all existing related terms in this taxonomy. Passing an
  2792  *                                    Will replace all existing related terms in this taxonomy. Passing an
  2704  *                                    empty value will remove all related terms.
  2793  *                                    empty array will remove all related terms.
  2705  * @param string           $taxonomy  The context in which to relate the term to the object.
  2794  * @param string           $taxonomy  The context in which to relate the term to the object.
  2706  * @param bool             $append    Optional. If false will delete difference of terms. Default false.
  2795  * @param bool             $append    Optional. If false will delete difference of terms. Default false.
  2707  * @return array|WP_Error Term taxonomy IDs of the affected terms or WP_Error on failure.
  2796  * @return array|WP_Error Term taxonomy IDs of the affected terms or WP_Error on failure.
  2708  */
  2797  */
  2709 function wp_set_object_terms( $object_id, $terms, $taxonomy, $append = false ) {
  2798 function wp_set_object_terms( $object_id, $terms, $taxonomy, $append = false ) {
  2713 
  2802 
  2714 	if ( ! taxonomy_exists( $taxonomy ) ) {
  2803 	if ( ! taxonomy_exists( $taxonomy ) ) {
  2715 		return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy.' ) );
  2804 		return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy.' ) );
  2716 	}
  2805 	}
  2717 
  2806 
  2718 	if ( ! is_array( $terms ) ) {
  2807 	if ( empty( $terms ) ) {
       
  2808 		$terms = array();
       
  2809 	} elseif ( ! is_array( $terms ) ) {
  2719 		$terms = array( $terms );
  2810 		$terms = array( $terms );
  2720 	}
  2811 	}
  2721 
  2812 
  2722 	if ( ! $append ) {
  2813 	if ( ! $append ) {
  2723 		$old_tt_ids = wp_get_object_terms(
  2814 		$old_tt_ids = wp_get_object_terms(
  2732 	} else {
  2823 	} else {
  2733 		$old_tt_ids = array();
  2824 		$old_tt_ids = array();
  2734 	}
  2825 	}
  2735 
  2826 
  2736 	$tt_ids     = array();
  2827 	$tt_ids     = array();
  2737 	$term_ids   = array();
       
  2738 	$new_tt_ids = array();
  2828 	$new_tt_ids = array();
  2739 
  2829 
  2740 	foreach ( (array) $terms as $term ) {
  2830 	foreach ( (array) $terms as $term ) {
  2741 		if ( '' === trim( $term ) ) {
  2831 		if ( '' === trim( $term ) ) {
  2742 			continue;
  2832 			continue;
  2755 
  2845 
  2756 		if ( is_wp_error( $term_info ) ) {
  2846 		if ( is_wp_error( $term_info ) ) {
  2757 			return $term_info;
  2847 			return $term_info;
  2758 		}
  2848 		}
  2759 
  2849 
  2760 		$term_ids[] = $term_info['term_id'];
  2850 		$tt_id    = $term_info['term_taxonomy_id'];
  2761 		$tt_id      = $term_info['term_taxonomy_id'];
  2851 		$tt_ids[] = $tt_id;
  2762 		$tt_ids[]   = $tt_id;
       
  2763 
  2852 
  2764 		if ( $wpdb->get_var( $wpdb->prepare( "SELECT term_taxonomy_id FROM $wpdb->term_relationships WHERE object_id = %d AND term_taxonomy_id = %d", $object_id, $tt_id ) ) ) {
  2853 		if ( $wpdb->get_var( $wpdb->prepare( "SELECT term_taxonomy_id FROM $wpdb->term_relationships WHERE object_id = %d AND term_taxonomy_id = %d", $object_id, $tt_id ) ) ) {
  2765 			continue;
  2854 			continue;
  2766 		}
  2855 		}
  2767 
  2856 
  2846 			}
  2935 			}
  2847 		}
  2936 		}
  2848 	}
  2937 	}
  2849 
  2938 
  2850 	wp_cache_delete( $object_id, $taxonomy . '_relationships' );
  2939 	wp_cache_delete( $object_id, $taxonomy . '_relationships' );
  2851 	wp_cache_delete( 'last_changed', 'terms' );
  2940 	wp_cache_set_terms_last_changed();
  2852 
  2941 
  2853 	/**
  2942 	/**
  2854 	 * Fires after an object's terms have been set.
  2943 	 * Fires after an object's terms have been set.
  2855 	 *
  2944 	 *
  2856 	 * @since 2.8.0
  2945 	 * @since 2.8.0
  2944 		do_action( 'delete_term_relationships', $object_id, $tt_ids, $taxonomy );
  3033 		do_action( 'delete_term_relationships', $object_id, $tt_ids, $taxonomy );
  2945 
  3034 
  2946 		$deleted = $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->term_relationships WHERE object_id = %d AND term_taxonomy_id IN ($in_tt_ids)", $object_id ) );
  3035 		$deleted = $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->term_relationships WHERE object_id = %d AND term_taxonomy_id IN ($in_tt_ids)", $object_id ) );
  2947 
  3036 
  2948 		wp_cache_delete( $object_id, $taxonomy . '_relationships' );
  3037 		wp_cache_delete( $object_id, $taxonomy . '_relationships' );
  2949 		wp_cache_delete( 'last_changed', 'terms' );
  3038 		wp_cache_set_terms_last_changed();
  2950 
  3039 
  2951 		/**
  3040 		/**
  2952 		 * Fires immediately after an object-term relationship is deleted.
  3041 		 * Fires immediately after an object-term relationship is deleted.
  2953 		 *
  3042 		 *
  2954 		 * @since 2.9.0
  3043 		 * @since 2.9.0
  3050 
  3139 
  3051 		if ( $wpdb->get_var( $query ) ) { // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
  3140 		if ( $wpdb->get_var( $query ) ) { // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
  3052 			$num = 2;
  3141 			$num = 2;
  3053 			do {
  3142 			do {
  3054 				$alt_slug = $slug . "-$num";
  3143 				$alt_slug = $slug . "-$num";
  3055 				$num++;
  3144 				++$num;
  3056 				$slug_check = $wpdb->get_var( $wpdb->prepare( "SELECT slug FROM $wpdb->terms WHERE slug = %s", $alt_slug ) );
  3145 				$slug_check = $wpdb->get_var( $wpdb->prepare( "SELECT slug FROM $wpdb->terms WHERE slug = %s", $alt_slug ) );
  3057 			} while ( $slug_check );
  3146 			} while ( $slug_check );
  3058 			$slug = $alt_slug;
  3147 			$slug = $alt_slug;
  3059 		}
  3148 		}
  3060 	}
  3149 	}
  3092  *
  3181  *
  3093  * @global wpdb $wpdb WordPress database abstraction object.
  3182  * @global wpdb $wpdb WordPress database abstraction object.
  3094  *
  3183  *
  3095  * @param int          $term_id  The ID of the term.
  3184  * @param int          $term_id  The ID of the term.
  3096  * @param string       $taxonomy The taxonomy of the term.
  3185  * @param string       $taxonomy The taxonomy of the term.
  3097  * @param array|string $args {
  3186  * @param array        $args {
  3098  *     Optional. Array or string of arguments for updating a term.
  3187  *     Optional. Array of arguments for updating a term.
  3099  *
  3188  *
  3100  *     @type string $alias_of    Slug of the term to make this term an alias of.
  3189  *     @type string $alias_of    Slug of the term to make this term an alias of.
  3101  *                               Default empty string. Accepts a term slug.
  3190  *                               Default empty string. Accepts a term slug.
  3102  *     @type string $description The term description. Default empty string.
  3191  *     @type string $description The term description. Default empty string.
  3103  *     @type int    $parent      The id of the parent term. Default 0.
  3192  *     @type int    $parent      The id of the parent term. Default 0.
  3199 	 *
  3288 	 *
  3200 	 * Hook to this filter to see if it will cause a hierarchy loop.
  3289 	 * Hook to this filter to see if it will cause a hierarchy loop.
  3201 	 *
  3290 	 *
  3202 	 * @since 3.1.0
  3291 	 * @since 3.1.0
  3203 	 *
  3292 	 *
  3204 	 * @param int    $parent      ID of the parent term.
  3293 	 * @param int    $parent_term ID of the parent term.
  3205 	 * @param int    $term_id     Term ID.
  3294 	 * @param int    $term_id     Term ID.
  3206 	 * @param string $taxonomy    Taxonomy slug.
  3295 	 * @param string $taxonomy    Taxonomy slug.
  3207 	 * @param array  $parsed_args An array of potentially altered update arguments for the given term.
  3296 	 * @param array  $parsed_args An array of potentially altered update arguments for the given term.
  3208 	 * @param array  $args        An array of update arguments for the given term.
  3297 	 * @param array  $args        Arguments passed to wp_update_term().
  3209 	 */
  3298 	 */
  3210 	$parent = (int) apply_filters( 'wp_update_term_parent', $args['parent'], $term_id, $taxonomy, $parsed_args, $args );
  3299 	$parent = (int) apply_filters( 'wp_update_term_parent', $args['parent'], $term_id, $taxonomy, $parsed_args, $args );
  3211 
  3300 
  3212 	// Check for duplicate slug.
  3301 	// Check for duplicate slug.
  3213 	$duplicate = get_term_by( 'slug', $slug, $taxonomy );
  3302 	$duplicate = get_term_by( 'slug', $slug, $taxonomy );
  3214 	if ( $duplicate && $duplicate->term_id !== $term_id ) {
  3303 	if ( $duplicate && $duplicate->term_id !== $term_id ) {
  3215 		// If an empty slug was passed or the parent changed, reset the slug to something unique.
  3304 		/*
  3216 		// Otherwise, bail.
  3305 		 * If an empty slug was passed or the parent changed, reset the slug to something unique.
       
  3306 		 * Otherwise, bail.
       
  3307 		 */
  3217 		if ( $empty_slug || ( $parent !== (int) $term['parent'] ) ) {
  3308 		if ( $empty_slug || ( $parent !== (int) $term['parent'] ) ) {
  3218 			$slug = wp_unique_term_slug( $slug, (object) $args );
  3309 			$slug = wp_unique_term_slug( $slug, (object) $args );
  3219 		} else {
  3310 		} else {
  3220 			/* translators: %s: Taxonomy term slug. */
  3311 			/* translators: %s: Taxonomy term slug. */
  3221 			return new WP_Error( 'duplicate_term_slug', sprintf( __( 'The slug &#8220;%s&#8221; is already in use by another term.' ), $slug ) );
  3312 			return new WP_Error( 'duplicate_term_slug', sprintf( __( 'The slug &#8220;%s&#8221; is already in use by another term.' ), $slug ) );
  3232 
  3323 
  3233 	/**
  3324 	/**
  3234 	 * Fires immediately before the given terms are edited.
  3325 	 * Fires immediately before the given terms are edited.
  3235 	 *
  3326 	 *
  3236 	 * @since 2.9.0
  3327 	 * @since 2.9.0
       
  3328 	 * @since 6.1.0 The `$args` parameter was added.
  3237 	 *
  3329 	 *
  3238 	 * @param int    $term_id  Term ID.
  3330 	 * @param int    $term_id  Term ID.
  3239 	 * @param string $taxonomy Taxonomy slug.
  3331 	 * @param string $taxonomy Taxonomy slug.
  3240 	 */
  3332 	 * @param array  $args     Arguments passed to wp_update_term().
  3241 	do_action( 'edit_terms', $term_id, $taxonomy );
  3333 	 */
       
  3334 	do_action( 'edit_terms', $term_id, $taxonomy, $args );
  3242 
  3335 
  3243 	$data = compact( 'name', 'slug', 'term_group' );
  3336 	$data = compact( 'name', 'slug', 'term_group' );
  3244 
  3337 
  3245 	/**
  3338 	/**
  3246 	 * Filters term data before it is updated in the database.
  3339 	 * Filters term data before it is updated in the database.
  3264 	/**
  3357 	/**
  3265 	 * Fires immediately after a term is updated in the database, but before its
  3358 	 * Fires immediately after a term is updated in the database, but before its
  3266 	 * term-taxonomy relationship is updated.
  3359 	 * term-taxonomy relationship is updated.
  3267 	 *
  3360 	 *
  3268 	 * @since 2.9.0
  3361 	 * @since 2.9.0
       
  3362 	 * @since 6.1.0 The `$args` parameter was added.
  3269 	 *
  3363 	 *
  3270 	 * @param int    $term_id  Term ID.
  3364 	 * @param int    $term_id  Term ID.
  3271 	 * @param string $taxonomy Taxonomy slug.
  3365 	 * @param string $taxonomy Taxonomy slug.
  3272 	 */
  3366 	 * @param array  $args     Arguments passed to wp_update_term().
  3273 	do_action( 'edited_terms', $term_id, $taxonomy );
  3367 	 */
       
  3368 	do_action( 'edited_terms', $term_id, $taxonomy, $args );
  3274 
  3369 
  3275 	/**
  3370 	/**
  3276 	 * Fires immediate before a term-taxonomy relationship is updated.
  3371 	 * Fires immediate before a term-taxonomy relationship is updated.
  3277 	 *
  3372 	 *
  3278 	 * @since 2.9.0
  3373 	 * @since 2.9.0
       
  3374 	 * @since 6.1.0 The `$args` parameter was added.
  3279 	 *
  3375 	 *
  3280 	 * @param int    $tt_id    Term taxonomy ID.
  3376 	 * @param int    $tt_id    Term taxonomy ID.
  3281 	 * @param string $taxonomy Taxonomy slug.
  3377 	 * @param string $taxonomy Taxonomy slug.
  3282 	 */
  3378 	 * @param array  $args     Arguments passed to wp_update_term().
  3283 	do_action( 'edit_term_taxonomy', $tt_id, $taxonomy );
  3379 	 */
       
  3380 	do_action( 'edit_term_taxonomy', $tt_id, $taxonomy, $args );
  3284 
  3381 
  3285 	$wpdb->update( $wpdb->term_taxonomy, compact( 'term_id', 'taxonomy', 'description', 'parent' ), array( 'term_taxonomy_id' => $tt_id ) );
  3382 	$wpdb->update( $wpdb->term_taxonomy, compact( 'term_id', 'taxonomy', 'description', 'parent' ), array( 'term_taxonomy_id' => $tt_id ) );
  3286 
  3383 
  3287 	/**
  3384 	/**
  3288 	 * Fires immediately after a term-taxonomy relationship is updated.
  3385 	 * Fires immediately after a term-taxonomy relationship is updated.
  3289 	 *
  3386 	 *
  3290 	 * @since 2.9.0
  3387 	 * @since 2.9.0
       
  3388 	 * @since 6.1.0 The `$args` parameter was added.
  3291 	 *
  3389 	 *
  3292 	 * @param int    $tt_id    Term taxonomy ID.
  3390 	 * @param int    $tt_id    Term taxonomy ID.
  3293 	 * @param string $taxonomy Taxonomy slug.
  3391 	 * @param string $taxonomy Taxonomy slug.
  3294 	 */
  3392 	 * @param array  $args     Arguments passed to wp_update_term().
  3295 	do_action( 'edited_term_taxonomy', $tt_id, $taxonomy );
  3393 	 */
       
  3394 	do_action( 'edited_term_taxonomy', $tt_id, $taxonomy, $args );
  3296 
  3395 
  3297 	/**
  3396 	/**
  3298 	 * Fires after a term has been updated, but before the term cache has been cleaned.
  3397 	 * Fires after a term has been updated, but before the term cache has been cleaned.
  3299 	 *
  3398 	 *
  3300 	 * The {@see 'edit_$taxonomy'} hook is also available for targeting a specific
  3399 	 * The {@see 'edit_$taxonomy'} hook is also available for targeting a specific
  3301 	 * taxonomy.
  3400 	 * taxonomy.
  3302 	 *
  3401 	 *
  3303 	 * @since 2.3.0
  3402 	 * @since 2.3.0
       
  3403 	 * @since 6.1.0 The `$args` parameter was added.
  3304 	 *
  3404 	 *
  3305 	 * @param int    $term_id  Term ID.
  3405 	 * @param int    $term_id  Term ID.
  3306 	 * @param int    $tt_id    Term taxonomy ID.
  3406 	 * @param int    $tt_id    Term taxonomy ID.
  3307 	 * @param string $taxonomy Taxonomy slug.
  3407 	 * @param string $taxonomy Taxonomy slug.
  3308 	 */
  3408 	 * @param array  $args     Arguments passed to wp_update_term().
  3309 	do_action( 'edit_term', $term_id, $tt_id, $taxonomy );
  3409 	 */
       
  3410 	do_action( 'edit_term', $term_id, $tt_id, $taxonomy, $args );
  3310 
  3411 
  3311 	/**
  3412 	/**
  3312 	 * Fires after a term in a specific taxonomy has been updated, but before the term
  3413 	 * Fires after a term in a specific taxonomy has been updated, but before the term
  3313 	 * cache has been cleaned.
  3414 	 * cache has been cleaned.
  3314 	 *
  3415 	 *
  3318 	 *
  3419 	 *
  3319 	 *  - `edit_category`
  3420 	 *  - `edit_category`
  3320 	 *  - `edit_post_tag`
  3421 	 *  - `edit_post_tag`
  3321 	 *
  3422 	 *
  3322 	 * @since 2.3.0
  3423 	 * @since 2.3.0
  3323 	 *
  3424 	 * @since 6.1.0 The `$args` parameter was added.
  3324 	 * @param int $term_id Term ID.
  3425 	 *
  3325 	 * @param int $tt_id   Term taxonomy ID.
  3426 	 * @param int   $term_id Term ID.
  3326 	 */
  3427 	 * @param int   $tt_id   Term taxonomy ID.
  3327 	do_action( "edit_{$taxonomy}", $term_id, $tt_id );
  3428 	 * @param array $args    Arguments passed to wp_update_term().
       
  3429 	 */
       
  3430 	do_action( "edit_{$taxonomy}", $term_id, $tt_id, $args );
  3328 
  3431 
  3329 	/** This filter is documented in wp-includes/taxonomy.php */
  3432 	/** This filter is documented in wp-includes/taxonomy.php */
  3330 	$term_id = apply_filters( 'term_id_filter', $term_id, $tt_id );
  3433 	$term_id = apply_filters( 'term_id_filter', $term_id, $tt_id );
  3331 
  3434 
  3332 	clean_term_cache( $term_id, $taxonomy );
  3435 	clean_term_cache( $term_id, $taxonomy );
  3336 	 *
  3439 	 *
  3337 	 * The {@see 'edited_$taxonomy'} hook is also available for targeting a specific
  3440 	 * The {@see 'edited_$taxonomy'} hook is also available for targeting a specific
  3338 	 * taxonomy.
  3441 	 * taxonomy.
  3339 	 *
  3442 	 *
  3340 	 * @since 2.3.0
  3443 	 * @since 2.3.0
       
  3444 	 * @since 6.1.0 The `$args` parameter was added.
  3341 	 *
  3445 	 *
  3342 	 * @param int    $term_id  Term ID.
  3446 	 * @param int    $term_id  Term ID.
  3343 	 * @param int    $tt_id    Term taxonomy ID.
  3447 	 * @param int    $tt_id    Term taxonomy ID.
  3344 	 * @param string $taxonomy Taxonomy slug.
  3448 	 * @param string $taxonomy Taxonomy slug.
  3345 	 */
  3449 	 * @param array  $args     Arguments passed to wp_update_term().
  3346 	do_action( 'edited_term', $term_id, $tt_id, $taxonomy );
  3450 	 */
       
  3451 	do_action( 'edited_term', $term_id, $tt_id, $taxonomy, $args );
  3347 
  3452 
  3348 	/**
  3453 	/**
  3349 	 * Fires after a term for a specific taxonomy has been updated, and the term
  3454 	 * Fires after a term for a specific taxonomy has been updated, and the term
  3350 	 * cache has been cleaned.
  3455 	 * cache has been cleaned.
  3351 	 *
  3456 	 *
  3355 	 *
  3460 	 *
  3356 	 *  - `edited_category`
  3461 	 *  - `edited_category`
  3357 	 *  - `edited_post_tag`
  3462 	 *  - `edited_post_tag`
  3358 	 *
  3463 	 *
  3359 	 * @since 2.3.0
  3464 	 * @since 2.3.0
  3360 	 *
  3465 	 * @since 6.1.0 The `$args` parameter was added.
  3361 	 * @param int $term_id Term ID.
  3466 	 *
  3362 	 * @param int $tt_id   Term taxonomy ID.
  3467 	 * @param int   $term_id Term ID.
  3363 	 */
  3468 	 * @param int   $tt_id   Term taxonomy ID.
  3364 	do_action( "edited_{$taxonomy}", $term_id, $tt_id );
  3469 	 * @param array $args    Arguments passed to wp_update_term().
       
  3470 	 */
       
  3471 	do_action( "edited_{$taxonomy}", $term_id, $tt_id, $args );
  3365 
  3472 
  3366 	/** This action is documented in wp-includes/taxonomy.php */
  3473 	/** This action is documented in wp-includes/taxonomy.php */
  3367 	do_action( 'saved_term', $term_id, $tt_id, $taxonomy, true );
  3474 	do_action( 'saved_term', $term_id, $tt_id, $taxonomy, true, $args );
  3368 
  3475 
  3369 	/** This action is documented in wp-includes/taxonomy.php */
  3476 	/** This action is documented in wp-includes/taxonomy.php */
  3370 	do_action( "saved_{$taxonomy}", $term_id, $tt_id, true );
  3477 	do_action( "saved_{$taxonomy}", $term_id, $tt_id, true, $args );
  3371 
  3478 
  3372 	return array(
  3479 	return array(
  3373 		'term_id'          => $term_id,
  3480 		'term_id'          => $term_id,
  3374 		'term_taxonomy_id' => $tt_id,
  3481 		'term_taxonomy_id' => $tt_id,
  3375 	);
  3482 	);
  3458 	if ( ! empty( $taxonomy->update_count_callback ) ) {
  3565 	if ( ! empty( $taxonomy->update_count_callback ) ) {
  3459 		call_user_func( $taxonomy->update_count_callback, $terms, $taxonomy );
  3566 		call_user_func( $taxonomy->update_count_callback, $terms, $taxonomy );
  3460 	} else {
  3567 	} else {
  3461 		$object_types = (array) $taxonomy->object_type;
  3568 		$object_types = (array) $taxonomy->object_type;
  3462 		foreach ( $object_types as &$object_type ) {
  3569 		foreach ( $object_types as &$object_type ) {
  3463 			if ( 0 === strpos( $object_type, 'attachment:' ) ) {
  3570 			if ( str_starts_with( $object_type, 'attachment:' ) ) {
  3464 				list( $object_type ) = explode( ':', $object_type );
  3571 				list( $object_type ) = explode( ':', $object_type );
  3465 			}
  3572 			}
  3466 		}
  3573 		}
  3467 
  3574 
  3468 		if ( array_filter( $object_types, 'post_type_exists' ) == $object_types ) {
  3575 		if ( array_filter( $object_types, 'post_type_exists' ) == $object_types ) {
  3514 
  3621 
  3515 	foreach ( $taxonomies as $taxonomy ) {
  3622 	foreach ( $taxonomies as $taxonomy ) {
  3516 		wp_cache_delete_multiple( $object_ids, "{$taxonomy}_relationships" );
  3623 		wp_cache_delete_multiple( $object_ids, "{$taxonomy}_relationships" );
  3517 	}
  3624 	}
  3518 
  3625 
  3519 	wp_cache_delete( 'last_changed', 'terms' );
  3626 	wp_cache_set_terms_last_changed();
  3520 
  3627 
  3521 	/**
  3628 	/**
  3522 	 * Fires after the object term cache has been cleaned.
  3629 	 * Fires after the object term cache has been cleaned.
  3523 	 *
  3630 	 *
  3524 	 * @since 2.5.0
  3631 	 * @since 2.5.0
  3589 		 * @param bool   $clean_taxonomy Whether or not to clean taxonomy-wide caches
  3696 		 * @param bool   $clean_taxonomy Whether or not to clean taxonomy-wide caches
  3590 		 */
  3697 		 */
  3591 		do_action( 'clean_term_cache', $ids, $taxonomy, $clean_taxonomy );
  3698 		do_action( 'clean_term_cache', $ids, $taxonomy, $clean_taxonomy );
  3592 	}
  3699 	}
  3593 
  3700 
  3594 	wp_cache_set( 'last_changed', microtime(), 'terms' );
  3701 	wp_cache_set_terms_last_changed();
  3595 }
  3702 }
  3596 
  3703 
  3597 /**
  3704 /**
  3598  * Cleans the caches for a taxonomy.
  3705  * Cleans the caches for a taxonomy.
  3599  *
  3706  *
  3602  * @param string $taxonomy Taxonomy slug.
  3709  * @param string $taxonomy Taxonomy slug.
  3603  */
  3710  */
  3604 function clean_taxonomy_cache( $taxonomy ) {
  3711 function clean_taxonomy_cache( $taxonomy ) {
  3605 	wp_cache_delete( 'all_ids', $taxonomy );
  3712 	wp_cache_delete( 'all_ids', $taxonomy );
  3606 	wp_cache_delete( 'get', $taxonomy );
  3713 	wp_cache_delete( 'get', $taxonomy );
  3607 	wp_cache_delete( 'last_changed', 'terms' );
  3714 	wp_cache_set_terms_last_changed();
  3608 
  3715 
  3609 	// Regenerate cached hierarchy.
  3716 	// Regenerate cached hierarchy.
  3610 	delete_option( "{$taxonomy}_children" );
  3717 	delete_option( "{$taxonomy}_children" );
  3611 	_get_term_hierarchy( $taxonomy );
  3718 	_get_term_hierarchy( $taxonomy );
  3612 
  3719 
  3974 
  4081 
  3975 /**
  4082 /**
  3976  * Adds any terms from the given IDs to the cache that do not already exist in cache.
  4083  * Adds any terms from the given IDs to the cache that do not already exist in cache.
  3977  *
  4084  *
  3978  * @since 4.6.0
  4085  * @since 4.6.0
  3979  * @access private
  4086  * @since 6.1.0 This function is no longer marked as "private".
       
  4087  * @since 6.3.0 Use wp_lazyload_term_meta() for lazy-loading of term meta.
  3980  *
  4088  *
  3981  * @global wpdb $wpdb WordPress database abstraction object.
  4089  * @global wpdb $wpdb WordPress database abstraction object.
  3982  *
  4090  *
  3983  * @param array $term_ids          Array of term IDs.
  4091  * @param array $term_ids          Array of term IDs.
  3984  * @param bool  $update_meta_cache Optional. Whether to update the meta cache. Default true.
  4092  * @param bool  $update_meta_cache Optional. Whether to update the meta cache. Default true.
  3989 	$non_cached_ids = _get_non_cached_ids( $term_ids, 'terms' );
  4097 	$non_cached_ids = _get_non_cached_ids( $term_ids, 'terms' );
  3990 	if ( ! empty( $non_cached_ids ) ) {
  4098 	if ( ! empty( $non_cached_ids ) ) {
  3991 		$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 ) ) ) );
  4099 		$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 ) ) ) );
  3992 
  4100 
  3993 		update_term_cache( $fresh_terms );
  4101 		update_term_cache( $fresh_terms );
  3994 
  4102 	}
  3995 		if ( $update_meta_cache ) {
  4103 
  3996 			update_termmeta_cache( $non_cached_ids );
  4104 	if ( $update_meta_cache ) {
  3997 		}
  4105 		wp_lazyload_term_meta( $term_ids );
  3998 	}
  4106 	}
  3999 }
  4107 }
  4000 
  4108 
  4001 //
  4109 //
  4002 // Default callbacks.
  4110 // Default callbacks.
  4260 	global $wpdb;
  4368 	global $wpdb;
  4261 
  4369 
  4262 	$lock_name = 'term_split.lock';
  4370 	$lock_name = 'term_split.lock';
  4263 
  4371 
  4264 	// Try to lock.
  4372 	// Try to lock.
  4265 	$lock_result = $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO `$wpdb->options` ( `option_name`, `option_value`, `autoload` ) VALUES (%s, %s, 'no') /* LOCK */", $lock_name, time() ) );
  4373 	$lock_result = $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO `$wpdb->options` ( `option_name`, `option_value`, `autoload` ) VALUES (%s, %s, 'off') /* LOCK */", $lock_name, time() ) );
  4266 
  4374 
  4267 	if ( ! $lock_result ) {
  4375 	if ( ! $lock_result ) {
  4268 		$lock_result = get_option( $lock_name );
  4376 		$lock_result = get_option( $lock_name );
  4269 
  4377 
  4270 		// Bail if we were unable to create a lock, or if the existing lock is still valid.
  4378 		// Bail if we were unable to create a lock, or if the existing lock is still valid.
  4490  * Shared taxonomy terms began to be split in 4.3, but failed cron tasks or
  4598  * Shared taxonomy terms began to be split in 4.3, but failed cron tasks or
  4491  * other delays in upgrade routines may cause shared terms to remain.
  4599  * other delays in upgrade routines may cause shared terms to remain.
  4492  *
  4600  *
  4493  * @since 4.4.0
  4601  * @since 4.4.0
  4494  *
  4602  *
       
  4603  * @global wpdb $wpdb WordPress database abstraction object.
       
  4604  *
  4495  * @param int $term_id Term ID.
  4605  * @param int $term_id Term ID.
  4496  * @return bool Returns false if a term is not shared between multiple taxonomies or
  4606  * @return bool Returns false if a term is not shared between multiple taxonomies or
  4497  *              if splitting shared taxonomy terms is finished.
  4607  *              if splitting shared taxonomy terms is finished.
  4498  */
  4608  */
  4499 function wp_term_is_shared( $term_id ) {
  4609 function wp_term_is_shared( $term_id ) {
  4669  *     @type string $template      Template for displaying a taxonomy label and list of terms.
  4779  *     @type string $template      Template for displaying a taxonomy label and list of terms.
  4670  *                                 Default is "Label: Terms."
  4780  *                                 Default is "Label: Terms."
  4671  *     @type string $term_template Template for displaying a single term in the list. Default is the term name
  4781  *     @type string $term_template Template for displaying a single term in the list. Default is the term name
  4672  *                                 linked to its archive.
  4782  *                                 linked to its archive.
  4673  * }
  4783  * }
  4674  * @return array List of taxonomies.
  4784  * @return string[] List of taxonomies.
  4675  */
  4785  */
  4676 function get_the_taxonomies( $post = 0, $args = array() ) {
  4786 function get_the_taxonomies( $post = 0, $args = array() ) {
  4677 	$post = get_post( $post );
  4787 	$post = get_post( $post );
  4678 
  4788 
  4679 	$args = wp_parse_args(
  4789 	$args = wp_parse_args(
  4907  *
  5017  *
  4908  * Attached to the {@see 'wp_update_term_parent'} filter.
  5018  * Attached to the {@see 'wp_update_term_parent'} filter.
  4909  *
  5019  *
  4910  * @since 3.1.0
  5020  * @since 3.1.0
  4911  *
  5021  *
  4912  * @param int    $parent   `term_id` of the parent for the term we're checking.
  5022  * @param int    $parent_term `term_id` of the parent for the term we're checking.
  4913  * @param int    $term_id  The term we're checking.
  5023  * @param int    $term_id     The term we're checking.
  4914  * @param string $taxonomy The taxonomy of the term we're checking.
  5024  * @param string $taxonomy    The taxonomy of the term we're checking.
  4915  * @return int The new parent for the term.
  5025  * @return int The new parent for the term.
  4916  */
  5026  */
  4917 function wp_check_term_hierarchy_for_loops( $parent, $term_id, $taxonomy ) {
  5027 function wp_check_term_hierarchy_for_loops( $parent_term, $term_id, $taxonomy ) {
  4918 	// Nothing fancy here - bail.
  5028 	// Nothing fancy here - bail.
  4919 	if ( ! $parent ) {
  5029 	if ( ! $parent_term ) {
  4920 		return 0;
  5030 		return 0;
  4921 	}
  5031 	}
  4922 
  5032 
  4923 	// Can't be its own parent.
  5033 	// Can't be its own parent.
  4924 	if ( $parent === $term_id ) {
  5034 	if ( $parent_term === $term_id ) {
  4925 		return 0;
  5035 		return 0;
  4926 	}
  5036 	}
  4927 
  5037 
  4928 	// Now look for larger loops.
  5038 	// Now look for larger loops.
  4929 	$loop = wp_find_hierarchy_loop( 'wp_get_term_taxonomy_parent_id', $term_id, $parent, array( $taxonomy ) );
  5039 	$loop = wp_find_hierarchy_loop( 'wp_get_term_taxonomy_parent_id', $term_id, $parent_term, array( $taxonomy ) );
  4930 	if ( ! $loop ) {
  5040 	if ( ! $loop ) {
  4931 		return $parent; // No loop.
  5041 		return $parent_term; // No loop.
  4932 	}
  5042 	}
  4933 
  5043 
  4934 	// Setting $parent to the given value causes a loop.
  5044 	// Setting $parent_term to the given value causes a loop.
  4935 	if ( isset( $loop[ $term_id ] ) ) {
  5045 	if ( isset( $loop[ $term_id ] ) ) {
  4936 		return 0;
  5046 		return 0;
  4937 	}
  5047 	}
  4938 
  5048 
  4939 	// There's a loop, but it doesn't contain $term_id. Break the loop.
  5049 	// There's a loop, but it doesn't contain $term_id. Break the loop.
  4940 	foreach ( array_keys( $loop ) as $loop_member ) {
  5050 	foreach ( array_keys( $loop ) as $loop_member ) {
  4941 		wp_update_term( $loop_member, $taxonomy, array( 'parent' => 0 ) );
  5051 		wp_update_term( $loop_member, $taxonomy, array( 'parent' => 0 ) );
  4942 	}
  5052 	}
  4943 
  5053 
  4944 	return $parent;
  5054 	return $parent_term;
  4945 }
  5055 }
  4946 
  5056 
  4947 /**
  5057 /**
  4948  * Determines whether a taxonomy is considered "viewable".
  5058  * Determines whether a taxonomy is considered "viewable".
  4949  *
  5059  *
  4962 
  5072 
  4963 	return $taxonomy->publicly_queryable;
  5073 	return $taxonomy->publicly_queryable;
  4964 }
  5074 }
  4965 
  5075 
  4966 /**
  5076 /**
       
  5077  * Determines whether a term is publicly viewable.
       
  5078  *
       
  5079  * A term is considered publicly viewable if its taxonomy is viewable.
       
  5080  *
       
  5081  * @since 6.1.0
       
  5082  *
       
  5083  * @param int|WP_Term $term Term ID or term object.
       
  5084  * @return bool Whether the term is publicly viewable.
       
  5085  */
       
  5086 function is_term_publicly_viewable( $term ) {
       
  5087 	$term = get_term( $term );
       
  5088 
       
  5089 	if ( ! $term ) {
       
  5090 		return false;
       
  5091 	}
       
  5092 
       
  5093 	return is_taxonomy_viewable( $term->taxonomy );
       
  5094 }
       
  5095 
       
  5096 /**
  4967  * Sets the last changed time for the 'terms' cache group.
  5097  * Sets the last changed time for the 'terms' cache group.
  4968  *
  5098  *
  4969  * @since 5.0.0
  5099  * @since 5.0.0
  4970  */
  5100  */
  4971 function wp_cache_set_terms_last_changed() {
  5101 function wp_cache_set_terms_last_changed() {
  4972 	wp_cache_set( 'last_changed', microtime(), 'terms' );
  5102 	wp_cache_set_last_changed( 'terms' );
  4973 }
  5103 }
  4974 
  5104 
  4975 /**
  5105 /**
  4976  * Aborts calls to term meta if it is not supported.
  5106  * Aborts calls to term meta if it is not supported.
  4977  *
  5107  *