Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Instead of interpreting $args['tax_query'] use WP_Query->tax_query #2419

Merged
merged 8 commits into from
Mar 1, 2022
112 changes: 2 additions & 110 deletions includes/classes/Indexable/Post/Post.php
Original file line number Diff line number Diff line change
Expand Up @@ -976,116 +976,8 @@ public function format_args( $args, $wp_query ) {
* terms array
* @since 0.9.1
*/

// Find root level taxonomies.
if ( empty( $args['tax_query'] ) ) {
if ( isset( $args['category_name'] ) && ! empty( $args['category_name'] ) ) {
$args['tax_query'][] = array(
'taxonomy' => 'category',
'terms' => array( $args['category_name'] ),
'field' => 'slug',
);
}

if ( isset( $args['cat'] ) && ! empty( $args['cat'] ) ) {
$args['tax_query'][] = array(
'taxonomy' => 'category',
'terms' => array( $args['cat'] ),
'field' => 'term_id',
);
}
}

if ( isset( $args['tag'] ) && ! empty( $args['tag'] ) ) {
if ( ! is_array( $args['tag'] ) && false !== strpos( $args['tag'], ',' ) ) {
$args['tag'] = explode( ',', $args['tag'] );
}
$args['tax_query'][] = array(
'taxonomy' => 'post_tag',
'terms' => (array) $args['tag'],
'field' => 'slug',
);
}

if ( isset( $args['post_tag'] ) && ! empty( $args['post_tag'] ) ) {
$args['tax_query'][] = array(
'taxonomy' => 'post_tag',
'terms' => array( $args['post_tag'] ),
'field' => 'slug',
);
}

$has_tag__and = false;

if ( isset( $args['tag__and'] ) && ! empty( $args['tag__and'] ) ) {
$args['tax_query'][] = array(
'taxonomy' => 'post_tag',
'terms' => $args['tag__and'],
'field' => 'term_id',
);

$has_tag__and = true;
}

if ( isset( $args['tag_id'] ) && ! empty( $args['tag_id'] ) && ! is_array( $args['tag_id'] ) ) {

// If you pass tag__in as a parameter, core adds the first
// term ID as tag_id, so we only need to append it if we have
// already added term IDs.
if ( $has_tag__and ) {

$args['tax_query'] = array_map(
function( $tax_query ) use ( $args ) {
if ( isset( $tax_query['taxonomy'] ) && 'post_tag' === $tax_query['taxonomy'] && ! in_array( $args['tag_id'], $tax_query['terms'], true ) ) {
$tax_query['terms'][] = $args['tag_id'];
}

return $tax_query;
},
$args['tax_query']
);
} elseif ( empty( $args['tax_query'] ) ) {
$args['tax_query'][] = array(
'taxonomy' => 'post_tag',
'terms' => $args['tag_id'],
'field' => 'term_id',
);
}
}

/**
* Try to find other taxonomies set in the root of WP_Query
*
* @since 3.4
* @since 3.4.2 Test taxonomies with their query_var value.
*/
$taxonomies = get_taxonomies( array(), 'objects' );

/**
* Filter taxonomies to exclude from tax root check.
* Default values prevent duplication of core's default taxonomies post_tag and category in ES query.
*
* @since 3.6.3
* @hook ep_post_tax_excluded_wp_query_root_check
* @param {array} $taxonomies Taxonomies
*/
$excluded_tax_from_root_check = apply_filters(
'ep_post_tax_excluded_wp_query_root_check',
[
'category',
'post_tag',
]
);

foreach ( $taxonomies as $tax_slug => $tax ) {

if ( $tax->query_var && ! empty( $args[ $tax->query_var ] ) && ! in_array( $tax->name, $excluded_tax_from_root_check, true ) ) {
$args['tax_query'][] = array(
'taxonomy' => $tax_slug,
'terms' => (array) $args[ $tax->query_var ],
'field' => 'slug',
);
}
if ( ! empty( $wp_query->tax_query ) && ! empty( $wp_query->tax_query->queries ) ) {
$args['tax_query'] = $wp_query->tax_query->queries;
}

if ( ! empty( $args['tax_query'] ) ) {
Expand Down
7 changes: 6 additions & 1 deletion tests/php/features/TestProtectedContent.php
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,12 @@ public function testAdminCategories() {
$wp_the_query = $query;

$args = array(
'category_name' => 'category one',
/**
* Despite its name, per WP docs `category_name` actually uses the cat slug.
*
* @see https://developer.wordpress.org/reference/classes/wp_query/#category-parameters
*/
'category_name' => 'category-one',
);

$query->query( $args );
Expand Down
194 changes: 124 additions & 70 deletions tests/php/indexables/TestPost.php
Original file line number Diff line number Diff line change
Expand Up @@ -5196,62 +5196,86 @@ public function testTagSlugQuery() {
* @group post
*/
public function testTagQuery() {
$tag1 = wp_insert_category( [ 'cat_name' => 'tag-1', 'taxonomy' => 'post_tag' ] );
$tag2 = wp_insert_category( [ 'cat_name' => 'tag-2', 'taxonomy' => 'post_tag' ] );
$tag3 = wp_insert_category( [ 'cat_name' => 'tag-3', 'taxonomy' => 'post_tag' ] );
$tag4 = wp_insert_category( [ 'cat_name' => 'tag-4', 'taxonomy' => 'post_tag' ] );
$tag5 = wp_insert_category( [ 'cat_name' => 'tag-5', 'taxonomy' => 'post_tag' ] );
$tag6 = wp_insert_category( [ 'cat_name' => 'tag-6', 'taxonomy' => 'post_tag' ] );

$post_id_1 = Functions\create_and_sync_post(
array(
'post_content' => 'findme test 1',
'tags_input' => array( 'one', 'two' ),
'tags_input' => array( $tag1, $tag2 ),
)
);
$post_id_2 = Functions\create_and_sync_post(
array(
'post_content' => 'findme test 2',
'tags_input' => array( 'three', 'four', 'five', 'six' ),
'tags_input' => array( $tag3, $tag4, $tag5, $tag6 ),
)
);

$post_id_3 = Functions\create_and_sync_post(
array(
'post_content' => 'findme test 3',
'tags_input' => array( 'one', 'six' ),
'tags_input' => array( $tag1, $tag2, $tag6 ),
)
);

$post_1_tags = get_the_tags( $post_id_1 );
$post_2_tags = get_the_tags( $post_id_2 );
$post_3_tags = get_the_tags( $post_id_3 );
/*
* | 1 | 2 | 3 | 4 | 5 | 6 |
* post 1 | x | x | | | | |
* post 2 | | | x | x | x | x |
* post 3 | x | x | | | | x |
*/

ElasticPress\Elasticsearch::factory()->refresh_indices();

// Should find only posts with both tags 1 AND 2
$args = array(
's' => 'findme',
'post_type' => 'post',
'tag__and' => array( $post_1_tags[1]->term_id, $post_2_tags[1]->term_id ),
'tag__and' => array( $tag1, $tag2 ),
'fields' => 'ids',
);

$query = new \WP_Query( $args );

$this->assertTrue( $query->elasticsearch_success );
$this->assertEquals( 2, $query->post_count );
$this->assertEquals( 2, $query->found_posts );
$this->assertEqualsCanonicalizing( [ $post_id_1, $post_id_3 ], $query->posts );

// Should find only posts with tag 3
$args = array(
's' => 'findme',
'post_type' => 'post',
'tag_id' => $tag3,
'fields' => 'ids',
);

// Verify we're only getting the posts we requested.
$post_names = wp_list_pluck( $query->posts, 'post_name' );
$query = new \WP_Query( $args );

$this->assertContains( get_post_field( 'post_name', $post_id_1 ), $post_names );
$this->assertContains( get_post_field( 'post_name', $post_id_2 ), $post_names );
$this->assertNotContains( get_post_field( 'post_name', $post_id_3 ), $post_names );
$this->assertTrue( $query->elasticsearch_success );
$this->assertEquals( 1, $query->post_count );
$this->assertEquals( 1, $query->found_posts );
$this->assertEqualsCanonicalizing( [ $post_id_2 ], $query->posts );

// Should find only posts with tags 1 OR 3
$args = array(
's' => 'findme',
'post_type' => 'post',
'tag_id' => $post_3_tags[1]->term_id,
'tag__in' => array( $tag1, $tag3 ),
'fields' => 'ids',
);

$query = new \WP_Query( $args );

$this->assertTrue( $query->elasticsearch_success );
$this->assertEquals( 2, $query->post_count );
$this->assertEquals( 2, $query->found_posts );
$this->assertEquals( 3, $query->post_count );
$this->assertEquals( 3, $query->found_posts );
$this->assertEqualsCanonicalizing( [ $post_id_1, $post_id_2, $post_id_3 ], $query->posts );
}

/**
Expand Down Expand Up @@ -5493,69 +5517,99 @@ public function testPrepareDocumentFallbacks() {
* @group post
*/
public function testFormatArgsRootLevelTaxonomies() {
$cat1 = wp_create_category( 'category one' );
$cat2 = wp_create_category( 'category two' );
$tag1 = wp_insert_category( [ 'cat_name' => 'tag-1', 'taxonomy' => 'post_tag' ] );
$tag2 = wp_insert_category( [ 'cat_name' => 'tag-2', 'taxonomy' => 'post_tag' ] );
$tag3 = wp_insert_category( [ 'cat_name' => 'tag-3', 'taxonomy' => 'post_tag' ] );

$post = new \ElasticPress\Indexable\Post\Post();

$query = new \WP_Query();
$posts_per_page = (int) get_option( 'posts_per_page' );
$post1 = Functions\create_and_sync_post(
array(
'tags_input' => array( $tag1, $tag2 ),
'post_category' => array( $cat1 ),
)
);
$post2 = Functions\create_and_sync_post(
array(
'tags_input' => array( $tag1, $tag2, $tag3 ),
'post_category' => array( $cat2 ),
)
);
$post3 = Functions\create_and_sync_post(
array(
'post_category' => array( $cat1 ),
)
);
$post4 = Functions\create_and_sync_post(
array(
'tags_input' => array( $tag1, $tag3 ),
)
);

$args = $post->format_args(
ElasticPress\Elasticsearch::factory()->refresh_indices();

$query = new \WP_Query(
[
'cat' => 123,
'tag' => 'tag-slug',
'post_tag' => 'post-tag-slug',
],
$query
'ep_integrate' => true,
'cat' => $cat1,
'tag' => 'tag-1',
'fields' => 'ids',
]
);

$this->assertSame( $posts_per_page, $args['size'] );

$this->assertTrue( is_array( $args['post_filter']['bool']['must'][0]['bool']['must'] ) );

$must_terms = $args['post_filter']['bool']['must'][0]['bool']['must'];

$this->assertSame( 123, $must_terms[0]['terms']['terms.category.term_id'][0] );
$this->assertSame( 'tag-slug', $must_terms[1]['terms']['terms.post_tag.slug'][0] );
$this->assertSame( 'post-tag-slug', $must_terms[2]['terms']['terms.post_tag.slug'][0] );

// Verify a bug fix where two different terms.post_tag.term_id
// parameters were being created. Should only be one parameter
// with the two IDs.
$args = $post->format_args(
$this->assertTrue( $query->elasticsearch_success );
$this->assertEqualsCanonicalizing( [ $post1 ], $query->posts );
$this->assertEquals( 1, $query->post_count );
$this->assertEquals( 1, $query->found_posts );

$query = new \WP_Query(
[
'tag__and' => [ 123, 456 ],
'tag_id' => 123,
],
$query
'ep_integrate' => true,
'tag__and' => [ $tag1, $tag2 ],
'tag_id' => $tag1,
'fields' => 'ids',
]
);

$this->assertTrue( is_array( $args['post_filter']['bool']['must'][0]['bool']['must'] ) );

$must_terms = $args['post_filter']['bool']['must'][0]['bool']['must'];

$this->assertCount( 1, $must_terms );
$this->assertCount( 2, $must_terms[0]['terms']['terms.post_tag.term_id'] );
$this->assertContains( 123, $must_terms[0]['terms']['terms.post_tag.term_id'] );
$this->assertContains( 456, $must_terms[0]['terms']['terms.post_tag.term_id'] );

// Verify we're append the tag_id to the array.
$args = $post->format_args(
$this->assertTrue( $query->elasticsearch_success );
$this->assertEqualsCanonicalizing( [ $post1, $post2 ], $query->posts );
$this->assertEquals( 2, $query->post_count );
$this->assertEquals( 2, $query->found_posts );

$query = new \WP_Query(
[
'tag__and' => [ 123, 456 ],
'tag_id' => 789,
],
$query
'ep_integrate' => true,
'tag__and' => [ $tag1, $tag2 ],
'tag_id' => $tag3,
'fields' => 'ids',
]
);

$this->assertTrue( is_array( $args['post_filter']['bool']['must'][0]['bool']['must'] ) );

$must_terms = $args['post_filter']['bool']['must'][0]['bool']['must'];

$this->assertCount( 1, $must_terms );
$this->assertCount( 3, $must_terms[0]['terms']['terms.post_tag.term_id'] );
$this->assertContains( 123, $must_terms[0]['terms']['terms.post_tag.term_id'] );
$this->assertContains( 456, $must_terms[0]['terms']['terms.post_tag.term_id'] );
$this->assertContains( 789, $must_terms[0]['terms']['terms.post_tag.term_id'] );
$this->assertTrue( $query->elasticsearch_success );
$this->assertEqualsCanonicalizing( [ $post2 ], $query->posts );
$this->assertEquals( 1, $query->post_count );
$this->assertEquals( 1, $query->found_posts );

$query = new \WP_Query(
[
'ep_integrate' => true,
'tag__in' => [ $tag1, $tag2, $tag3 ],
'fields' => 'ids',
]
);
$this->assertTrue( $query->elasticsearch_success );
$this->assertEqualsCanonicalizing( [ $post1, $post2, $post4 ], $query->posts );
$this->assertEquals( 3, $query->post_count );
$this->assertEquals( 3, $query->found_posts );

$query = new \WP_Query(
[
'ep_integrate' => true,
'category__in' => [ $cat1, $cat2 ],
'fields' => 'ids',
]
);
$this->assertTrue( $query->elasticsearch_success );
$this->assertEqualsCanonicalizing( [ $post1, $post2, $post3 ], $query->posts );
$this->assertEquals( 3, $query->post_count );
$this->assertEquals( 3, $query->found_posts );
}

/**
Expand Down