Allow get_terms()
results to ordered by metadata.
The `$orderby` parameter of `get_terms()` now accepts the following values, related to term meta: * 'meta_value' * 'meta_value_num' * the value of the `$meta_key` parameter * any key from the `$meta_query` array This brings order-by-meta support for terms in line with post, comment, and user queries. As a byproduct of these improvements, `$meta_key` and `$meta_value` parameters have been introduced to `get_terms()`. They interact with `$meta_query` in the same way as in `WP_Query` and other query classes. Props jadpm, eherman24. Fixes #34996. git-svn-id: https://develop.svn.wordpress.org/trunk@36485 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
0673904ddf
commit
eb8e2fb6ed
@ -1060,6 +1060,7 @@ function get_term_to_edit( $id, $taxonomy ) {
|
||||
* @since 4.4.0 Introduced the ability to pass 'term_id' as an alias of 'id' for the `orderby` parameter.
|
||||
* Introduced the 'meta_query' and 'update_term_meta_cache' parameters. Converted to return
|
||||
* a list of WP_Term objects.
|
||||
* @since 4.5.0 Introduced 'meta_key' and 'meta_value' parameters. Introduced the ability to order results by metadata.
|
||||
*
|
||||
* @global wpdb $wpdb WordPress database abstraction object.
|
||||
* @global array $wp_filter
|
||||
@ -1071,7 +1072,9 @@ function get_term_to_edit( $id, $taxonomy ) {
|
||||
* @type string $orderby Field(s) to order terms by. Accepts term fields ('name', 'slug',
|
||||
* 'term_group', 'term_id', 'id', 'description'), 'count' for term
|
||||
* taxonomy count, 'include' to match the 'order' of the $include param,
|
||||
* or 'none' to skip ORDER BY. Defaults to 'name'.
|
||||
* '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 $order Whether to order terms in ascending or descending order.
|
||||
* Accepts 'ASC' (ascending) or 'DESC' (descending).
|
||||
* Default 'ASC'.
|
||||
@ -1119,6 +1122,10 @@ function get_term_to_edit( $id, $taxonomy ) {
|
||||
* @type bool $update_term_meta_cache Whether to prime meta caches for matched terms. Default true.
|
||||
* @type array $meta_query Meta query clauses to limit retrieved terms by.
|
||||
* See `WP_Meta_Query`. Default empty.
|
||||
* @type string $meta_key Limit terms to those matching a specific metadata key. Can be used in
|
||||
* conjunction with `$meta_value`.
|
||||
* @type string $meta_value Limit terms to those matching a specific metadata value. Usually used
|
||||
* in conjunction with `$meta_key`.
|
||||
* }
|
||||
* @return array|int|WP_Error List of WP_Term instances and their children. Will return WP_Error, if any of $taxonomies
|
||||
* do not exist.
|
||||
@ -1414,13 +1421,53 @@ function get_terms( $taxonomies, $args = '' ) {
|
||||
// Meta query support.
|
||||
$join = '';
|
||||
$distinct = '';
|
||||
if ( ! empty( $args['meta_query'] ) ) {
|
||||
$mquery = new WP_Meta_Query( $args['meta_query'] );
|
||||
$mq_sql = $mquery->get_sql( 'term', 't', 'term_id' );
|
||||
|
||||
$mquery = new WP_Meta_Query();
|
||||
$mquery->parse_query_vars( $args );
|
||||
$mq_sql = $mquery->get_sql( 'term', 't', 'term_id' );
|
||||
$meta_clauses = $mquery->get_clauses();
|
||||
|
||||
if ( ! empty( $meta_clauses ) ) {
|
||||
$join .= $mq_sql['join'];
|
||||
$where .= $mq_sql['where'];
|
||||
$distinct .= "DISTINCT";
|
||||
|
||||
// 'orderby' support.
|
||||
$allowed_keys = array();
|
||||
$primary_meta_key = null;
|
||||
$primary_meta_query = reset( $meta_clauses );
|
||||
if ( ! empty( $primary_meta_query['key'] ) ) {
|
||||
$primary_meta_key = $primary_meta_query['key'];
|
||||
$allowed_keys[] = $primary_meta_key;
|
||||
}
|
||||
$allowed_keys[] = 'meta_value';
|
||||
$allowed_keys[] = 'meta_value_num';
|
||||
$allowed_keys = array_merge( $allowed_keys, array_keys( $meta_clauses ) );
|
||||
|
||||
if ( ! empty( $args['orderby'] ) && in_array( $args['orderby'], $allowed_keys ) ) {
|
||||
switch( $args['orderby'] ) {
|
||||
case $primary_meta_key:
|
||||
case 'meta_value':
|
||||
if ( ! empty( $primary_meta_query['type'] ) ) {
|
||||
$orderby = "ORDER BY CAST({$primary_meta_query['alias']}.meta_value AS {$primary_meta_query['cast']})";
|
||||
} else {
|
||||
$orderby = "ORDER BY {$primary_meta_query['alias']}.meta_value";
|
||||
}
|
||||
break;
|
||||
|
||||
case 'meta_value_num':
|
||||
$orderby = "ORDER BY {$primary_meta_query['alias']}.meta_value+0";
|
||||
break;
|
||||
|
||||
default:
|
||||
if ( array_key_exists( $args['orderby'], $meta_clauses ) ) {
|
||||
// $orderby corresponds to a meta_query clause.
|
||||
$meta_clause = $meta_clauses[ $args['orderby'] ];
|
||||
$orderby = "ORDER BY CAST({$meta_clause['alias']}.meta_value AS {$meta_clause['cast']})";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$selects = array();
|
||||
|
@ -1233,6 +1233,337 @@ class Tests_Term_getTerms extends WP_UnitTestCase {
|
||||
$this->assertEquals( array( $t1, $t2, $t3 ), $found );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 34996
|
||||
*/
|
||||
public function test_orderby_meta_value() {
|
||||
register_taxonomy( 'wptests_tax', 'post' );
|
||||
$terms = self::factory()->term->create_many( 3, array( 'taxonomy' => 'wptests_tax' ) );
|
||||
add_term_meta( $terms[0], 'foo', 'zzz' );
|
||||
add_term_meta( $terms[0], 'fee', 'ber' );
|
||||
add_term_meta( $terms[1], 'foo', 'aaa' );
|
||||
add_term_meta( $terms[1], 'fee', 'ber' );
|
||||
add_term_meta( $terms[2], 'foo', 'jjj' );
|
||||
add_term_meta( $terms[2], 'fee', 'ber' );
|
||||
|
||||
// Matches the first meta query clause.
|
||||
$found = get_terms( 'wptests_tax', array(
|
||||
'hide_empty' => false,
|
||||
'meta_query' => array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
array(
|
||||
'key' => 'fee',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
),
|
||||
'orderby' => 'meta_value',
|
||||
'order' => 'ASC',
|
||||
'fields' => 'ids',
|
||||
) );
|
||||
|
||||
$this->assertEqualSets( array( $terms[1], $terms[2], $terms[0] ), $found );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 34996
|
||||
*/
|
||||
public function test_orderby_meta_value_num() {
|
||||
register_taxonomy( 'wptests_tax', 'post' );
|
||||
$terms = self::factory()->term->create_many( 3, array( 'taxonomy' => 'wptests_tax' ) );
|
||||
add_term_meta( $terms[0], 'foo', '999' );
|
||||
add_term_meta( $terms[0], 'fee', 'ber' );
|
||||
add_term_meta( $terms[1], 'foo', '111' );
|
||||
add_term_meta( $terms[1], 'fee', 'ber' );
|
||||
add_term_meta( $terms[2], 'foo', '555' );
|
||||
add_term_meta( $terms[2], 'fee', 'ber' );
|
||||
|
||||
// Matches the first meta query clause.
|
||||
$found = get_terms( 'wptests_tax', array(
|
||||
'hide_empty' => false,
|
||||
'meta_query' => array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
array(
|
||||
'key' => 'fee',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
),
|
||||
'orderby' => 'meta_value_num',
|
||||
'order' => 'ASC',
|
||||
'fields' => 'ids',
|
||||
) );
|
||||
|
||||
$this->assertEqualSets( array( $terms[1], $terms[2], $terms[0] ), $found );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 34996
|
||||
*/
|
||||
public function test_orderby_meta_value_with_meta_key() {
|
||||
register_taxonomy( 'wptests_tax', 'post' );
|
||||
$terms = self::factory()->term->create_many( 3, array( 'taxonomy' => 'wptests_tax' ) );
|
||||
add_term_meta( $terms[0], 'foo', 'bar' );
|
||||
add_term_meta( $terms[0], 'fee', 'zzz' );
|
||||
add_term_meta( $terms[0], 'faa', 'jjj' );
|
||||
add_term_meta( $terms[1], 'foo', 'bar' );
|
||||
add_term_meta( $terms[1], 'fee', 'aaa' );
|
||||
add_term_meta( $terms[1], 'faa', 'aaa' );
|
||||
add_term_meta( $terms[2], 'foo', 'bar' );
|
||||
add_term_meta( $terms[2], 'fee', 'jjj' );
|
||||
add_term_meta( $terms[2], 'faa', 'zzz' );
|
||||
|
||||
$found = get_terms( 'wptests_tax', array(
|
||||
'hide_empty' => false,
|
||||
'meta_key' => 'fee',
|
||||
'orderby' => 'meta_value',
|
||||
'order' => 'ASC',
|
||||
'fields' => 'ids',
|
||||
) );
|
||||
|
||||
$this->assertEqualSets( array( $terms[1], $terms[2], $terms[0] ), $found );
|
||||
|
||||
$found = get_terms( 'wptests_tax', array(
|
||||
'hide_empty' => false,
|
||||
'meta_query' => array(
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
),
|
||||
'meta_key' => 'fee',
|
||||
'orderby' => 'meta_value',
|
||||
'order' => 'ASC',
|
||||
'fields' => 'ids',
|
||||
) );
|
||||
|
||||
$this->assertEqualSets( array( $terms[1], $terms[2], $terms[0] ), $found );
|
||||
|
||||
// Matches the first meta query clause.
|
||||
$found = get_terms( 'wptests_tax', array(
|
||||
'hide_empty' => false,
|
||||
'meta_query' => array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
array(
|
||||
'key' => 'fee',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
),
|
||||
'meta_key' => 'fee',
|
||||
'orderby' => 'meta_value',
|
||||
'order' => 'ASC',
|
||||
'fields' => 'ids',
|
||||
) );
|
||||
|
||||
$this->assertEqualSets( array( $terms[1], $terms[2], $terms[0] ), $found );
|
||||
|
||||
// Matches the meta query clause corresponding to the 'meta_key' param.
|
||||
$found = get_terms( 'wptests_tax', array(
|
||||
'hide_empty' => false,
|
||||
'meta_query' => array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
array(
|
||||
'key' => 'fee',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
),
|
||||
'meta_key' => 'faa',
|
||||
'orderby' => 'meta_value',
|
||||
'order' => 'ASC',
|
||||
'fields' => 'ids',
|
||||
) );
|
||||
|
||||
$this->assertEqualSets( array( $terms[1], $terms[0], $terms[2] ), $found );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 34996
|
||||
*/
|
||||
public function test_orderby_meta_value_num_with_meta_key() {
|
||||
register_taxonomy( 'wptests_tax', 'post' );
|
||||
$terms = self::factory()->term->create_many( 3, array( 'taxonomy' => 'wptests_tax' ) );
|
||||
add_term_meta( $terms[0], 'foo', 'bar' );
|
||||
add_term_meta( $terms[0], 'fee', '999' );
|
||||
add_term_meta( $terms[0], 'faa', '555' );
|
||||
add_term_meta( $terms[1], 'foo', 'bar' );
|
||||
add_term_meta( $terms[1], 'fee', '111' );
|
||||
add_term_meta( $terms[1], 'faa', '111' );
|
||||
add_term_meta( $terms[2], 'foo', 'bar' );
|
||||
add_term_meta( $terms[2], 'fee', '555' );
|
||||
add_term_meta( $terms[2], 'faa', '999' );
|
||||
|
||||
$found = get_terms( 'wptests_tax', array(
|
||||
'hide_empty' => false,
|
||||
'meta_key' => 'fee',
|
||||
'orderby' => 'meta_value',
|
||||
'order' => 'ASC',
|
||||
'fields' => 'ids',
|
||||
) );
|
||||
|
||||
$this->assertEqualSets( array( $terms[1], $terms[2], $terms[0] ), $found );
|
||||
|
||||
$found = get_terms( 'wptests_tax', array(
|
||||
'hide_empty' => false,
|
||||
'meta_query' => array(
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
),
|
||||
'meta_key' => 'fee',
|
||||
'orderby' => 'meta_value',
|
||||
'order' => 'ASC',
|
||||
'fields' => 'ids',
|
||||
) );
|
||||
|
||||
$this->assertEqualSets( array( $terms[1], $terms[2], $terms[0] ), $found );
|
||||
|
||||
$found = get_terms( 'wptests_tax', array(
|
||||
'hide_empty' => false,
|
||||
'meta_query' => array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
array(
|
||||
'key' => 'fee',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
),
|
||||
'meta_key' => 'fee',
|
||||
'orderby' => 'meta_value',
|
||||
'order' => 'ASC',
|
||||
'fields' => 'ids',
|
||||
) );
|
||||
|
||||
$this->assertEqualSets( array( $terms[1], $terms[2], $terms[0] ), $found );
|
||||
|
||||
$found = get_terms( 'wptests_tax', array(
|
||||
'hide_empty' => false,
|
||||
'meta_query' => array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
array(
|
||||
'key' => 'fee',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
),
|
||||
'meta_key' => 'faa',
|
||||
'orderby' => 'meta_value',
|
||||
'order' => 'ASC',
|
||||
'fields' => 'ids',
|
||||
) );
|
||||
|
||||
$this->assertEqualSets( array( $terms[1], $terms[0], $terms[2] ), $found );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 34996
|
||||
*/
|
||||
public function test_orderby_clause_key() {
|
||||
register_taxonomy( 'wptests_tax', 'post' );
|
||||
$terms = self::factory()->term->create_many( 3, array( 'taxonomy' => 'wptests_tax' ) );
|
||||
add_term_meta( $terms[0], 'foo', 'zzz' );
|
||||
add_term_meta( $terms[0], 'fee', 'jjj' );
|
||||
add_term_meta( $terms[1], 'foo', 'aaa' );
|
||||
add_term_meta( $terms[1], 'fee', 'aaa' );
|
||||
add_term_meta( $terms[2], 'foo', 'jjj' );
|
||||
add_term_meta( $terms[2], 'fee', 'zzz' );
|
||||
|
||||
$found = get_terms( 'wptests_tax', array(
|
||||
'hide_empty' => false,
|
||||
'meta_query' => array(
|
||||
'relation' => 'AND',
|
||||
'foo_key' => array(
|
||||
'key' => 'foo',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
'fee_key' => array(
|
||||
'key' => 'fee',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
),
|
||||
'orderby' => 'foo_key',
|
||||
'order' => 'ASC',
|
||||
'fields' => 'ids',
|
||||
) );
|
||||
|
||||
$this->assertEqualSets( array( $terms[1], $terms[2], $terms[0] ), $found );
|
||||
|
||||
$found = get_terms( 'wptests_tax', array(
|
||||
'hide_empty' => false,
|
||||
'meta_query' => array(
|
||||
'relation' => 'AND',
|
||||
'foo_key' => array(
|
||||
'key' => 'foo',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
'fee_key' => array(
|
||||
'key' => 'fee',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
),
|
||||
'orderby' => 'fee_key',
|
||||
'order' => 'ASC',
|
||||
'fields' => 'ids',
|
||||
) );
|
||||
|
||||
$this->assertEqualSets( array( $terms[1], $terms[0], $terms[2] ), $found );
|
||||
|
||||
$expected = get_terms( 'wptests_tax', array(
|
||||
'hide_empty' => false,
|
||||
'meta_query' => array(
|
||||
'relation' => 'AND',
|
||||
'foo_key' => array(
|
||||
'key' => 'foo',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
'fee_key' => array(
|
||||
'key' => 'fee',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
),
|
||||
'fields' => 'ids',
|
||||
) );
|
||||
|
||||
$found = get_terms( 'wptests_tax', array(
|
||||
'hide_empty' => false,
|
||||
'meta_query' => array(
|
||||
'relation' => 'AND',
|
||||
'foo_key' => array(
|
||||
'key' => 'foo',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
'fee_key' => array(
|
||||
'key' => 'fee',
|
||||
'compare' => 'EXISTS',
|
||||
),
|
||||
),
|
||||
'orderby' => 'faa_key',
|
||||
'fields' => 'ids',
|
||||
) );
|
||||
|
||||
$this->assertEqualSets( $expected, $found );
|
||||
}
|
||||
|
||||
public function test_hierarchical_false_with_parent() {
|
||||
$initial_terms = $this->create_hierarchical_terms();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user