diff --git src/wp-includes/class-wp-tax-query.php src/wp-includes/class-wp-tax-query.php
index 4b58635..cdefcd8 100644
|
|
class WP_Tax_Query { |
90 | 90 | * |
91 | 91 | * @since 3.1.0 |
92 | 92 | * @since 4.1.0 Added support for `$operator` 'NOT EXISTS' and 'EXISTS' values. |
| 93 | * @since 5.0.0 Added support for `$operator` 'BETWEEN' values. |
93 | 94 | * |
94 | 95 | * @param array $tax_query { |
95 | 96 | * Array of taxonomy query clauses. |
… |
… |
class WP_Tax_Query { |
104 | 105 | * @type string $field Field to match $terms against. Accepts 'term_id', 'slug', |
105 | 106 | * 'name', or 'term_taxonomy_id'. Default: 'term_id'. |
106 | 107 | * @type string $operator MySQL operator to be used with $terms in the WHERE clause. |
107 | | * Accepts 'AND', 'IN', 'NOT IN', 'EXISTS', 'NOT EXISTS'. |
| 108 | * Accepts 'AND', 'IN', 'NOT IN', 'EXISTS', 'NOT EXISTS', 'BETWEEN'. |
108 | 109 | * Default: 'IN'. |
109 | 110 | * @type bool $include_children Optional. Whether to include child terms. |
110 | 111 | * Requires a $taxonomy. Default: true. |
… |
… |
class WP_Tax_Query { |
399 | 400 | $terms = $clause['terms']; |
400 | 401 | $operator = strtoupper( $clause['operator'] ); |
401 | 402 | |
402 | | if ( 'IN' == $operator ) { |
| 403 | if ( 'IN' == $operator || 'BETWEEN' == $operator ) { |
403 | 404 | |
404 | 405 | if ( empty( $terms ) ) { |
405 | 406 | return self::$no_results; |
… |
… |
class WP_Tax_Query { |
427 | 428 | $join .= " ON ($this->primary_table.$this->primary_id_column = $alias.object_id)"; |
428 | 429 | } |
429 | 430 | |
| 431 | $operator = 'IN'; |
| 432 | |
430 | 433 | $where = "$alias.term_taxonomy_id $operator ($terms)"; |
431 | 434 | |
432 | 435 | } elseif ( 'NOT IN' == $operator ) { |
… |
… |
class WP_Tax_Query { |
621 | 624 | $args['slug'] = $terms; |
622 | 625 | break; |
623 | 626 | case 'name': |
624 | | $args['name'] = $terms; |
| 627 | if ( 'BETWEEN' == strtoupper( $query['operator'] ) ) { |
| 628 | $args['name__between'] = $terms; |
| 629 | } else { |
| 630 | $args['name'] = $terms; |
| 631 | } |
625 | 632 | break; |
626 | 633 | case 'term_taxonomy_id': |
627 | 634 | $args['term_taxonomy_id'] = $terms; |
diff --git src/wp-includes/class-wp-term-query.php src/wp-includes/class-wp-term-query.php
index 5890bf7..a3e7eda 100644
|
|
class WP_Term_Query { |
88 | 88 | * @since 4.6.0 Introduced 'term_taxonomy_id' parameter. |
89 | 89 | * @since 4.7.0 Introduced 'object_ids' parameter. |
90 | 90 | * @since 4.9.0 Added 'slug__in' support for 'orderby'. |
| 91 | * @since 5.0.0 Added 'name__between' parameter. |
91 | 92 | * |
92 | 93 | * @param string|array $query { |
93 | 94 | * Optional. Array or query string of term query parameters. Default empty. |
… |
… |
class WP_Term_Query { |
148 | 149 | * wildcards before and after. Default empty. |
149 | 150 | * @type string $name__like Retrieve terms with criteria by which a term is LIKE |
150 | 151 | * `$name__like`. Default empty. |
| 152 | * @type string $name__between Retrieve terms with criteria by which a term is BETWEEN |
| 153 | * the two array values supplied in `$name__between`. Default empty. |
151 | 154 | * @type string $description__like Retrieve terms where the description is LIKE |
152 | 155 | * `$description__like`. Default empty. |
153 | 156 | * @type bool $pad_counts Whether to pad the quantity of a term's children in the |
… |
… |
class WP_Term_Query { |
197 | 200 | 'hierarchical' => true, |
198 | 201 | 'search' => '', |
199 | 202 | 'name__like' => '', |
| 203 | 'name__between' => '', |
200 | 204 | 'description__like' => '', |
201 | 205 | 'pad_counts' => false, |
202 | 206 | 'get' => '', |
… |
… |
class WP_Term_Query { |
513 | 517 | $this->sql_clauses['where']['name__like'] = $wpdb->prepare( 't.name LIKE %s', '%' . $wpdb->esc_like( $args['name__like'] ) . '%' ); |
514 | 518 | } |
515 | 519 | |
| 520 | if ( ! empty( $args['name__between'] ) ) { |
| 521 | $this->sql_clauses['where']['name__between'] = $wpdb->prepare( 'CAST(t.name AS SIGNED) BETWEEN %s AND %s', array_slice( $args['name__between'], 0, 2 ) ); |
| 522 | } |
| 523 | |
516 | 524 | if ( ! empty( $args['description__like'] ) ) { |
517 | 525 | $this->sql_clauses['where']['description__like'] = $wpdb->prepare( 'tt.description LIKE %s', '%' . $wpdb->esc_like( $args['description__like'] ) . '%' ); |
518 | 526 | } |
diff --git tests/phpunit/tests/query/taxQuery.php tests/phpunit/tests/query/taxQuery.php
index fea31ed..7add121 100644
|
|
class Tests_Query_TaxQuery extends WP_UnitTestCase { |
1620 | 1620 | |
1621 | 1621 | $this->assertEqualSets( array( $p ), $q->posts ); |
1622 | 1622 | } |
| 1623 | |
| 1624 | public function test_tax_terms_between() { |
| 1625 | register_taxonomy( $tax = 'height', 'post' ); |
| 1626 | |
| 1627 | $posts = array(); |
| 1628 | |
| 1629 | foreach ( range( 0, 20 ) as $height ) { |
| 1630 | $t = self::factory()->term->create( |
| 1631 | array( |
| 1632 | 'name' => strval( $height ), |
| 1633 | 'taxonomy' => $tax, |
| 1634 | ) |
| 1635 | ); |
| 1636 | |
| 1637 | $p = self::factory()->post->create(); |
| 1638 | wp_set_object_terms( $p, array( $t ), $tax ); |
| 1639 | $posts[] = $p; |
| 1640 | } |
| 1641 | |
| 1642 | $q = new WP_Query( |
| 1643 | array( |
| 1644 | 'fields' => 'ids', |
| 1645 | 'tax_query' => array( |
| 1646 | array( |
| 1647 | 'taxonomy' => $tax, |
| 1648 | 'operator' => 'between', |
| 1649 | 'field' => 'name', |
| 1650 | 'terms' => array( 7, 13 ), |
| 1651 | ), |
| 1652 | ), |
| 1653 | ) |
| 1654 | ); |
| 1655 | |
| 1656 | $this->assertEqualSets( array_slice( $posts, 7, 7 ), $q->posts ); |
| 1657 | } |
1623 | 1658 | } |
diff --git tests/phpunit/tests/term/getTerms.php tests/phpunit/tests/term/getTerms.php
index 6e38eea..dc2fa83 100644
|
|
class Tests_Term_getTerms extends WP_UnitTestCase { |
2841 | 2841 | $this->assertEqualSets( array( $term_id1, $term_id2 ), wp_list_pluck( $found, 'term_id' ) ); |
2842 | 2842 | } |
2843 | 2843 | |
| 2844 | public function test_get_terms_between() { |
| 2845 | register_taxonomy( $tax = 'length', 'post' ); |
| 2846 | |
| 2847 | $term_ids = array(); |
| 2848 | |
| 2849 | foreach ( range( 0, 20 ) as $length ) { |
| 2850 | $term_ids[] = self::factory()->term->create( |
| 2851 | array( |
| 2852 | 'name' => strval( $length ), |
| 2853 | 'taxonomy' => $tax, |
| 2854 | ) |
| 2855 | ); |
| 2856 | } |
| 2857 | |
| 2858 | $terms = get_terms( |
| 2859 | $tax, array( |
| 2860 | 'hide_empty' => false, |
| 2861 | 'name__between' => array( 7, 13 ), |
| 2862 | 'fields' => 'ids', |
| 2863 | ) |
| 2864 | ); |
| 2865 | $this->assertEqualSets( array_slice( $term_ids, 7, 7 ), $terms ); |
| 2866 | } |
| 2867 | |
2844 | 2868 | protected function create_hierarchical_terms_and_posts() { |
2845 | 2869 | $terms = array(); |
2846 | 2870 | |