--- a/wp/wp-includes/class-wp-term-query.php Tue Oct 22 16:11:46 2019 +0200
+++ b/wp/wp-includes/class-wp-term-query.php Tue Dec 15 13:49:49 2020 +0100
@@ -29,7 +29,7 @@
* Metadata query container.
*
* @since 4.6.0
- * @var object WP_Meta_Query
+ * @var WP_Meta_Query A meta query instance.
*/
public $meta_query = false;
@@ -96,24 +96,29 @@
* be limited.
* @type int|array $object_ids Optional. Object ID, or array of object IDs. Results will be
* limited to terms associated with these objects.
- * @type string $orderby Field(s) to order terms by. Accepts term fields ('name',
- * 'slug', 'term_group', 'term_id', 'id', 'description', 'parent'),
- * 'count' for term taxonomy count, 'include' to match the
- * 'order' of the $include param, 'slug__in' to match the
- * 'order' of the $slug param, 'meta_value', 'meta_value_num',
- * the value of `$meta_key`, the array keys of `$meta_query`, or
- * 'none' to omit the ORDER BY clause. Defaults to 'name'.
+ * @type string $orderby Field(s) to order terms by. Accepts:
+ * - term fields ('name', 'slug', 'term_group', 'term_id', 'id',
+ * 'description', 'parent', 'term_order'). Unless `$object_ids`
+ * is not empty, 'term_order' is treated the same as 'term_id'.
+ * - 'count' for term taxonomy count.
+ * - 'include' to match the 'order' of the $include param.
+ * - 'slug__in' to match the 'order' of the $slug param.
+ * - 'meta_value', 'meta_value_num'.
+ * - the value of `$meta_key`.
+ * - the array keys of `$meta_query`.
+ * - 'none' to omit the ORDER BY clause.
+ * Defaults to 'name'.
* @type string $order Whether to order terms in ascending or descending order.
* Accepts 'ASC' (ascending) or 'DESC' (descending).
* Default 'ASC'.
* @type bool|int $hide_empty Whether to hide terms not assigned to any posts. Accepts
* 1|true or 0|false. Default 1|true.
- * @type array|string $include Array or comma/space-separated string of term ids to include.
+ * @type array|string $include Array or comma/space-separated string of term IDs to include.
* Default empty array.
- * @type array|string $exclude Array or comma/space-separated string of term ids to exclude.
+ * @type array|string $exclude Array or comma/space-separated string of term IDs to exclude.
* If $include is non-empty, $exclude is ignored.
* Default empty array.
- * @type array|string $exclude_tree Array or comma/space-separated string of term ids to exclude
+ * @type array|string $exclude_tree Array or comma/space-separated string of term IDs to exclude
* along with all of their descendant terms. If $include is
* non-empty, $exclude_tree is ignored. Default empty array.
* @type int|string $number Maximum number of terms to return. Accepts ''|0 (all) or any
@@ -121,29 +126,33 @@
* not return accurate results when coupled with $object_ids.
* See #41796 for details.
* @type int $offset The number by which to offset the terms query. Default empty.
- * @type string $fields Term fields to query for. Accepts 'all' (returns an array of
- * complete term objects), 'all_with_object_id' (returns an
- * array of term objects with the 'object_id' param; works only
- * when the `$object_ids` parameter is populated), 'ids'
- * (returns an array of ids), 'tt_ids' (returns an array of
- * term taxonomy ids), 'id=>parent' (returns an associative
- * array with ids as keys, parent term IDs as values), 'names'
- * (returns an array of term names), 'count' (returns the number
- * of matching terms), 'id=>name' (returns an associative array
- * with ids as keys, term names as values), or 'id=>slug'
- * (returns an associative array with ids as keys, term slugs
- * as values). Default 'all'.
- * @type bool $count Whether to return a term count (true) or array of term objects
- * (false). Will take precedence over `$fields` if true.
- * Default false.
+ * @type string $fields Term fields to query for. Accepts:
+ * - 'all' Returns an array of complete term objects (`WP_Term[]`).
+ * - 'all_with_object_id' Returns an array of term objects
+ * with the 'object_id' param (`WP_Term[]`). Works only
+ * when the `$object_ids` parameter is populated.
+ * - 'ids' Returns an array of term IDs (`int[]`).
+ * - 'tt_ids' Returns an array of term taxonomy IDs (`int[]`).
+ * - 'names' Returns an array of term names (`string[]`).
+ * - 'slugs' Returns an array of term slugs (`string[]`).
+ * - 'count' Returns the number of matching terms (`int`).
+ * - 'id=>parent' Returns an associative array of parent term IDs,
+ * keyed by term ID (`int[]`).
+ * - 'id=>name' Returns an associative array of term names,
+ * keyed by term ID (`string[]`).
+ * - 'id=>slug' Returns an associative array of term slugs,
+ * keyed by term ID (`string[]`).
+ * Default 'all'.
+ * @type bool $count Whether to return a term count. If true, will take precedence
+ * over `$fields`. Default false.
* @type string|array $name Optional. Name or array of names to return term(s) for.
* Default empty.
* @type string|array $slug Optional. Slug or array of slugs to return term(s) for.
* Default empty.
* @type int|array $term_taxonomy_id Optional. Term taxonomy ID, or array of term taxonomy IDs,
* to match when querying terms.
- * @type bool $hierarchical Whether to include terms that have non-empty descendants (even
- * if $hide_empty is set to true). Default true.
+ * @type bool $hierarchical Whether to include terms that have non-empty descendants
+ * (even if $hide_empty is set to true). Default true.
* @type string $search Search criteria to match terms. Will be SQL-formatted with
* wildcards before and after. Default empty.
* @type string $name__like Retrieve terms with criteria by which a term is LIKE
@@ -253,7 +262,7 @@
$query['child_of'] = false;
}
- if ( 'all' == $query['get'] ) {
+ if ( 'all' === $query['get'] ) {
$query['childless'] = false;
$query['child_of'] = 0;
$query['hide_empty'] = 0;
@@ -326,6 +335,9 @@
$has_hierarchical_tax = true;
}
}
+ } else {
+ // When no taxonomies are provided, assume we have to descend the tree.
+ $has_hierarchical_tax = true;
}
if ( ! $has_hierarchical_tax ) {
@@ -338,7 +350,7 @@
$args['child_of'] = false;
}
- if ( 'all' == $args['get'] ) {
+ if ( 'all' === $args['get'] ) {
$args['childless'] = false;
$args['child_of'] = 0;
$args['hide_empty'] = 0;
@@ -379,7 +391,7 @@
}
if ( ! $in_hierarchy ) {
- if ( 'count' == $args['fields'] ) {
+ if ( 'count' === $args['fields'] ) {
return 0;
} else {
$this->terms = array();
@@ -393,6 +405,7 @@
if ( 'term_order' === $_orderby && empty( $this->query_vars['object_ids'] ) ) {
$_orderby = 'term_id';
}
+
$orderby = $this->parse_orderby( $_orderby );
if ( $orderby ) {
@@ -428,8 +441,8 @@
$excluded_children = array_merge(
$excluded_children,
(array) get_terms(
- reset( $taxonomies ),
array(
+ 'taxonomy' => reset( $taxonomies ),
'child_of' => intval( $extrunk ),
'fields' => 'ids',
'hide_empty' => 0,
@@ -542,7 +555,7 @@
}
$hierarchical = $args['hierarchical'];
- if ( 'count' == $args['fields'] ) {
+ if ( 'count' === $args['fields'] ) {
$hierarchical = false;
}
if ( $args['hide_empty'] && ! $hierarchical ) {
@@ -607,10 +620,10 @@
$selects = array( 'COUNT(*)' );
break;
case 'id=>name':
- $selects = array( 't.term_id', 't.name', 'tt.count', 'tt.taxonomy' );
+ $selects = array( 't.term_id', 't.name', 'tt.parent', 'tt.count', 'tt.taxonomy' );
break;
case 'id=>slug':
- $selects = array( 't.term_id', 't.slug', 'tt.count', 'tt.taxonomy' );
+ $selects = array( 't.term_id', 't.slug', 'tt.parent', 'tt.count', 'tt.taxonomy' );
break;
}
@@ -672,6 +685,25 @@
$this->request = "{$this->sql_clauses['select']} {$this->sql_clauses['from']} {$where} {$this->sql_clauses['orderby']} {$this->sql_clauses['limits']}";
+ $this->terms = null;
+
+ /**
+ * Filter the terms array before the query takes place.
+ *
+ * Return a non-null value to bypass WordPress's default term queries.
+ *
+ * @since 5.3.0
+ *
+ * @param array|null $terms Return an array of term data to short-circuit WP's term query,
+ * or null to allow WP queries to run normally.
+ * @param WP_Term_Query $this The WP_Term_Query instance, passed by reference.
+ */
+ $this->terms = apply_filters_ref_array( 'terms_pre_query', array( $this->terms, &$this ) );
+
+ if ( null !== $this->terms ) {
+ return $this->terms;
+ }
+
// $args can be anything. Only use the args defined in defaults to compute the key.
$key = md5( serialize( wp_array_slice_assoc( $args, array_keys( $this->query_var_defaults ) ) ) . serialize( $taxonomies ) . $this->request );
$last_changed = wp_cache_get_last_changed( 'terms' );
@@ -686,14 +718,15 @@
return $this->terms;
}
- if ( 'count' == $_fields ) {
+ if ( 'count' === $_fields ) {
$count = $wpdb->get_var( $this->request );
wp_cache_set( $cache_key, $count, 'terms' );
return $count;
}
$terms = $wpdb->get_results( $this->request );
- if ( 'all' == $_fields || 'all_with_object_id' === $_fields ) {
+
+ if ( 'all' === $_fields || 'all_with_object_id' === $_fields ) {
update_term_cache( $terms );
}
@@ -718,7 +751,7 @@
}
// Update term counts to include children.
- if ( $args['pad_counts'] && 'all' == $_fields ) {
+ if ( $args['pad_counts'] && 'all' === $_fields ) {
foreach ( $taxonomies as $_tax ) {
_pad_term_counts( $terms, $_tax );
}
@@ -750,8 +783,9 @@
* `$fields` is 'all_with_object_id', but should otherwise be
* removed.
*/
- if ( ! empty( $args['object_ids'] ) && 'all_with_object_id' != $_fields ) {
- $_tt_ids = $_terms = array();
+ if ( ! empty( $args['object_ids'] ) && 'all_with_object_id' !== $_fields ) {
+ $_tt_ids = array();
+ $_terms = array();
foreach ( $terms as $term ) {
if ( isset( $_tt_ids[ $term->term_id ] ) ) {
continue;
@@ -765,31 +799,31 @@
}
$_terms = array();
- if ( 'id=>parent' == $_fields ) {
+ if ( 'id=>parent' === $_fields ) {
foreach ( $terms as $term ) {
$_terms[ $term->term_id ] = $term->parent;
}
- } elseif ( 'ids' == $_fields ) {
+ } elseif ( 'ids' === $_fields ) {
foreach ( $terms as $term ) {
$_terms[] = (int) $term->term_id;
}
- } elseif ( 'tt_ids' == $_fields ) {
+ } elseif ( 'tt_ids' === $_fields ) {
foreach ( $terms as $term ) {
$_terms[] = (int) $term->term_taxonomy_id;
}
- } elseif ( 'names' == $_fields ) {
+ } elseif ( 'names' === $_fields ) {
foreach ( $terms as $term ) {
$_terms[] = $term->name;
}
- } elseif ( 'slugs' == $_fields ) {
+ } elseif ( 'slugs' === $_fields ) {
foreach ( $terms as $term ) {
$_terms[] = $term->slug;
}
- } elseif ( 'id=>name' == $_fields ) {
+ } elseif ( 'id=>name' === $_fields ) {
foreach ( $terms as $term ) {
$_terms[ $term->term_id ] = $term->name;
}
- } elseif ( 'id=>slug' == $_fields ) {
+ } elseif ( 'id=>slug' === $_fields ) {
foreach ( $terms as $term ) {
$_terms[ $term->term_id ] = $term->slug;
}
@@ -838,15 +872,15 @@
$orderby = "tt.$_orderby";
} elseif ( 'term_order' === $_orderby ) {
$orderby = 'tr.term_order';
- } elseif ( 'include' == $_orderby && ! empty( $this->query_vars['include'] ) ) {
+ } elseif ( 'include' === $_orderby && ! empty( $this->query_vars['include'] ) ) {
$include = implode( ',', wp_parse_id_list( $this->query_vars['include'] ) );
$orderby = "FIELD( t.term_id, $include )";
- } elseif ( 'slug__in' == $_orderby && ! empty( $this->query_vars['slug'] ) && is_array( $this->query_vars['slug'] ) ) {
+ } elseif ( 'slug__in' === $_orderby && ! empty( $this->query_vars['slug'] ) && is_array( $this->query_vars['slug'] ) ) {
$slugs = implode( "', '", array_map( 'sanitize_title_for_query', $this->query_vars['slug'] ) );
$orderby = "FIELD( t.slug, '" . $slugs . "')";
- } elseif ( 'none' == $_orderby ) {
+ } elseif ( 'none' === $_orderby ) {
$orderby = '';
- } elseif ( empty( $_orderby ) || 'id' == $_orderby || 'term_id' === $_orderby ) {
+ } elseif ( empty( $_orderby ) || 'id' === $_orderby || 'term_id' === $_orderby ) {
$orderby = 't.term_id';
} else {
$orderby = 't.name';