wp/wp-includes/taxonomy.php
changeset 19 3d72ae0968f4
parent 18 be944660c56a
child 21 48c4eec2b7e6
--- a/wp/wp-includes/taxonomy.php	Wed Sep 21 18:19:35 2022 +0200
+++ b/wp/wp-includes/taxonomy.php	Tue Sep 27 16:37:53 2022 +0200
@@ -18,12 +18,15 @@
  * avoid registering rewrite rules before the {@see 'init'} action.
  *
  * @since 2.8.0
+ * @since 5.9.0 Added `'wp_template_part_area'` taxonomy.
  *
  * @global WP_Rewrite $wp_rewrite WordPress rewrite component.
  */
 function create_initial_taxonomies() {
 	global $wp_rewrite;
 
+	WP_Taxonomy::reset_default_labels();
+
 	if ( ! did_action( 'init' ) ) {
 		$rewrite = array(
 			'category'    => false,
@@ -107,17 +110,26 @@
 		'nav_menu',
 		'nav_menu_item',
 		array(
-			'public'            => false,
-			'hierarchical'      => false,
-			'labels'            => array(
+			'public'                => false,
+			'hierarchical'          => false,
+			'labels'                => array(
 				'name'          => __( 'Navigation Menus' ),
 				'singular_name' => __( 'Navigation Menu' ),
 			),
-			'query_var'         => false,
-			'rewrite'           => false,
-			'show_ui'           => false,
-			'_builtin'          => true,
-			'show_in_nav_menus' => false,
+			'query_var'             => false,
+			'rewrite'               => false,
+			'show_ui'               => false,
+			'_builtin'              => true,
+			'show_in_nav_menus'     => false,
+			'capabilities'          => array(
+				'manage_terms' => 'edit_theme_options',
+				'edit_terms'   => 'edit_theme_options',
+				'delete_terms' => 'edit_theme_options',
+				'assign_terms' => 'edit_theme_options',
+			),
+			'show_in_rest'          => true,
+			'rest_base'             => 'menus',
+			'rest_controller_class' => 'WP_REST_Menus_Controller',
 		)
 	);
 
@@ -175,7 +187,7 @@
 
 	register_taxonomy(
 		'wp_theme',
-		array( 'wp_template' ),
+		array( 'wp_template', 'wp_template_part', 'wp_global_styles' ),
 		array(
 			'public'            => false,
 			'hierarchical'      => false,
@@ -191,6 +203,25 @@
 			'show_in_rest'      => false,
 		)
 	);
+
+	register_taxonomy(
+		'wp_template_part_area',
+		array( 'wp_template_part' ),
+		array(
+			'public'            => false,
+			'hierarchical'      => false,
+			'labels'            => array(
+				'name'          => __( 'Template Part Areas' ),
+				'singular_name' => __( 'Template Part Area' ),
+			),
+			'query_var'         => false,
+			'rewrite'           => false,
+			'show_ui'           => false,
+			'_builtin'          => true,
+			'show_in_nav_menus' => false,
+			'show_in_rest'      => false,
+		)
+	);
 }
 
 /**
@@ -198,7 +229,7 @@
  *
  * @since 3.0.0
  *
- * @global array $wp_taxonomies The registered taxonomies.
+ * @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies.
  *
  * @param array  $args     Optional. An array of `key => value` arguments to match against the taxonomy objects.
  *                         Default empty array.
@@ -218,8 +249,8 @@
 }
 
 /**
- * Return the names or objects of the taxonomies which are registered for the requested object or object type, such as
- * a post object or post type name.
+ * Returns the names or objects of the taxonomies which are registered for the requested object or object type,
+ * such as a post object or post type name.
  *
  * Example:
  *
@@ -231,7 +262,7 @@
  *
  * @since 2.3.0
  *
- * @global array $wp_taxonomies The registered taxonomies.
+ * @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies.
  *
  * @param string|string[]|WP_Post $object Name of the type of taxonomy object, or an object (row from posts)
  * @param string                  $output Optional. The type of output to return in the array. Accepts either
@@ -272,10 +303,10 @@
  *
  * @since 2.3.0
  *
- * @global array $wp_taxonomies The registered taxonomies.
+ * @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies.
  *
  * @param string $taxonomy Name of taxonomy object to return.
- * @return WP_Taxonomy|false The Taxonomy Object or false if $taxonomy doesn't exist.
+ * @return WP_Taxonomy|false The taxonomy object or false if $taxonomy doesn't exist.
  */
 function get_taxonomy( $taxonomy ) {
 	global $wp_taxonomies;
@@ -298,7 +329,7 @@
  *
  * @since 3.0.0
  *
- * @global array $wp_taxonomies The registered taxonomies.
+ * @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies.
  *
  * @param string $taxonomy Name of taxonomy object.
  * @return bool Whether the taxonomy exists.
@@ -351,12 +382,13 @@
  * @since 4.4.0 The `public` argument now controls whether the taxonomy can be queried on the front end.
  * @since 4.5.0 Introduced `publicly_queryable` argument.
  * @since 4.7.0 Introduced `show_in_rest`, 'rest_base' and 'rest_controller_class'
- *              arguments to register the Taxonomy in REST API.
+ *              arguments to register the taxonomy in REST API.
  * @since 5.1.0 Introduced `meta_box_sanitize_cb` argument.
  * @since 5.4.0 Added the registered taxonomy object as a return value.
  * @since 5.5.0 Introduced `default_term` argument.
- *
- * @global array $wp_taxonomies Registered taxonomies.
+ * @since 5.9.0 Introduced `rest_namespace` argument.
+ *
+ * @global WP_Taxonomy[] $wp_taxonomies Registered taxonomies.
  *
  * @param string       $taxonomy    Taxonomy key, must not exceed 32 characters.
  * @param array|string $object_type Object type or array of object types with which the taxonomy should be associated.
@@ -387,6 +419,7 @@
  *     @type bool          $show_in_rest          Whether to include the taxonomy in the REST API. Set this to true
  *                                                for the taxonomy to be available in the block editor.
  *     @type string        $rest_base             To change the base url of REST API route. Default is $taxonomy.
+ *     @type string        $rest_namespace        To change the namespace URL of REST API route. Default is wp/v2.
  *     @type string        $rest_controller_class REST API Controller class name. Default is 'WP_REST_Terms_Controller'.
  *     @type bool          $show_tagcloud         Whether to list the taxonomy in the Tag Cloud Widget controls. If not set,
  *                                                the default is inherited from `$show_ui` (default true).
@@ -496,6 +529,24 @@
 	 */
 	do_action( 'registered_taxonomy', $taxonomy, $object_type, (array) $taxonomy_object );
 
+	/**
+	 * Fires after a specific taxonomy is registered.
+	 *
+	 * The dynamic portion of the filter name, `$taxonomy`, refers to the taxonomy key.
+	 *
+	 * Possible hook names include:
+	 *
+	 *  - `registered_taxonomy_category`
+	 *  - `registered_taxonomy_post_tag`
+	 *
+	 * @since 6.0.0
+	 *
+	 * @param string       $taxonomy    Taxonomy slug.
+	 * @param array|string $object_type Object type or array of object types.
+	 * @param array        $args        Array of taxonomy registration arguments.
+	 */
+	do_action( "registered_taxonomy_{$taxonomy}", $taxonomy, $object_type, (array) $taxonomy_object );
+
 	return $taxonomy_object;
 }
 
@@ -507,7 +558,7 @@
  * @since 4.5.0
  *
  * @global WP    $wp            Current WordPress environment instance.
- * @global array $wp_taxonomies List of taxonomies.
+ * @global WP_Taxonomy[] $wp_taxonomies List of taxonomies.
  *
  * @param string $taxonomy Taxonomy name.
  * @return true|WP_Error True on success, WP_Error on failure or if the taxonomy doesn't exist.
@@ -558,6 +609,8 @@
  * @since 4.9.0 Added the `most_used` and `back_to_items` labels.
  * @since 5.7.0 Added the `filter_by_item` label.
  * @since 5.8.0 Added the `item_link` and `item_link_description` labels.
+ * @since 5.9.0 Added the `name_field_description`, `slug_field_description`,
+ *              `parent_field_description`, and `desc_field_description` labels.
  *
  * @param WP_Taxonomy $tax Taxonomy object.
  * @return object {
@@ -574,6 +627,19 @@
  *     @type string $parent_item                This label is only used for hierarchical taxonomies. Default
  *                                              'Parent Category'.
  *     @type string $parent_item_colon          The same as `parent_item`, but with colon `:` in the end.
+ *     @type string $name_field_description     Description for the Name field on Edit Tags screen.
+ *                                              Default 'The name is how it appears on your site'.
+ *     @type string $slug_field_description     Description for the Slug field on Edit Tags screen.
+ *                                              Default 'The “slug” is the URL-friendly version
+ *                                              of the name. It is usually all lowercase and contains
+ *                                              only letters, numbers, and hyphens'.
+ *     @type string $parent_field_description   Description for the Parent field on Edit Tags screen.
+ *                                              Default 'Assign a parent term to create a hierarchy.
+ *                                              The term Jazz, for example, would be the parent
+ *                                              of Bebop and Big Band'.
+ *     @type string $desc_field_description     Description for the Description field on Edit Tags screen.
+ *                                              Default 'The description is not prominent by default;
+ *                                              however, some themes may show it'.
  *     @type string $edit_item                  Default 'Edit Tag'/'Edit Category'.
  *     @type string $view_item                  Default 'View Tag'/'View Category'.
  *     @type string $update_item                Default 'Update Tag'/'Update Category'.
@@ -613,39 +679,7 @@
 		$tax->labels['not_found'] = $tax->no_tagcloud;
 	}
 
-	$nohier_vs_hier_defaults = array(
-		'name'                       => array( _x( 'Tags', 'taxonomy general name' ), _x( 'Categories', 'taxonomy general name' ) ),
-		'singular_name'              => array( _x( 'Tag', 'taxonomy singular name' ), _x( 'Category', 'taxonomy singular name' ) ),
-		'search_items'               => array( __( 'Search Tags' ), __( 'Search Categories' ) ),
-		'popular_items'              => array( __( 'Popular Tags' ), null ),
-		'all_items'                  => array( __( 'All Tags' ), __( 'All Categories' ) ),
-		'parent_item'                => array( null, __( 'Parent Category' ) ),
-		'parent_item_colon'          => array( null, __( 'Parent Category:' ) ),
-		'edit_item'                  => array( __( 'Edit Tag' ), __( 'Edit Category' ) ),
-		'view_item'                  => array( __( 'View Tag' ), __( 'View Category' ) ),
-		'update_item'                => array( __( 'Update Tag' ), __( 'Update Category' ) ),
-		'add_new_item'               => array( __( 'Add New Tag' ), __( 'Add New Category' ) ),
-		'new_item_name'              => array( __( 'New Tag Name' ), __( 'New Category Name' ) ),
-		'separate_items_with_commas' => array( __( 'Separate tags with commas' ), null ),
-		'add_or_remove_items'        => array( __( 'Add or remove tags' ), null ),
-		'choose_from_most_used'      => array( __( 'Choose from the most used tags' ), null ),
-		'not_found'                  => array( __( 'No tags found.' ), __( 'No categories found.' ) ),
-		'no_terms'                   => array( __( 'No tags' ), __( 'No categories' ) ),
-		'filter_by_item'             => array( null, __( 'Filter by category' ) ),
-		'items_list_navigation'      => array( __( 'Tags list navigation' ), __( 'Categories list navigation' ) ),
-		'items_list'                 => array( __( 'Tags list' ), __( 'Categories list' ) ),
-		/* translators: Tab heading when selecting from the most used terms. */
-		'most_used'                  => array( _x( 'Most Used', 'tags' ), _x( 'Most Used', 'categories' ) ),
-		'back_to_items'              => array( __( '← Go to Tags' ), __( '← Go to Categories' ) ),
-		'item_link'                  => array(
-			_x( 'Tag Link', 'navigation link block title' ),
-			_x( 'Category Link', 'navigation link block description' ),
-		),
-		'item_link_description'      => array(
-			_x( 'A link to a tag.', 'navigation link block description' ),
-			_x( 'A link to a category.', 'navigation link block description' ),
-		),
-	);
+	$nohier_vs_hier_defaults = WP_Taxonomy::get_default_labels();
 
 	$nohier_vs_hier_defaults['menu_name'] = $nohier_vs_hier_defaults['name'];
 
@@ -680,11 +714,11 @@
 }
 
 /**
- * Add an already registered taxonomy to an object type.
+ * Adds an already registered taxonomy to an object type.
  *
  * @since 3.0.0
  *
- * @global array $wp_taxonomies The registered taxonomies.
+ * @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies.
  *
  * @param string $taxonomy    Name of taxonomy object.
  * @param string $object_type Name of the object type.
@@ -722,11 +756,11 @@
 }
 
 /**
- * Remove an already registered taxonomy from an object type.
+ * Removes an already registered taxonomy from an object type.
  *
  * @since 3.7.0
  *
- * @global array $wp_taxonomies The registered taxonomies.
+ * @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies.
  *
  * @param string $taxonomy    Name of taxonomy object.
  * @param string $object_type Name of the object type.
@@ -768,28 +802,26 @@
 //
 
 /**
- * Retrieve object_ids of valid taxonomy and term.
- *
- * The strings of $taxonomies must exist before this function will continue.
- * On failure of finding a valid taxonomy, it will return a WP_Error class,
- * kind of like Exceptions in PHP 5, except you can't catch them. Even so,
- * you can still test for the WP_Error class and get the error message.
- *
- * The $terms aren't checked the same as $taxonomies, but still need to exist
- * for $object_ids to be returned.
- *
- * It is possible to change the order that object_ids is returned by either
- * using PHP sort family functions or using the database by using $args with
- * either ASC or DESC array. The value should be in the key named 'order'.
+ * Retrieves object IDs of valid taxonomy and term.
+ *
+ * The strings of `$taxonomies` must exist before this function will continue.
+ * On failure of finding a valid taxonomy, it will return a WP_Error.
+ *
+ * The `$terms` aren't checked the same as `$taxonomies`, but still need to exist
+ * for object IDs to be returned.
+ *
+ * It is possible to change the order that object IDs are returned by using `$args`
+ * with either ASC or DESC array. The value should be in the key named 'order'.
  *
  * @since 2.3.0
  *
  * @global wpdb $wpdb WordPress database abstraction object.
  *
- * @param int|array    $term_ids   Term ID or array of term IDs of terms that will be used.
- * @param string|array $taxonomies String of taxonomy name or Array of string values of taxonomy names.
- * @param array|string $args       Change the order of the object_ids, either ASC or DESC.
- * @return array|WP_Error An array of $object_ids on success, WP_Error if the taxonomy does not exist.
+ * @param int|int[]       $term_ids   Term ID or array of term IDs of terms that will be used.
+ * @param string|string[] $taxonomies String of taxonomy name or Array of string values of taxonomy names.
+ * @param array|string    $args       Change the order of the object IDs, either ASC or DESC.
+ * @return string[]|WP_Error An array of object IDs as numeric strings on success,
+ *                           WP_Error if the taxonomy does not exist.
  */
 function get_objects_in_term( $term_ids, $taxonomies, $args = array() ) {
 	global $wpdb;
@@ -844,7 +876,7 @@
  * @param array  $tax_query         A compact tax query
  * @param string $primary_table
  * @param string $primary_id_column
- * @return array
+ * @return string[]
  */
 function get_tax_sql( $tax_query, $primary_table, $primary_id_column ) {
 	$tax_query_obj = new WP_Tax_Query( $tax_query );
@@ -852,7 +884,7 @@
 }
 
 /**
- * Get all Term data from database by Term ID.
+ * Gets all term data from database by term ID.
  *
  * The usage of the get_term function is to apply filters to a term object. It
  * is possible to get a term object from the database before applying the
@@ -865,7 +897,7 @@
  * There are two hooks, one is specifically for each term, named 'get_term', and
  * the second is for the taxonomy name, 'term_$taxonomy'. Both hooks gets the
  * term object, and the taxonomy name as parameters. Both hooks are expected to
- * return a Term object.
+ * return a term object.
  *
  * {@see 'get_term'} hook - Takes two parameters the term Object and the taxonomy name.
  * Must return term object. Used in get_term() as a catch-all filter for every
@@ -945,9 +977,14 @@
 	/**
 	 * Filters a taxonomy term object.
 	 *
-	 * The dynamic portion of the filter name, `$taxonomy`, refers
+	 * The dynamic portion of the hook name, `$taxonomy`, refers
 	 * to the slug of the term's taxonomy.
 	 *
+	 * Possible hook names include:
+	 *
+	 *  - `get_category`
+	 *  - `get_post_tag`
+	 *
 	 * @since 2.3.0
 	 * @since 4.4.0 `$_term` is now a `WP_Term` object.
 	 *
@@ -974,7 +1011,7 @@
 }
 
 /**
- * Get all Term data from database by Term field and data.
+ * Gets all term data from database by term field and data.
  *
  * Warning: $value is not escaped for 'name' $field. You must do it yourself, if
  * required.
@@ -983,7 +1020,7 @@
  * field, but not recommended that you do so.
  *
  * If $value does not exist, the return value will be false. If $taxonomy exists
- * and $field and $value combinations exist, the Term will be returned.
+ * and $field and $value combinations exist, the term will be returned.
  *
  * This function will always return the first term that matches the `$field`-
  * `$value`-`$taxonomy` combination specified in the parameters. If your query
@@ -1001,7 +1038,7 @@
  *
  * @see sanitize_term_field() The $context param lists the available values for get_term_by() $filter param.
  *
- * @param string     $field    Either 'slug', 'name', 'id' or 'ID' (term_id), or 'term_taxonomy_id'.
+ * @param string     $field    Either 'slug', 'name', 'term_id' (or 'id', 'ID'), or 'term_taxonomy_id'.
  * @param string|int $value    Search for this term value.
  * @param string     $taxonomy Taxonomy name. Optional, if `$field` is 'term_taxonomy_id'.
  * @param string     $output   Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which
@@ -1075,7 +1112,7 @@
 }
 
 /**
- * Merge all term children into a single array of their IDs.
+ * Merges all term children into a single array of their IDs.
  *
  * This recursive function will merge all of the children of $term into the same
  * array of term IDs. Only useful for taxonomies which are hierarchical.
@@ -1084,9 +1121,9 @@
  *
  * @since 2.3.0
  *
- * @param int    $term_id  ID of Term to get children.
- * @param string $taxonomy Taxonomy Name.
- * @return array|WP_Error List of Term IDs. WP_Error returned if `$taxonomy` does not exist.
+ * @param int    $term_id  ID of term to get children.
+ * @param string $taxonomy Taxonomy name.
+ * @return array|WP_Error List of term IDs. WP_Error returned if `$taxonomy` does not exist.
  */
 function get_term_children( $term_id, $taxonomy ) {
 	if ( ! taxonomy_exists( $taxonomy ) ) {
@@ -1117,7 +1154,7 @@
 }
 
 /**
- * Get sanitized Term field.
+ * Gets sanitized term field.
  *
  * The function is for contextual reasons and for simplicity of usage.
  *
@@ -1128,7 +1165,7 @@
  *
  * @param string      $field    Term field to fetch.
  * @param int|WP_Term $term     Term ID or object.
- * @param string      $taxonomy Optional. Taxonomy Name. Default empty.
+ * @param string      $taxonomy Optional. Taxonomy name. Default empty.
  * @param string      $context  Optional. How to sanitize term fields. Look at sanitize_term_field() for available options.
  *                              Default 'display'.
  * @return string|int|null|WP_Error Will return an empty string if $term is not an object or if $field is not set in $term.
@@ -1151,7 +1188,7 @@
 }
 
 /**
- * Sanitizes Term for editing.
+ * Sanitizes term for editing.
  *
  * Return value is sanitize_term() and usage is for sanitizing the term for
  * editing. Function is for contextual and simplicity.
@@ -1290,7 +1327,7 @@
 	 * @since 4.6.0 Added the `$term_query` parameter.
 	 *
 	 * @param array         $terms      Array of found terms.
-	 * @param array         $taxonomies An array of taxonomies.
+	 * @param array|null    $taxonomies An array of taxonomies if known.
 	 * @param array         $args       An array of get_terms() arguments.
 	 * @param WP_Term_Query $term_query The WP_Term_Query object.
 	 */
@@ -1398,7 +1435,7 @@
 }
 
 /**
- * Get all meta data, including meta IDs, for the given term ID.
+ * Gets all meta data, including meta IDs, for the given term ID.
  *
  * @since 4.9.0
  *
@@ -1461,8 +1498,9 @@
  * Conditional Tags} article in the Theme Developer Handbook.
  *
  * @since 3.0.0
- *
- * @global wpdb $wpdb WordPress database abstraction object.
+ * @since 6.0.0 Converted to use `get_terms()`.
+ *
+ * @global bool $_wp_suspend_cache_invalidation
  *
  * @param int|string $term     The term to check. Accepts term ID, slug, or name.
  * @param string     $taxonomy Optional. The taxonomy name to use.
@@ -1473,65 +1511,89 @@
  *               Returns 0 if term ID 0 is passed to the function.
  */
 function term_exists( $term, $taxonomy = '', $parent = null ) {
-	global $wpdb;
-
-	$select     = "SELECT term_id FROM $wpdb->terms as t WHERE ";
-	$tax_select = "SELECT tt.term_id, tt.term_taxonomy_id FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy as tt ON tt.term_id = t.term_id WHERE ";
+	global $_wp_suspend_cache_invalidation;
+
+	if ( null === $term ) {
+		return null;
+	}
+
+	$defaults = array(
+		'get'                    => 'all',
+		'fields'                 => 'ids',
+		'number'                 => 1,
+		'update_term_meta_cache' => false,
+		'order'                  => 'ASC',
+		'orderby'                => 'term_id',
+		'suppress_filter'        => true,
+	);
+
+	// Ensure that while importing, queries are not cached.
+	if ( ! empty( $_wp_suspend_cache_invalidation ) ) {
+		// @todo Disable caching once #52710 is merged.
+		$defaults['cache_domain'] = microtime();
+	}
+
+	if ( ! empty( $taxonomy ) ) {
+		$defaults['taxonomy'] = $taxonomy;
+		$defaults['fields']   = 'all';
+	}
+
+	/**
+	 * Filters default query arguments for checking if a term exists.
+	 *
+	 * @since 6.0.0
+	 *
+	 * @param array      $defaults An array of arguments passed to get_terms().
+	 * @param int|string $term     The term to check. Accepts term ID, slug, or name.
+	 * @param string     $taxonomy The taxonomy name to use. An empty string indicates
+	 *                             the search is against all taxonomies.
+	 * @param int|null   $parent   ID of parent term under which to confine the exists search.
+	 *                             Null indicates the search is unconfined.
+	 */
+	$defaults = apply_filters( 'term_exists_default_query_args', $defaults, $term, $taxonomy, $parent );
 
 	if ( is_int( $term ) ) {
 		if ( 0 === $term ) {
 			return 0;
 		}
-		$where = 't.term_id = %d';
-		if ( ! empty( $taxonomy ) ) {
-			// phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
-			return $wpdb->get_row( $wpdb->prepare( $tax_select . $where . ' AND tt.taxonomy = %s', $term, $taxonomy ), ARRAY_A );
-		} else {
-			return $wpdb->get_var( $wpdb->prepare( $select . $where, $term ) );
+		$args  = wp_parse_args( array( 'include' => array( $term ) ), $defaults );
+		$terms = get_terms( $args );
+	} else {
+		$term = trim( wp_unslash( $term ) );
+		if ( '' === $term ) {
+			return null;
+		}
+
+		if ( ! empty( $taxonomy ) && is_numeric( $parent ) ) {
+			$defaults['parent'] = (int) $parent;
 		}
-	}
-
-	$term = trim( wp_unslash( $term ) );
-	$slug = sanitize_title( $term );
-
-	$where             = 't.slug = %s';
-	$else_where        = 't.name = %s';
-	$where_fields      = array( $slug );
-	$else_where_fields = array( $term );
-	$orderby           = 'ORDER BY t.term_id ASC';
-	$limit             = 'LIMIT 1';
+
+		$args  = wp_parse_args( array( 'slug' => sanitize_title( $term ) ), $defaults );
+		$terms = get_terms( $args );
+		if ( empty( $terms ) || is_wp_error( $terms ) ) {
+			$args  = wp_parse_args( array( 'name' => $term ), $defaults );
+			$terms = get_terms( $args );
+		}
+	}
+
+	if ( empty( $terms ) || is_wp_error( $terms ) ) {
+		return null;
+	}
+
+	$_term = array_shift( $terms );
+
 	if ( ! empty( $taxonomy ) ) {
-		if ( is_numeric( $parent ) ) {
-			$parent              = (int) $parent;
-			$where_fields[]      = $parent;
-			$else_where_fields[] = $parent;
-			$where              .= ' AND tt.parent = %d';
-			$else_where         .= ' AND tt.parent = %d';
-		}
-
-		$where_fields[]      = $taxonomy;
-		$else_where_fields[] = $taxonomy;
-
-		$result = $wpdb->get_row( $wpdb->prepare( "SELECT tt.term_id, tt.term_taxonomy_id FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy as tt ON tt.term_id = t.term_id WHERE $where AND tt.taxonomy = %s $orderby $limit", $where_fields ), ARRAY_A );
-		if ( $result ) {
-			return $result;
-		}
-
-		return $wpdb->get_row( $wpdb->prepare( "SELECT tt.term_id, tt.term_taxonomy_id FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy as tt ON tt.term_id = t.term_id WHERE $else_where AND tt.taxonomy = %s $orderby $limit", $else_where_fields ), ARRAY_A );
-	}
-
-	// phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
-	$result = $wpdb->get_var( $wpdb->prepare( "SELECT term_id FROM $wpdb->terms as t WHERE $where $orderby $limit", $where_fields ) );
-	if ( $result ) {
-		return $result;
-	}
-
-	// phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
-	return $wpdb->get_var( $wpdb->prepare( "SELECT term_id FROM $wpdb->terms as t WHERE $else_where $orderby $limit", $else_where_fields ) );
+		return array(
+			'term_id'          => (string) $_term->term_id,
+			'term_taxonomy_id' => (string) $_term->term_taxonomy_id,
+		);
+	}
+
+	return (string) $_term;
 }
 
 /**
- * Check if a term is an ancestor of another term.
+ * Checks if a term is an ancestor of another term.
  *
  * You can use either an ID or the term object for both parameters.
  *
@@ -1561,7 +1623,7 @@
 }
 
 /**
- * Sanitize all term fields.
+ * Sanitizes all term fields.
  *
  * Relies on sanitize_term_field() to sanitize the term. The difference is that
  * this function will sanitize **all** fields. The context is based
@@ -1607,7 +1669,7 @@
 }
 
 /**
- * Cleanse the field value in the term based on the context.
+ * Sanitizes the field value in the term based on the context.
  *
  * Passing a term field value through the function should be assumed to have
  * cleansed the value for whatever context the term field is going to be used.
@@ -1624,7 +1686,7 @@
  * @param string $field    Term field to sanitize.
  * @param string $value    Search for this term value.
  * @param int    $term_id  Term ID.
- * @param string $taxonomy Taxonomy Name.
+ * @param string $taxonomy Taxonomy name.
  * @param string $context  Context in which to sanitize the term field.
  *                         Accepts 'raw', 'edit', 'db', 'display', 'rss',
  *                         'attribute', or 'js'. Default 'display'.
@@ -1650,7 +1712,7 @@
 		/**
 		 * Filters a term field to edit before it is sanitized.
 		 *
-		 * The dynamic portion of the filter name, `$field`, refers to the term field.
+		 * The dynamic portion of the hook name, `$field`, refers to the term field.
 		 *
 		 * @since 2.3.0
 		 *
@@ -1683,7 +1745,7 @@
 		/**
 		 * Filters a term field value before it is sanitized.
 		 *
-		 * The dynamic portion of the filter name, `$field`, refers to the term field.
+		 * The dynamic portion of the hook name, `$field`, refers to the term field.
 		 *
 		 * @since 2.3.0
 		 *
@@ -1722,7 +1784,7 @@
 		/**
 		 * Filters the term field for use in RSS.
 		 *
-		 * The dynamic portion of the filter name, `$field`, refers to the term field.
+		 * The dynamic portion of the hook name, `$field`, refers to the term field.
 		 *
 		 * @since 2.3.0
 		 *
@@ -1748,7 +1810,7 @@
 		/**
 		 * Filters the term field sanitized for display.
 		 *
-		 * The dynamic portion of the filter name, `$field`, refers to the term field name.
+		 * The dynamic portion of the hook name, `$field`, refers to the term field name.
 		 *
 		 * @since 2.3.0
 		 *
@@ -1789,7 +1851,7 @@
 }
 
 /**
- * Count how many terms are in Taxonomy.
+ * Counts how many terms are in taxonomy.
  *
  * Default $args is 'hide_empty' which can be 'hide_empty=true' or array('hide_empty' => true).
  *
@@ -1839,7 +1901,7 @@
 }
 
 /**
- * Will unlink the object from the taxonomy or taxonomies.
+ * Unlinks the object from the taxonomy or taxonomies.
  *
  * Will remove all relationships between the object and any terms in
  * a particular taxonomy or taxonomies. Does not remove the term or
@@ -1847,8 +1909,8 @@
  *
  * @since 2.3.0
  *
- * @param int          $object_id  The term Object Id that refers to the term.
- * @param string|array $taxonomies List of Taxonomy Names or single Taxonomy name.
+ * @param int          $object_id  The term object ID that refers to the term.
+ * @param string|array $taxonomies List of taxonomy names or single taxonomy name.
  */
 function wp_delete_object_term_relationships( $object_id, $taxonomies ) {
 	$object_id = (int) $object_id;
@@ -1877,7 +1939,7 @@
  * @global wpdb $wpdb WordPress database abstraction object.
  *
  * @param int          $term     Term ID.
- * @param string       $taxonomy Taxonomy Name.
+ * @param string       $taxonomy Taxonomy name.
  * @param array|string $args {
  *     Optional. Array of arguments to override the default term ID. Default empty array.
  *
@@ -1943,7 +2005,7 @@
 	 * @since 4.1.0
 	 *
 	 * @param int    $term     Term ID.
-	 * @param string $taxonomy Taxonomy Name.
+	 * @param string $taxonomy Taxonomy name.
 	 */
 	do_action( 'pre_delete_term', $term, $taxonomy );
 
@@ -2227,7 +2289,7 @@
 }
 
 /**
- * Add a new term to the database.
+ * Adds a new term to the database.
  *
  * A non-existent term is inserted in the following sequence:
  * 1. The term is added to the term table, then related to the taxonomy.
@@ -2471,12 +2533,12 @@
 	 * and term_taxonomy_id of the older term instead. Then return out of the function so that the "create" hooks
 	 * are not fired.
 	 */
-	$duplicate_term = $wpdb->get_row( $wpdb->prepare( "SELECT t.term_id, t.slug, tt.term_taxonomy_id, tt.taxonomy FROM $wpdb->terms t INNER JOIN $wpdb->term_taxonomy 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 ) );
+	$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 ) );
 
 	/**
 	 * Filters the duplicate term check that takes place during term creation.
 	 *
-	 * Term parent+taxonomy+slug combinations are meant to be unique, and wp_insert_term()
+	 * Term parent + taxonomy + slug combinations are meant to be unique, and wp_insert_term()
 	 * performs a last-minute confirmation of this uniqueness before allowing a new term
 	 * to be created. Plugins with different uniqueness requirements may use this filter
 	 * to bypass or modify the duplicate-term check.
@@ -2622,9 +2684,9 @@
 }
 
 /**
- * Create Term and Taxonomy Relationships.
- *
- * Relates an object (post, link etc) to a term and taxonomy type. Creates the
+ * Creates term and taxonomy relationships.
+ *
+ * Relates an object (post, link, etc.) to a term and taxonomy type. Creates the
  * term and taxonomy relationship if it doesn't already exist. Creates a term if
  * it doesn't exist (using the slug).
  *
@@ -2806,7 +2868,7 @@
 }
 
 /**
- * Add term(s) associated with a given object.
+ * Adds term(s) associated with a given object.
  *
  * @since 3.6.0
  *
@@ -2820,7 +2882,7 @@
 }
 
 /**
- * Remove term(s) associated with a given object.
+ * Removes term(s) associated with a given object.
  *
  * @since 3.6.0
  *
@@ -2828,7 +2890,7 @@
  *
  * @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.
+ * @param 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 ) {
@@ -2875,8 +2937,8 @@
 		 * @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 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 );
@@ -2907,7 +2969,7 @@
 }
 
 /**
- * Will make slug unique, if it isn't already.
+ * Makes term 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
@@ -3010,7 +3072,7 @@
 }
 
 /**
- * Update term based on arguments provided.
+ * Updates 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
@@ -3205,7 +3267,7 @@
 	 *
 	 * @since 2.9.0
 	 *
-	 * @param int    $term_id  Term ID
+	 * @param int    $term_id  Term ID.
 	 * @param string $taxonomy Taxonomy slug.
 	 */
 	do_action( 'edited_terms', $term_id, $taxonomy );
@@ -3314,7 +3376,7 @@
 }
 
 /**
- * Enable or disable term counting.
+ * Enables or disables term counting.
  *
  * @since 2.5.0
  *
@@ -3381,7 +3443,7 @@
 }
 
 /**
- * Perform term count update immediately.
+ * Performs term count update immediately.
  *
  * @since 2.5.0
  *
@@ -3450,11 +3512,11 @@
 
 	$taxonomies = get_object_taxonomies( $object_type );
 
-	foreach ( $object_ids as $id ) {
-		foreach ( $taxonomies as $taxonomy ) {
-			wp_cache_delete( $id, "{$taxonomy}_relationships" );
-		}
-	}
+	foreach ( $taxonomies as $taxonomy ) {
+		wp_cache_delete_multiple( $object_ids, "{$taxonomy}_relationships" );
+	}
+
+	wp_cache_delete( 'last_changed', 'terms' );
 
 	/**
 	 * Fires after the object term cache has been cleaned.
@@ -3468,7 +3530,7 @@
 }
 
 /**
- * Will remove all of the term IDs from the cache.
+ * Removes all of the term IDs from the cache.
  *
  * @since 2.3.0
  *
@@ -3503,18 +3565,12 @@
 		foreach ( (array) $terms as $term ) {
 			$taxonomies[] = $term->taxonomy;
 			$ids[]        = $term->term_id;
-			wp_cache_delete( $term->term_id, 'terms' );
 		}
-
+		wp_cache_delete_multiple( $ids, 'terms' );
 		$taxonomies = array_unique( $taxonomies );
 	} else {
+		wp_cache_delete_multiple( $ids, 'terms' );
 		$taxonomies = array( $taxonomy );
-
-		foreach ( $taxonomies as $taxonomy ) {
-			foreach ( $ids as $id ) {
-				wp_cache_delete( $id, 'terms' );
-			}
-		}
 	}
 
 	foreach ( $taxonomies as $taxonomy ) {
@@ -3539,7 +3595,7 @@
 }
 
 /**
- * Clean the caches for a taxonomy.
+ * Cleans the caches for a taxonomy.
  *
  * @since 4.9.0
  *
@@ -3548,6 +3604,7 @@
 function clean_taxonomy_cache( $taxonomy ) {
 	wp_cache_delete( 'all_ids', $taxonomy );
 	wp_cache_delete( 'get', $taxonomy );
+	wp_cache_delete( 'last_changed', 'terms' );
 
 	// Regenerate cached hierarchy.
 	delete_option( "{$taxonomy}_children" );
@@ -3687,15 +3744,19 @@
 		}
 	}
 
+	$cache_values = array();
 	foreach ( $object_terms as $id => $value ) {
 		foreach ( $value as $taxonomy => $terms ) {
-			wp_cache_add( $id, $terms, "{$taxonomy}_relationships" );
+			$cache_values[ $taxonomy ][ $id ] = $terms;
 		}
 	}
+	foreach ( $cache_values as $taxonomy => $data ) {
+		wp_cache_add_multiple( $data, "{$taxonomy}_relationships" );
+	}
 }
 
 /**
- * Updates Terms to Taxonomy in cache.
+ * Updates terms in cache.
  *
  * @since 2.3.0
  *
@@ -3703,6 +3764,7 @@
  * @param string    $taxonomy Not used.
  */
 function update_term_cache( $terms, $taxonomy = '' ) {
+	$data = array();
 	foreach ( (array) $terms as $term ) {
 		// Create a copy in case the array was passed by reference.
 		$_term = clone $term;
@@ -3710,8 +3772,9 @@
 		// Object ID should not be cached.
 		unset( $_term->object_id );
 
-		wp_cache_add( $term->term_id, $_term, 'terms' );
-	}
+		$data[ $term->term_id ] = $_term;
+	}
+	wp_cache_add_multiple( $data, 'terms' );
 }
 
 //
@@ -3719,13 +3782,13 @@
 //
 
 /**
- * Retrieves children of taxonomy as Term IDs.
+ * 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.
+ * @return array Empty if $taxonomy isn't hierarchical or returns children as term IDs.
  */
 function _get_term_hierarchy( $taxonomy ) {
 	if ( ! is_taxonomy_hierarchical( $taxonomy ) ) {
@@ -3757,7 +3820,7 @@
 }
 
 /**
- * Get the subset of $terms that are descendants of $term_id.
+ * Gets 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.
@@ -3833,7 +3896,7 @@
 }
 
 /**
- * Add count of children to parent count.
+ * Adds 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.
@@ -3927,7 +3990,7 @@
 	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 );
+		update_term_cache( $fresh_terms );
 
 		if ( $update_meta_cache ) {
 			update_termmeta_cache( $non_cached_ids );
@@ -3940,7 +4003,7 @@
 //
 
 /**
- * Will update term count based on object types of the current taxonomy.
+ * Updates term count based on object types of the current taxonomy.
  *
  * Private function for the default callback for post_tag and category
  * taxonomies.
@@ -3950,7 +4013,7 @@
  *
  * @global wpdb $wpdb WordPress database abstraction object.
  *
- * @param int[]       $terms    List of Term taxonomy IDs.
+ * @param int[]       $terms    List of term taxonomy IDs.
  * @param WP_Taxonomy $taxonomy Current taxonomy object of terms.
  */
 function _update_post_term_count( $terms, $taxonomy ) {
@@ -4010,7 +4073,7 @@
 }
 
 /**
- * Will update term count based on number of objects.
+ * Updates term count based on number of objects.
  *
  * Default callback for the 'link_category' taxonomy.
  *
@@ -4037,7 +4100,7 @@
 }
 
 /**
- * Create a new term for a term_taxonomy item that currently shares its term
+ * Creates a new term for a term_taxonomy item that currently shares its term
  * with another term_taxonomy.
  *
  * @ignore
@@ -4284,7 +4347,7 @@
 
 /**
  * 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.
+ * checks that it's still scheduled while we haven't finished splitting terms.
  *
  * @ignore
  * @since 4.3.0
@@ -4296,7 +4359,7 @@
 }
 
 /**
- * Check default categories when a term gets split to see if any of them need to be updated.
+ * Checks default categories when a term gets split to see if any of them need to be updated.
  *
  * @ignore
  * @since 4.2.0
@@ -4319,7 +4382,7 @@
 }
 
 /**
- * Check menu items when a term gets split to see if any of them need to be updated.
+ * Checks menu items when a term gets split to see if any of them need to be updated.
  *
  * @ignore
  * @since 4.2.0
@@ -4355,7 +4418,7 @@
 }
 
 /**
- * If the term being split is a nav_menu, change associations.
+ * If the term being split is a nav_menu, changes associations.
  *
  * @ignore
  * @since 4.3.0
@@ -4381,7 +4444,7 @@
 }
 
 /**
- * Get data about terms that previously shared a single term_id, but have since been split.
+ * Gets data about terms that previously shared a single term_id, but have since been split.
  *
  * @since 4.2.0
  *
@@ -4400,7 +4463,7 @@
 }
 
 /**
- * Get the new term ID corresponding to a previously split term.
+ * Gets the new term ID corresponding to a previously split term.
  *
  * @since 4.2.0
  *
@@ -4422,7 +4485,7 @@
 }
 
 /**
- * Determine whether a term is shared between multiple taxonomies.
+ * Determines whether a term is shared between multiple taxonomies.
  *
  * Shared taxonomy terms began to be split in 4.3, but failed cron tasks or
  * other delays in upgrade routines may cause shared terms to remain.
@@ -4446,7 +4509,7 @@
 }
 
 /**
- * Generate a permalink for a taxonomy term archive.
+ * Generates a permalink for a taxonomy term archive.
  *
  * @since 2.5.0
  *
@@ -4560,7 +4623,7 @@
 }
 
 /**
- * Display the taxonomies of a post with available options.
+ * Displays the taxonomies of a post with available options.
  *
  * This function can be used within the loop to display the taxonomies for a
  * post without specifying the Post ID. You can also use it outside the Loop to
@@ -4572,10 +4635,10 @@
  *     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.
+ *     @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() ) {
@@ -4592,7 +4655,7 @@
 }
 
 /**
- * Retrieve all taxonomies associated with a post.
+ * Retrieves all taxonomies associated with a post.
  *
  * This function can be used within the loop. It will also return an array of
  * the taxonomies with links to the taxonomy and name.
@@ -4660,7 +4723,7 @@
 }
 
 /**
- * Retrieve all taxonomy names for the given post.
+ * Retrieves all taxonomy names for the given post.
  *
  * @since 2.5.0
  *
@@ -4674,7 +4737,7 @@
 }
 
 /**
- * Determine if the given object is associated with any of the given terms.
+ * Determines if the given object is associated with any of the given terms.
  *
  * The given terms are checked against the object's terms' term_ids, names and slugs.
  * Terms given as integers will only be checked against the object's terms' term_ids.
@@ -4749,7 +4812,7 @@
 }
 
 /**
- * Determine if the given object type is associated with the given taxonomy.
+ * Determines if the given object type is associated with the given taxonomy.
  *
  * @since 3.0.0
  *
@@ -4766,7 +4829,7 @@
 }
 
 /**
- * Get an array of ancestor IDs for a given object.
+ * Gets an array of ancestor IDs for a given object.
  *
  * @since 3.1.0
  * @since 4.1.0 Introduced the `$resource_type` argument.
@@ -4822,7 +4885,7 @@
 }
 
 /**
- * Returns the term's parent's term_ID.
+ * Returns the term's parent's term ID.
  *
  * @since 3.1.0
  *