In `get_terms()`, do not override 'hierarchical' and 'pad_counts' when 'parent' is present.

The previous behavior resulted in descendant terms being improperly excluded
from the results when passing a 'parent', even when 'hierarchical' had been
set to true.

The patch also adds unit tests that demonstrate the various interactions
between the 'child_of', 'parent', and 'hierarchical' parameters of `get_terms()`.

Props landakram.
Fixes #29815.

git-svn-id: https://develop.svn.wordpress.org/trunk@30107 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Boone Gorges 2014-10-30 02:11:56 +00:00
parent 2988aa8ba7
commit cf1d77c101
2 changed files with 226 additions and 4 deletions

View File

@ -1628,13 +1628,19 @@ function get_terms( $taxonomies, $args = '' ) {
$args = wp_parse_args( $args, $defaults );
$args['number'] = absint( $args['number'] );
$args['offset'] = absint( $args['offset'] );
if ( !$single_taxonomy || ! is_taxonomy_hierarchical( reset( $taxonomies ) ) ||
( '' !== $args['parent'] && 0 !== $args['parent'] ) ) {
$args['child_of'] = 0;
// Save queries by not crawling the tree in the case of multiple taxes or a flat tax.
if ( ! $single_taxonomy || ! is_taxonomy_hierarchical( reset( $taxonomies ) ) ) {
$args['child_of'] = false;
$args['hierarchical'] = false;
$args['pad_counts'] = false;
}
// 'parent' overrides 'child_of'.
if ( 0 < intval( $args['parent'] ) ) {
$args['child_of'] = false;
}
if ( 'all' == $args['get'] ) {
$args['child_of'] = 0;
$args['hide_empty'] = 0;

View File

@ -820,8 +820,151 @@ class Tests_Term_getTerms extends WP_UnitTestCase {
$this->assertEquals( array( $t4, $t1, $t2 ), $found );
}
protected function create_hierarchical_terms_and_posts() {
public function test_hierarchical_false_with_parent() {
$initial_terms = $this->create_hierarchical_terms();
// Case where hierarchical is false
$terms = get_terms( 'category', array(
'hierarchical' => false,
'parent' => $initial_terms['one_term']['term_id']
) );
// Verify that there are no children
$this->assertEquals( 0, count( $terms ) );
}
/**
* @ticket 29185
*/
public function test_hierarchical_true_with_parent() {
$initial_terms = $this->create_hierarchical_terms();
// Case where hierarchical is true
$terms = get_terms( 'category', array(
'hierarchical' => true,
'parent' => $initial_terms['one_term']['term_id']
) );
// Verify that the children with non-empty descendants are returned
$expected = array(
$initial_terms['two_term']['term_id'],
$initial_terms['five_term']['term_id'],
);
$actual = wp_list_pluck( $terms, 'term_id' );
$this->assertEqualSets( $expected, $actual );
}
public function test_hierarchical_false_with_child_of_and_direct_child() {
$initial_terms = $this->create_hierarchical_terms();
$post_id = $this->factory->post->create();
wp_set_post_terms(
$post_id,
array( $initial_terms['seven_term']['term_id'] ),
'category'
);
// Case where hierarchical is false
$terms = get_terms( 'category', array(
'hierarchical' => false,
'child_of' => $initial_terms['one_term']['term_id']
) );
$expected = array(
$initial_terms['seven_term']['term_id'],
);
$actual = wp_list_pluck( $terms, 'term_id' );
$this->assertEqualSets( $expected, $actual );
}
public function test_hierarchical_false_with_child_of_should_not_return_grandchildren() {
$initial_terms = $this->create_hierarchical_terms();
// Case where hierarchical is false
$terms = get_terms( 'category', array(
'hierarchical' => false,
'child_of' => $initial_terms['one_term']['term_id']
) );
// Verify that there are no children
$this->assertEquals( 0, count( $terms ) );
}
public function test_hierarchical_true_with_child_of_should_return_grandchildren() {
$initial_terms = $this->create_hierarchical_terms();
// Case where hierarchical is true
$terms = get_terms( 'category', array(
'hierarchical' => true,
'child_of' => $initial_terms['one_term']['term_id']
) );
$expected = array(
$initial_terms['two_term']['term_id'],
$initial_terms['three_term']['term_id'],
$initial_terms['five_term']['term_id'],
$initial_terms['six_term']['term_id'],
);
$actual = wp_list_pluck( $terms, 'term_id' );
$this->assertEqualSets( $expected, $actual );
}
public function test_parent_should_override_child_of() {
$initial_terms = $this->create_hierarchical_terms();
$terms = get_terms( 'category', array(
'hide_empty' => false,
'child_of' => $initial_terms['one_term']['term_id'],
'parent' => $initial_terms['one_term']['term_id']
) );
// Verify that parent takes precedence over child_of and returns only direct children.
$expected = array(
$initial_terms['two_term']['term_id'],
$initial_terms['five_term']['term_id'],
$initial_terms['seven_term']['term_id']
);
$actual = wp_list_pluck( $terms, 'term_id' );
$this->assertEqualSets( $expected, $actual );
}
public function test_hierarchical_false_parent_should_override_child_of() {
$initial_terms = $this->create_hierarchical_terms();
// Case where hierarchical is false
$terms = get_terms( 'category', array(
'hierarchical' => false,
'child_of' => $initial_terms['one_term']['term_id'],
'parent' => $initial_terms['one_term']['term_id']
) );
// hierarchical=false means that descendants are not fetched.
$this->assertEquals( 0, count( $terms ) );
}
/**
* @ticket 29185
*/
public function test_hierarchical_true_parent_overrides_child_of() {
$initial_terms = $this->create_hierarchical_terms();
// Case where hierarchical is true
$terms = get_terms( 'category', array(
'hierarchical' => true,
'child_of' => $initial_terms['one_term']['term_id'],
'parent' => $initial_terms['one_term']['term_id'],
) );
// Verify that parent takes precedence over child_of
$expected = array(
$initial_terms['two_term']['term_id'],
$initial_terms['five_term']['term_id'],
);
$actual = wp_list_pluck( $terms, 'term_id' );
$this->assertEqualSets( $expected, $actual );
}
protected function create_hierarchical_terms_and_posts() {
$terms = array();
$terms['parent1'] = $this->factory->term->create( array( 'slug' => 'parent-1', 'name' => 'Parent 1', 'taxonomy' => 'hierarchical_fields' ) );
@ -836,4 +979,77 @@ class Tests_Term_getTerms extends WP_UnitTestCase {
return $terms;
}
protected function create_hierarchical_terms() {
// Set up the following hierarchy:
// - One
// - Two
// - Three (1)
// - Four
// - Five
// - Six (1)
// - Seven
$one_term = wp_insert_term(
'One',
'category'
);
$two_term = wp_insert_term(
'Two',
'category',
array(
'parent' => $one_term['term_id']
)
);
$three_term = wp_insert_term(
'Three',
'category',
array(
'parent' => $two_term['term_id']
)
);
$four_term = wp_insert_term(
'Four',
'category',
array(
'parent' => $two_term['term_id']
)
);
$five_term = wp_insert_term(
'Five',
'category',
array(
'parent' => $one_term['term_id']
)
);
$six_term = wp_insert_term(
'Six',
'category',
array(
'parent' => $five_term['term_id']
)
);
$seven_term = wp_insert_term(
'Seven',
'category',
array(
'parent' => $one_term['term_id']
)
);
// Ensure child terms are not empty
$first_post_id = $this->factory->post->create();
$second_post_id = $this->factory->post->create();
wp_set_post_terms( $first_post_id, array( $three_term['term_id'] ), 'category' );
wp_set_post_terms( $second_post_id, array( $six_term['term_id'] ), 'category' );
return array(
'one_term' => $one_term,
'two_term' => $two_term,
'three_term' => $three_term,
'four_term' => $four_term,
'five_term' => $five_term,
'six_term' => $six_term,
'seven_term' => $seven_term
);
}
}