wp/wp-includes/class-wp-term-query.php
changeset 9 177826044cd9
parent 7 cf61fcea0001
child 16 a86126ab1dd4
equal deleted inserted replaced
8:c7c34916027a 9:177826044cd9
   121 	 *                                                not return accurate results when coupled with $object_ids.
   121 	 *                                                not return accurate results when coupled with $object_ids.
   122 	 *                                                See #41796 for details.
   122 	 *                                                See #41796 for details.
   123 	 *     @type int          $offset                 The number by which to offset the terms query. Default empty.
   123 	 *     @type int          $offset                 The number by which to offset the terms query. Default empty.
   124 	 *     @type string       $fields                 Term fields to query for. Accepts 'all' (returns an array of
   124 	 *     @type string       $fields                 Term fields to query for. Accepts 'all' (returns an array of
   125 	 *                                                complete term objects), 'all_with_object_id' (returns an
   125 	 *                                                complete term objects), 'all_with_object_id' (returns an
   126 	 *                                                array of term objects with the 'object_id' param; only works
   126 	 *                                                array of term objects with the 'object_id' param; works only
   127 	 *                                                when the `$fields` parameter is 'object_ids' ), 'ids'
   127 	 *                                                when the `$object_ids` parameter is populated), 'ids'
   128 	 *                                                (returns an array of ids), 'tt_ids' (returns an array of
   128 	 *                                                (returns an array of ids), 'tt_ids' (returns an array of
   129 	 *                                                term taxonomy ids), 'id=>parent' (returns an associative
   129 	 *                                                term taxonomy ids), 'id=>parent' (returns an associative
   130 	 *                                                array with ids as keys, parent term IDs as values), 'names'
   130 	 *                                                array with ids as keys, parent term IDs as values), 'names'
   131 	 *                                                (returns an array of term names), 'count' (returns the number
   131 	 *                                                (returns an array of term names), 'count' (returns the number
   132 	 *                                                of matching terms), 'id=>name' (returns an associative array
   132 	 *                                                of matching terms), 'id=>name' (returns an associative array
   170 	 *                                                See `WP_Meta_Query`. Default empty.
   170 	 *                                                See `WP_Meta_Query`. Default empty.
   171 	 *     @type string       $meta_key               Limit terms to those matching a specific metadata key.
   171 	 *     @type string       $meta_key               Limit terms to those matching a specific metadata key.
   172 	 *                                                Can be used in conjunction with `$meta_value`. Default empty.
   172 	 *                                                Can be used in conjunction with `$meta_value`. Default empty.
   173 	 *     @type string       $meta_value             Limit terms to those matching a specific metadata value.
   173 	 *     @type string       $meta_value             Limit terms to those matching a specific metadata value.
   174 	 *                                                Usually used in conjunction with `$meta_key`. Default empty.
   174 	 *                                                Usually used in conjunction with `$meta_key`. Default empty.
   175 	 *     @type string       $meta_type              Type of object metadata is for (e.g., comment, post, or user).
   175 	 *     @type string       $meta_type              MySQL data type that the `$meta_value` will be CAST to for
   176 	 *                                                Default empty.
   176 	 *                                                comparisons. Default empty.
   177 	 *     @type string       $meta_compare           Comparison operator to test the 'meta_value'. Default empty.
   177 	 *     @type string       $meta_compare           Comparison operator to test the 'meta_value'. Default empty.
   178 	 * }
   178 	 * }
   179 	 */
   179 	 */
   180 	public function __construct( $query = '' ) {
   180 	public function __construct( $query = '' ) {
   181 		$this->query_var_defaults = array(
   181 		$this->query_var_defaults = array(
   236 		 *
   236 		 *
   237 		 * Use {@see 'get_terms_args'} to filter the passed arguments.
   237 		 * Use {@see 'get_terms_args'} to filter the passed arguments.
   238 		 *
   238 		 *
   239 		 * @since 4.4.0
   239 		 * @since 4.4.0
   240 		 *
   240 		 *
   241 		 * @param array $defaults   An array of default get_terms() arguments.
   241 		 * @param array    $defaults   An array of default get_terms() arguments.
   242 		 * @param array $taxonomies An array of taxonomies.
   242 		 * @param string[] $taxonomies An array of taxonomy names.
   243 		 */
   243 		 */
   244 		$this->query_var_defaults = apply_filters( 'get_terms_defaults', $this->query_var_defaults, $taxonomies );
   244 		$this->query_var_defaults = apply_filters( 'get_terms_defaults', $this->query_var_defaults, $taxonomies );
   245 
   245 
   246 		$query = wp_parse_args( $query, $this->query_var_defaults );
   246 		$query = wp_parse_args( $query, $this->query_var_defaults );
   247 
   247 
   252 		if ( 0 < intval( $query['parent'] ) ) {
   252 		if ( 0 < intval( $query['parent'] ) ) {
   253 			$query['child_of'] = false;
   253 			$query['child_of'] = false;
   254 		}
   254 		}
   255 
   255 
   256 		if ( 'all' == $query['get'] ) {
   256 		if ( 'all' == $query['get'] ) {
   257 			$query['childless'] = false;
   257 			$query['childless']    = false;
   258 			$query['child_of'] = 0;
   258 			$query['child_of']     = 0;
   259 			$query['hide_empty'] = 0;
   259 			$query['hide_empty']   = 0;
   260 			$query['hierarchical'] = false;
   260 			$query['hierarchical'] = false;
   261 			$query['pad_counts'] = false;
   261 			$query['pad_counts']   = false;
   262 		}
   262 		}
   263 
   263 
   264 		$query['taxonomy'] = $taxonomies;
   264 		$query['taxonomy'] = $taxonomies;
   265 
   265 
   266 		$this->query_vars = $query;
   266 		$this->query_vars = $query;
   328 			}
   328 			}
   329 		}
   329 		}
   330 
   330 
   331 		if ( ! $has_hierarchical_tax ) {
   331 		if ( ! $has_hierarchical_tax ) {
   332 			$args['hierarchical'] = false;
   332 			$args['hierarchical'] = false;
   333 			$args['pad_counts'] = false;
   333 			$args['pad_counts']   = false;
   334 		}
   334 		}
   335 
   335 
   336 		// 'parent' overrides 'child_of'.
   336 		// 'parent' overrides 'child_of'.
   337 		if ( 0 < intval( $args['parent'] ) ) {
   337 		if ( 0 < intval( $args['parent'] ) ) {
   338 			$args['child_of'] = false;
   338 			$args['child_of'] = false;
   339 		}
   339 		}
   340 
   340 
   341 		if ( 'all' == $args['get'] ) {
   341 		if ( 'all' == $args['get'] ) {
   342 			$args['childless'] = false;
   342 			$args['childless']    = false;
   343 			$args['child_of'] = 0;
   343 			$args['child_of']     = 0;
   344 			$args['hide_empty'] = 0;
   344 			$args['hide_empty']   = 0;
   345 			$args['hierarchical'] = false;
   345 			$args['hierarchical'] = false;
   346 			$args['pad_counts'] = false;
   346 			$args['pad_counts']   = false;
   347 		}
   347 		}
   348 
   348 
   349 		/**
   349 		/**
   350 		 * Filters the terms query arguments.
   350 		 * Filters the terms query arguments.
   351 		 *
   351 		 *
   352 		 * @since 3.1.0
   352 		 * @since 3.1.0
   353 		 *
   353 		 *
   354 		 * @param array $args       An array of get_terms() arguments.
   354 		 * @param array    $args       An array of get_terms() arguments.
   355 		 * @param array $taxonomies An array of taxonomies.
   355 		 * @param string[] $taxonomies An array of taxonomy names.
   356 		 */
   356 		 */
   357 		$args = apply_filters( 'get_terms_args', $args, $taxonomies );
   357 		$args = apply_filters( 'get_terms_args', $args, $taxonomies );
   358 
   358 
   359 		// Avoid the query if the queried parent/child_of term has no descendants.
   359 		// Avoid the query if the queried parent/child_of term has no descendants.
   360 		$child_of = $args['child_of'];
   360 		$child_of = $args['child_of'];
   377 					$in_hierarchy = true;
   377 					$in_hierarchy = true;
   378 				}
   378 				}
   379 			}
   379 			}
   380 
   380 
   381 			if ( ! $in_hierarchy ) {
   381 			if ( ! $in_hierarchy ) {
   382 				return array();
   382 				if ( 'count' == $args['fields'] ) {
       
   383 					return 0;
       
   384 				} else {
       
   385 					$this->terms = array();
       
   386 					return $this->terms;
       
   387 				}
   383 			}
   388 			}
   384 		}
   389 		}
   385 
   390 
   386 		// 'term_order' is a legal sort order only when joining the relationship table.
   391 		// 'term_order' is a legal sort order only when joining the relationship table.
   387 		$_orderby = $this->query_vars['orderby'];
   392 		$_orderby = $this->query_vars['orderby'];
   404 		$exclude_tree = $args['exclude_tree'];
   409 		$exclude_tree = $args['exclude_tree'];
   405 		$include      = $args['include'];
   410 		$include      = $args['include'];
   406 
   411 
   407 		$inclusions = '';
   412 		$inclusions = '';
   408 		if ( ! empty( $include ) ) {
   413 		if ( ! empty( $include ) ) {
   409 			$exclude = '';
   414 			$exclude      = '';
   410 			$exclude_tree = '';
   415 			$exclude_tree = '';
   411 			$inclusions = implode( ',', wp_parse_id_list( $include ) );
   416 			$inclusions   = implode( ',', wp_parse_id_list( $include ) );
   412 		}
   417 		}
   413 
   418 
   414 		if ( ! empty( $inclusions ) ) {
   419 		if ( ! empty( $inclusions ) ) {
   415 			$this->sql_clauses['where']['inclusions'] = 't.term_id IN ( ' . $inclusions . ' )';
   420 			$this->sql_clauses['where']['inclusions'] = 't.term_id IN ( ' . $inclusions . ' )';
   416 		}
   421 		}
   417 
   422 
   418 		$exclusions = array();
   423 		$exclusions = array();
   419 		if ( ! empty( $exclude_tree ) ) {
   424 		if ( ! empty( $exclude_tree ) ) {
   420 			$exclude_tree = wp_parse_id_list( $exclude_tree );
   425 			$exclude_tree      = wp_parse_id_list( $exclude_tree );
   421 			$excluded_children = $exclude_tree;
   426 			$excluded_children = $exclude_tree;
   422 			foreach ( $exclude_tree as $extrunk ) {
   427 			foreach ( $exclude_tree as $extrunk ) {
   423 				$excluded_children = array_merge(
   428 				$excluded_children = array_merge(
   424 					$excluded_children,
   429 					$excluded_children,
   425 					(array) get_terms( reset( $taxonomies ), array(
   430 					(array) get_terms(
   426 						'child_of' => intval( $extrunk ),
   431 						reset( $taxonomies ),
   427 						'fields' => 'ids',
   432 						array(
   428 						'hide_empty' => 0
   433 							'child_of'   => intval( $extrunk ),
   429 					) )
   434 							'fields'     => 'ids',
       
   435 							'hide_empty' => 0,
       
   436 						)
       
   437 					)
   430 				);
   438 				);
   431 			}
   439 			}
   432 			$exclusions = array_merge( $excluded_children, $exclusions );
   440 			$exclusions = array_merge( $excluded_children, $exclusions );
   433 		}
   441 		}
   434 
   442 
   439 		// 'childless' terms are those without an entry in the flattened term hierarchy.
   447 		// 'childless' terms are those without an entry in the flattened term hierarchy.
   440 		$childless = (bool) $args['childless'];
   448 		$childless = (bool) $args['childless'];
   441 		if ( $childless ) {
   449 		if ( $childless ) {
   442 			foreach ( $taxonomies as $_tax ) {
   450 			foreach ( $taxonomies as $_tax ) {
   443 				$term_hierarchy = _get_term_hierarchy( $_tax );
   451 				$term_hierarchy = _get_term_hierarchy( $_tax );
   444 				$exclusions = array_merge( array_keys( $term_hierarchy ), $exclusions );
   452 				$exclusions     = array_merge( array_keys( $term_hierarchy ), $exclusions );
   445 			}
   453 			}
   446 		}
   454 		}
   447 
   455 
   448 		if ( ! empty( $exclusions ) ) {
   456 		if ( ! empty( $exclusions ) ) {
   449 			$exclusions = 't.term_id NOT IN (' . implode( ',', array_map( 'intval', $exclusions ) ) . ')';
   457 			$exclusions = 't.term_id NOT IN (' . implode( ',', array_map( 'intval', $exclusions ) ) . ')';
   454 		/**
   462 		/**
   455 		 * Filters the terms to exclude from the terms query.
   463 		 * Filters the terms to exclude from the terms query.
   456 		 *
   464 		 *
   457 		 * @since 2.3.0
   465 		 * @since 2.3.0
   458 		 *
   466 		 *
   459 		 * @param string $exclusions `NOT IN` clause of the terms query.
   467 		 * @param string   $exclusions `NOT IN` clause of the terms query.
   460 		 * @param array  $args       An array of terms query arguments.
   468 		 * @param array    $args       An array of terms query arguments.
   461 		 * @param array  $taxonomies An array of taxonomies.
   469 		 * @param string[] $taxonomies An array of taxonomy names.
   462 		 */
   470 		 */
   463 		$exclusions = apply_filters( 'list_terms_exclusions', $exclusions, $args, $taxonomies );
   471 		$exclusions = apply_filters( 'list_terms_exclusions', $exclusions, $args, $taxonomies );
   464 
   472 
   465 		if ( ! empty( $exclusions ) ) {
   473 		if ( ! empty( $exclusions ) ) {
   466 			// Must do string manipulation here for backward compatibility with filter.
   474 			// Must do string manipulation here for backward compatibility with filter.
   483 		if (
   491 		if (
   484 			( ! empty( $args['slug'] ) ) ||
   492 			( ! empty( $args['slug'] ) ) ||
   485 			( is_string( $args['slug'] ) && 0 !== strlen( $args['slug'] ) )
   493 			( is_string( $args['slug'] ) && 0 !== strlen( $args['slug'] ) )
   486 		) {
   494 		) {
   487 			if ( is_array( $args['slug'] ) ) {
   495 			if ( is_array( $args['slug'] ) ) {
   488 				$slug = array_map( 'sanitize_title', $args['slug'] );
   496 				$slug                               = array_map( 'sanitize_title', $args['slug'] );
   489 				$this->sql_clauses['where']['slug'] = "t.slug IN ('" . implode( "', '", $slug ) . "')";
   497 				$this->sql_clauses['where']['slug'] = "t.slug IN ('" . implode( "', '", $slug ) . "')";
   490 			} else {
   498 			} else {
   491 				$slug = sanitize_title( $args['slug'] );
   499 				$slug                               = sanitize_title( $args['slug'] );
   492 				$this->sql_clauses['where']['slug'] = "t.slug = '$slug'";
   500 				$this->sql_clauses['where']['slug'] = "t.slug = '$slug'";
   493 			}
   501 			}
   494 		}
   502 		}
   495 
   503 
   496 		if ( ! empty( $args['term_taxonomy_id'] ) ) {
   504 		if ( ! empty( $args['term_taxonomy_id'] ) ) {
   497 			if ( is_array( $args['term_taxonomy_id'] ) ) {
   505 			if ( is_array( $args['term_taxonomy_id'] ) ) {
   498 				$tt_ids = implode( ',', array_map( 'intval', $args['term_taxonomy_id'] ) );
   506 				$tt_ids = implode( ',', array_map( 'intval', $args['term_taxonomy_id'] ) );
   499 				$this->sql_clauses['where']['term_taxonomy_id'] = "tt.term_taxonomy_id IN ({$tt_ids})";
   507 				$this->sql_clauses['where']['term_taxonomy_id'] = "tt.term_taxonomy_id IN ({$tt_ids})";
   500 			} else {
   508 			} else {
   501 				$this->sql_clauses['where']['term_taxonomy_id'] = $wpdb->prepare( "tt.term_taxonomy_id = %d", $args['term_taxonomy_id'] );
   509 				$this->sql_clauses['where']['term_taxonomy_id'] = $wpdb->prepare( 'tt.term_taxonomy_id = %d', $args['term_taxonomy_id'] );
   502 			}
   510 			}
   503 		}
   511 		}
   504 
   512 
   505 		if ( ! empty( $args['name__like'] ) ) {
   513 		if ( ! empty( $args['name__like'] ) ) {
   506 			$this->sql_clauses['where']['name__like'] = $wpdb->prepare( "t.name LIKE %s", '%' . $wpdb->esc_like( $args['name__like'] ) . '%' );
   514 			$this->sql_clauses['where']['name__like'] = $wpdb->prepare( 't.name LIKE %s', '%' . $wpdb->esc_like( $args['name__like'] ) . '%' );
   507 		}
   515 		}
   508 
   516 
   509 		if ( ! empty( $args['description__like'] ) ) {
   517 		if ( ! empty( $args['description__like'] ) ) {
   510 			$this->sql_clauses['where']['description__like'] = $wpdb->prepare( "tt.description LIKE %s", '%' . $wpdb->esc_like( $args['description__like'] ) . '%' );
   518 			$this->sql_clauses['where']['description__like'] = $wpdb->prepare( 'tt.description LIKE %s', '%' . $wpdb->esc_like( $args['description__like'] ) . '%' );
   511 		}
   519 		}
   512 
   520 
   513 		if ( ! empty( $args['object_ids'] ) ) {
   521 		if ( ! empty( $args['object_ids'] ) ) {
   514 			$object_ids = $args['object_ids'];
   522 			$object_ids = $args['object_ids'];
   515 			if ( ! is_array( $object_ids ) ) {
   523 			if ( ! is_array( $object_ids ) ) {
   516 				$object_ids = array( $object_ids );
   524 				$object_ids = array( $object_ids );
   517 			}
   525 			}
   518 
   526 
   519 			$object_ids = implode( ', ', array_map( 'intval', $object_ids ) );
   527 			$object_ids                               = implode( ', ', array_map( 'intval', $object_ids ) );
   520 			$this->sql_clauses['where']['object_ids'] = "tr.object_id IN ($object_ids)";
   528 			$this->sql_clauses['where']['object_ids'] = "tr.object_id IN ($object_ids)";
   521 		}
   529 		}
   522 
   530 
   523 		/*
   531 		/*
   524 		 * When querying for object relationships, the 'count > 0' check
   532 		 * When querying for object relationships, the 'count > 0' check
   527 		if ( ! empty( $args['object_ids'] ) ) {
   535 		if ( ! empty( $args['object_ids'] ) ) {
   528 			$args['hide_empty'] = false;
   536 			$args['hide_empty'] = false;
   529 		}
   537 		}
   530 
   538 
   531 		if ( '' !== $parent ) {
   539 		if ( '' !== $parent ) {
   532 			$parent = (int) $parent;
   540 			$parent                               = (int) $parent;
   533 			$this->sql_clauses['where']['parent'] = "tt.parent = '$parent'";
   541 			$this->sql_clauses['where']['parent'] = "tt.parent = '$parent'";
   534 		}
   542 		}
   535 
   543 
   536 		$hierarchical = $args['hierarchical'];
   544 		$hierarchical = $args['hierarchical'];
   537 		if ( 'count' == $args['fields'] ) {
   545 		if ( 'count' == $args['fields'] ) {
   538 			$hierarchical = false;
   546 			$hierarchical = false;
   539 		}
   547 		}
   540 		if ( $args['hide_empty'] && !$hierarchical ) {
   548 		if ( $args['hide_empty'] && ! $hierarchical ) {
   541 			$this->sql_clauses['where']['count'] = 'tt.count > 0';
   549 			$this->sql_clauses['where']['count'] = 'tt.count > 0';
   542 		}
   550 		}
   543 
   551 
   544 		$number = $args['number'];
   552 		$number = $args['number'];
   545 		$offset = $args['offset'];
   553 		$offset = $args['offset'];
   553 			}
   561 			}
   554 		} else {
   562 		} else {
   555 			$limits = '';
   563 			$limits = '';
   556 		}
   564 		}
   557 
   565 
   558 
       
   559 		if ( ! empty( $args['search'] ) ) {
   566 		if ( ! empty( $args['search'] ) ) {
   560 			$this->sql_clauses['where']['search'] = $this->get_search_sql( $args['search'] );
   567 			$this->sql_clauses['where']['search'] = $this->get_search_sql( $args['search'] );
   561 		}
   568 		}
   562 
   569 
   563 		// Meta query support.
   570 		// Meta query support.
   564 		$join = '';
   571 		$join     = '';
   565 		$distinct = '';
   572 		$distinct = '';
   566 
   573 
   567 		// Reparse meta_query query_vars, in case they were modified in a 'pre_get_terms' callback.
   574 		// Reparse meta_query query_vars, in case they were modified in a 'pre_get_terms' callback.
   568 		$this->meta_query->parse_query_vars( $this->query_vars );
   575 		$this->meta_query->parse_query_vars( $this->query_vars );
   569 		$mq_sql = $this->meta_query->get_sql( 'term', 't', 'term_id' );
   576 		$mq_sql       = $this->meta_query->get_sql( 'term', 't', 'term_id' );
   570 		$meta_clauses = $this->meta_query->get_clauses();
   577 		$meta_clauses = $this->meta_query->get_clauses();
   571 
   578 
   572 		if ( ! empty( $meta_clauses ) ) {
   579 		if ( ! empty( $meta_clauses ) ) {
   573 			$join .= $mq_sql['join'];
   580 			$join                                    .= $mq_sql['join'];
   574 			$this->sql_clauses['where']['meta_query'] = preg_replace( '/^\s*AND\s*/', '', $mq_sql['where'] );
   581 			$this->sql_clauses['where']['meta_query'] = preg_replace( '/^\s*AND\s*/', '', $mq_sql['where'] );
   575 			$distinct .= "DISTINCT";
   582 			$distinct                                .= 'DISTINCT';
   576 
   583 
   577 		}
   584 		}
   578 
   585 
   579 		$selects = array();
   586 		$selects = array();
   580 		switch ( $args['fields'] ) {
   587 		switch ( $args['fields'] ) {
   581 			case 'all':
   588 			case 'all':
   582 			case 'all_with_object_id' :
   589 			case 'all_with_object_id':
   583 			case 'tt_ids' :
   590 			case 'tt_ids':
   584 			case 'slugs' :
   591 			case 'slugs':
   585 				$selects = array( 't.*', 'tt.*' );
   592 				$selects = array( 't.*', 'tt.*' );
   586 				if ( 'all_with_object_id' === $args['fields'] && ! empty( $args['object_ids'] ) ) {
   593 				if ( 'all_with_object_id' === $args['fields'] && ! empty( $args['object_ids'] ) ) {
   587 					$selects[] = 'tr.object_id';
   594 					$selects[] = 'tr.object_id';
   588 				}
   595 				}
   589 				break;
   596 				break;
   594 			case 'names':
   601 			case 'names':
   595 				$selects = array( 't.term_id', 'tt.parent', 'tt.count', 't.name', 'tt.taxonomy' );
   602 				$selects = array( 't.term_id', 'tt.parent', 'tt.count', 't.name', 'tt.taxonomy' );
   596 				break;
   603 				break;
   597 			case 'count':
   604 			case 'count':
   598 				$orderby = '';
   605 				$orderby = '';
   599 				$order = '';
   606 				$order   = '';
   600 				$selects = array( 'COUNT(*)' );
   607 				$selects = array( 'COUNT(*)' );
   601 				break;
   608 				break;
   602 			case 'id=>name':
   609 			case 'id=>name':
   603 				$selects = array( 't.term_id', 't.name', 'tt.count', 'tt.taxonomy' );
   610 				$selects = array( 't.term_id', 't.name', 'tt.count', 'tt.taxonomy' );
   604 				break;
   611 				break;
   619 		 *
   626 		 *
   620 		 * Use of this filter can result in unpredictable behavior, and is not recommended.
   627 		 * Use of this filter can result in unpredictable behavior, and is not recommended.
   621 		 *
   628 		 *
   622 		 * @since 2.8.0
   629 		 * @since 2.8.0
   623 		 *
   630 		 *
   624 		 * @param array $selects    An array of fields to select for the terms query.
   631 		 * @param string[] $selects    An array of fields to select for the terms query.
   625 		 * @param array $args       An array of term query arguments.
   632 		 * @param array    $args       An array of term query arguments.
   626 		 * @param array $taxonomies An array of taxonomies.
   633 		 * @param string[] $taxonomies An array of taxonomy names.
   627 		 */
   634 		 */
   628 		$fields = implode( ', ', apply_filters( 'get_terms_fields', $selects, $args, $taxonomies ) );
   635 		$fields = implode( ', ', apply_filters( 'get_terms_fields', $selects, $args, $taxonomies ) );
   629 
   636 
   630 		$join .= " INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id";
   637 		$join .= " INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id";
   631 
   638 
   638 		/**
   645 		/**
   639 		 * Filters the terms query SQL clauses.
   646 		 * Filters the terms query SQL clauses.
   640 		 *
   647 		 *
   641 		 * @since 3.1.0
   648 		 * @since 3.1.0
   642 		 *
   649 		 *
   643 		 * @param array $pieces     Terms query SQL clauses.
   650 		 * @param string[] $pieces     Array of query SQL clauses.
   644 		 * @param array $taxonomies An array of taxonomies.
   651 		 * @param string[] $taxonomies An array of taxonomy names.
   645 		 * @param array $args       An array of terms query arguments.
   652 		 * @param array    $args       An array of term query arguments.
   646 		 */
   653 		 */
   647 		$clauses = apply_filters( 'terms_clauses', compact( 'fields', 'join', 'where', 'distinct', 'orderby', 'order', 'limits' ), $taxonomies, $args );
   654 		$clauses = apply_filters( 'terms_clauses', compact( 'fields', 'join', 'where', 'distinct', 'orderby', 'order', 'limits' ), $taxonomies, $args );
   648 
   655 
   649 		$fields = isset( $clauses[ 'fields' ] ) ? $clauses[ 'fields' ] : '';
   656 		$fields   = isset( $clauses['fields'] ) ? $clauses['fields'] : '';
   650 		$join = isset( $clauses[ 'join' ] ) ? $clauses[ 'join' ] : '';
   657 		$join     = isset( $clauses['join'] ) ? $clauses['join'] : '';
   651 		$where = isset( $clauses[ 'where' ] ) ? $clauses[ 'where' ] : '';
   658 		$where    = isset( $clauses['where'] ) ? $clauses['where'] : '';
   652 		$distinct = isset( $clauses[ 'distinct' ] ) ? $clauses[ 'distinct' ] : '';
   659 		$distinct = isset( $clauses['distinct'] ) ? $clauses['distinct'] : '';
   653 		$orderby = isset( $clauses[ 'orderby' ] ) ? $clauses[ 'orderby' ] : '';
   660 		$orderby  = isset( $clauses['orderby'] ) ? $clauses['orderby'] : '';
   654 		$order = isset( $clauses[ 'order' ] ) ? $clauses[ 'order' ] : '';
   661 		$order    = isset( $clauses['order'] ) ? $clauses['order'] : '';
   655 		$limits = isset( $clauses[ 'limits' ] ) ? $clauses[ 'limits' ] : '';
   662 		$limits   = isset( $clauses['limits'] ) ? $clauses['limits'] : '';
   656 
   663 
   657 		if ( $where ) {
   664 		if ( $where ) {
   658 			$where = "WHERE $where";
   665 			$where = "WHERE $where";
   659 		}
   666 		}
   660 
   667 
   664 		$this->sql_clauses['limits']  = $limits;
   671 		$this->sql_clauses['limits']  = $limits;
   665 
   672 
   666 		$this->request = "{$this->sql_clauses['select']} {$this->sql_clauses['from']} {$where} {$this->sql_clauses['orderby']} {$this->sql_clauses['limits']}";
   673 		$this->request = "{$this->sql_clauses['select']} {$this->sql_clauses['from']} {$where} {$this->sql_clauses['orderby']} {$this->sql_clauses['limits']}";
   667 
   674 
   668 		// $args can be anything. Only use the args defined in defaults to compute the key.
   675 		// $args can be anything. Only use the args defined in defaults to compute the key.
   669 		$key = md5( serialize( wp_array_slice_assoc( $args, array_keys( $this->query_var_defaults ) ) ) . serialize( $taxonomies ) . $this->request );
   676 		$key          = md5( serialize( wp_array_slice_assoc( $args, array_keys( $this->query_var_defaults ) ) ) . serialize( $taxonomies ) . $this->request );
   670 		$last_changed = wp_cache_get_last_changed( 'terms' );
   677 		$last_changed = wp_cache_get_last_changed( 'terms' );
   671 		$cache_key = "get_terms:$key:$last_changed";
   678 		$cache_key    = "get_terms:$key:$last_changed";
   672 		$cache = wp_cache_get( $cache_key, 'terms' );
   679 		$cache        = wp_cache_get( $cache_key, 'terms' );
   673 		if ( false !== $cache ) {
   680 		if ( false !== $cache ) {
   674 			if ( 'all' === $_fields || 'all_with_object_id' === $_fields ) {
   681 			if ( 'all' === $_fields || 'all_with_object_id' === $_fields ) {
   675 				$cache = $this->populate_terms( $cache );
   682 				$cache = $this->populate_terms( $cache );
   676 			}
   683 			}
   677 
   684 
   749 				if ( isset( $_tt_ids[ $term->term_id ] ) ) {
   756 				if ( isset( $_tt_ids[ $term->term_id ] ) ) {
   750 					continue;
   757 					continue;
   751 				}
   758 				}
   752 
   759 
   753 				$_tt_ids[ $term->term_id ] = 1;
   760 				$_tt_ids[ $term->term_id ] = 1;
   754 				$_terms[] = $term;
   761 				$_terms[]                  = $term;
   755 			}
   762 			}
   756 
   763 
   757 			$terms = $_terms;
   764 			$terms = $_terms;
   758 		}
   765 		}
   759 
   766 
   820 	 *
   827 	 *
   821 	 * @param string $orderby_raw Alias for the field to order by.
   828 	 * @param string $orderby_raw Alias for the field to order by.
   822 	 * @return string|false Value to used in the ORDER clause. False otherwise.
   829 	 * @return string|false Value to used in the ORDER clause. False otherwise.
   823 	 */
   830 	 */
   824 	protected function parse_orderby( $orderby_raw ) {
   831 	protected function parse_orderby( $orderby_raw ) {
   825 		$_orderby = strtolower( $orderby_raw );
   832 		$_orderby           = strtolower( $orderby_raw );
   826 		$maybe_orderby_meta = false;
   833 		$maybe_orderby_meta = false;
   827 
   834 
   828 		if ( in_array( $_orderby, array( 'term_id', 'name', 'slug', 'term_group' ), true ) ) {
   835 		if ( in_array( $_orderby, array( 'term_id', 'name', 'slug', 'term_group' ), true ) ) {
   829 			$orderby = "t.$_orderby";
   836 			$orderby = "t.$_orderby";
   830 		} elseif ( in_array( $_orderby, array( 'count', 'parent', 'taxonomy', 'term_taxonomy_id', 'description' ), true ) ) {
   837 		} elseif ( in_array( $_orderby, array( 'count', 'parent', 'taxonomy', 'term_taxonomy_id', 'description' ), true ) ) {
   833 			$orderby = 'tr.term_order';
   840 			$orderby = 'tr.term_order';
   834 		} elseif ( 'include' == $_orderby && ! empty( $this->query_vars['include'] ) ) {
   841 		} elseif ( 'include' == $_orderby && ! empty( $this->query_vars['include'] ) ) {
   835 			$include = implode( ',', wp_parse_id_list( $this->query_vars['include'] ) );
   842 			$include = implode( ',', wp_parse_id_list( $this->query_vars['include'] ) );
   836 			$orderby = "FIELD( t.term_id, $include )";
   843 			$orderby = "FIELD( t.term_id, $include )";
   837 		} elseif ( 'slug__in' == $_orderby && ! empty( $this->query_vars['slug'] ) && is_array( $this->query_vars['slug'] ) ) {
   844 		} elseif ( 'slug__in' == $_orderby && ! empty( $this->query_vars['slug'] ) && is_array( $this->query_vars['slug'] ) ) {
   838 			$slugs = implode( "', '", array_map( 'sanitize_title_for_query', $this->query_vars['slug'] ) );
   845 			$slugs   = implode( "', '", array_map( 'sanitize_title_for_query', $this->query_vars['slug'] ) );
   839 			$orderby = "FIELD( t.slug, '" . $slugs . "')";
   846 			$orderby = "FIELD( t.slug, '" . $slugs . "')";
   840 		} elseif ( 'none' == $_orderby ) {
   847 		} elseif ( 'none' == $_orderby ) {
   841 			$orderby = '';
   848 			$orderby = '';
   842 		} elseif ( empty( $_orderby ) || 'id' == $_orderby || 'term_id' === $_orderby ) {
   849 		} elseif ( empty( $_orderby ) || 'id' == $_orderby || 'term_id' === $_orderby ) {
   843 			$orderby = 't.term_id';
   850 			$orderby = 't.term_id';
   851 		/**
   858 		/**
   852 		 * Filters the ORDERBY clause of the terms query.
   859 		 * Filters the ORDERBY clause of the terms query.
   853 		 *
   860 		 *
   854 		 * @since 2.8.0
   861 		 * @since 2.8.0
   855 		 *
   862 		 *
   856 		 * @param string $orderby    `ORDERBY` clause of the terms query.
   863 		 * @param string   $orderby    `ORDERBY` clause of the terms query.
   857 		 * @param array  $args       An array of terms query arguments.
   864 		 * @param array    $args       An array of term query arguments.
   858 		 * @param array  $taxonomies An array of taxonomies.
   865 		 * @param string[] $taxonomies An array of taxonomy names.
   859 		 */
   866 		 */
   860 		$orderby = apply_filters( 'get_terms_orderby', $orderby, $this->query_vars, $this->query_vars['taxonomy'] );
   867 		$orderby = apply_filters( 'get_terms_orderby', $orderby, $this->query_vars, $this->query_vars['taxonomy'] );
   861 
   868 
   862 		// Run after the 'get_terms_orderby' filter for backward compatibility.
   869 		// Run after the 'get_terms_orderby' filter for backward compatibility.
   863 		if ( $maybe_orderby_meta ) {
   870 		if ( $maybe_orderby_meta ) {
   886 		$meta_clauses = $this->meta_query->get_clauses();
   893 		$meta_clauses = $this->meta_query->get_clauses();
   887 		if ( ! $meta_clauses || ! $orderby_raw ) {
   894 		if ( ! $meta_clauses || ! $orderby_raw ) {
   888 			return $orderby;
   895 			return $orderby;
   889 		}
   896 		}
   890 
   897 
   891 		$allowed_keys = array();
   898 		$allowed_keys       = array();
   892 		$primary_meta_key = null;
   899 		$primary_meta_key   = null;
   893 		$primary_meta_query = reset( $meta_clauses );
   900 		$primary_meta_query = reset( $meta_clauses );
   894 		if ( ! empty( $primary_meta_query['key'] ) ) {
   901 		if ( ! empty( $primary_meta_query['key'] ) ) {
   895 			$primary_meta_key = $primary_meta_query['key'];
   902 			$primary_meta_key = $primary_meta_query['key'];
   896 			$allowed_keys[] = $primary_meta_key;
   903 			$allowed_keys[]   = $primary_meta_key;
   897 		}
   904 		}
   898 		$allowed_keys[] = 'meta_value';
   905 		$allowed_keys[] = 'meta_value';
   899 		$allowed_keys[] = 'meta_value_num';
   906 		$allowed_keys[] = 'meta_value_num';
   900 		$allowed_keys   = array_merge( $allowed_keys, array_keys( $meta_clauses ) );
   907 		$allowed_keys   = array_merge( $allowed_keys, array_keys( $meta_clauses ) );
   901 
   908 
   902 		if ( ! in_array( $orderby_raw, $allowed_keys, true ) ) {
   909 		if ( ! in_array( $orderby_raw, $allowed_keys, true ) ) {
   903 			return $orderby;
   910 			return $orderby;
   904 		}
   911 		}
   905 
   912 
   906 		switch( $orderby_raw ) {
   913 		switch ( $orderby_raw ) {
   907 			case $primary_meta_key:
   914 			case $primary_meta_key:
   908 			case 'meta_value':
   915 			case 'meta_value':
   909 				if ( ! empty( $primary_meta_query['type'] ) ) {
   916 				if ( ! empty( $primary_meta_query['type'] ) ) {
   910 					$orderby = "CAST({$primary_meta_query['alias']}.meta_value AS {$primary_meta_query['cast']})";
   917 					$orderby = "CAST({$primary_meta_query['alias']}.meta_value AS {$primary_meta_query['cast']})";
   911 				} else {
   918 				} else {
   919 
   926 
   920 			default:
   927 			default:
   921 				if ( array_key_exists( $orderby_raw, $meta_clauses ) ) {
   928 				if ( array_key_exists( $orderby_raw, $meta_clauses ) ) {
   922 					// $orderby corresponds to a meta_query clause.
   929 					// $orderby corresponds to a meta_query clause.
   923 					$meta_clause = $meta_clauses[ $orderby_raw ];
   930 					$meta_clause = $meta_clauses[ $orderby_raw ];
   924 					$orderby = "CAST({$meta_clause['alias']}.meta_value AS {$meta_clause['cast']})";
   931 					$orderby     = "CAST({$meta_clause['alias']}.meta_value AS {$meta_clause['cast']})";
   925 				}
   932 				}
   926 				break;
   933 				break;
   927 		}
   934 		}
   928 
   935 
   929 		return $orderby;
   936 		return $orderby;