Make WordPress Core

Opened 2 years ago

Closed 2 years ago

Last modified 2 years ago

#56370 closed defect (bug) (wontfix)

Taxonomy parameter in a WP_Query not merged correctly with already existing taxonomy query with OR relation.

Reported by: hugod's profile hugod Owned by:
Milestone: Priority: normal
Severity: normal Version: 6.1
Component: Query Keywords: has-unit-tests
Focuses: Cc:

Description

When creating a WP_Query with a taxonomy slug in parameter and a taxonomy query with the OR relation, all queried terms are merge under the OR relation.
Here is an example, given this query:

<?php
$q = new WP_Query(
        array(
                'fields'                 => 'ids',
                'update_post_meta_cache' => false,
                'update_post_term_cache' => false,
                'foo'                    => 'foo-term',
                'tax_query'              => array(
                        'relation' => 'OR',
                        array(
                                'taxonomy' => 'category',
                                'terms'    => array( $cat_term_1 ),
                                'field'    => 'term_id',
                        ),
                        array(
                                'taxonomy' => 'category',
                                'terms'    => array( $cat_term_2 ),
                                'field'    => 'term_id',
                        ),
                ),
        )
);

WP_Query::parse_tax_query() transforms WP_Query->tax_query->queries into:

<?php
$resulting_query = array(
                'relation' => 'OR',
                array(
                        'taxonomy'         => 'category',
                        'terms'            => array( $cat_term_1 ),
                        'field'            => 'term_id',
                        'operator'         => 'IN',
                        'include_children' => true,
                ),
                array(
                        'taxonomy'         => 'category',
                        'terms'            => array( $cat_term_2 ),
                        'field'            => 'term_id',
                        'operator'         => 'IN',
                        'include_children' => true,
                ),
                array(
                        'taxonomy'         => 'foo',
                        'terms'            => array(
                                'foo-term',
                        ),
                        'field'            => 'slug',
                        'operator'         => 'IN',
                        'include_children' => true,
        ),
);

Although I expect it to be:

<?php
$expected = array(
        'relation' => 'AND',
        array(
                'taxonomy'         => 'foo',
                'terms'            => 'foo-term',
                'field'            => 'slug',
                'operator'         => 'IN',
                'include_children' => true,
        ),
        array(
        'relation' => 'OR',
                array(
                        'taxonomy'         => 'category',
                        'terms'            => array( $cat_term_1 ),
                        'field'            => 'term_id',
                        'operator'         => 'IN',
                        'include_children' => true,
                ),
                array(
                        'taxonomy'         => 'category',
                        'terms'            => array( $cat_term_2 ),
                        'field'            => 'term_id',
                        'operator'         => 'IN',
                        'include_children' => true,
                ),
                array(
                        'taxonomy'         => 'foo',
                        'terms'            => array(
                                'foo-term',
                        ),
                        'field'            => 'slug',
                        'operator'         => 'IN',
                        'include_children' => true,
                ),
        ),
);

Indeed, the relation AND is the default one. See https://github.com/WordPress/wordpress-develop/blob/6.0/src/wp-includes/class-wp-tax-query.php#L97-L98.
WordPress merges all queried terms here https://github.com/WordPress/wordpress-develop/blob/6.0.1/src/wp-includes/class-wp-query.php#L1163-L1168 without looking at the relations.
I am aware that querying with the taxonomy slug as parameter in WP_Query is deprecated, but the same issue occurs with category for instance with a query like this:

<?php
$q = new WP_Query(
        array(
                'post_type' => 'post',
                'cat' => 5,
                'posts_per_page' => 10,
                'tax_query' => array(
                        'relation' => 'OR',
                        array(
                                'taxonomy' => 'custom_tax',
                                'field' => 'slug',
                                'terms' => array( 'test-tax' )
                        ),
                        array(
                                'taxonomy' => 'custom_tax',
                                'field' => 'slug',
                                'terms' => array( 'test-tax-2' )
                        )
                )
        )
);

But for category, WordPress merges terms here https://github.com/WordPress/wordpress-develop/blob/6.0.1/src/wp-includes/class-wp-query.php#L1196-L1203.

Change History (6)

This ticket was mentioned in PR #3086 on WordPress/wordpress-develop by Hug0-Drelon.


2 years ago
#1

  • Keywords has-patch has-unit-tests added

Trac ticket: https://core.trac.wordpress.org/ticket/56370

Just adds a test to confirm the bug mentioned in the ticket.

#2 @hugod
2 years ago

I created a PR to add a unit test showing the bug.

#3 @hugod
2 years ago

  • Keywords has-patch removed

#4 @peterwilsoncc
2 years ago

Thanks for the ticket @hugod

I think this is a case in which it is very difficult to interpret the developer's intent.

I can see your argument but I can also see why another developer may think that having specified OR, it ought to apply to all taxonomy types, no matter how they are entered.

I think the best way to fix this is to recommend developers use either cat* and tag* OR tax_query.

#5 @hugod
2 years ago

  • Resolution set to invalid
  • Status changed from new to closed

Thanks for the answer @peterwilsoncc !
I understand your point.

#6 @peterwilsoncc
2 years ago

  • Milestone Awaiting Review deleted
  • Resolution changed from invalid to wontfix

Thanks for the understanding @hugod. I've changed the resolution from invalid to wontfix as I think it was a legitimate edge case to ask about.

Note: See TracTickets for help on using tickets.