WordPress.org

Make WordPress Core

Opened 3 years ago

Last modified 10 months ago

#39140 new defect (bug)

Taxonomies - operator AND doesn't work properly for taxonomy hierarchies

Reported by: bredefladen Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 4.6.1
Component: Query Keywords: needs-refresh has-unit-tests needs-patch
Focuses: Cc:
PR Number:

Description

Hi,

This is a problem discovered using WooCommerce shortcodes but has its core problem in the WP core according to my findings. I've already implemented a fix for this in a customer project.

I’ve ran into problems using one of the Woo shortcodes and operator ‘AND’. This is questioned by others several times before (see links below) but it seems like the core of the problem is not solved. I’ve worked with the issue on WP 4.6.1 installation and come to what I believe is a solution (changes in file class-wp-tax-query.php).

Even if the issue is found using Woo product categories I believe this is an issue for taxonomies in general.

Problem:
Using shortcode to retrieve a filtered product list and filtering on two or more product categories using operator “AND” fails when using one or more non-leaf (i.e. parent) product categories. There even seemed to be additional problems when using more than two leaf keywords. In general the "AND" didn't behave as expected.

Other reports on the issue:
https://wordpress.org/support/topic/operator-and-on-product_category/
https://wordpress.org/support/topic/woocommerce-display-products-from-two-categories-combined/
https://wordpress.org/support/topic/woocommerce-product_category-and-operator-returns-no-results/

Examples using Woo shortcodes:

Taxonomies (product categories) for Product1: LeafCatA, LeafCatB

[product_category category=”ParentCatA, LeafCatB” operator=”AND”] => Fails - shows nothing. Should show Product1

[product_category category=”LeafCatA, LeafCatB” operator=”AND”] => Ok - shows Product1

Reason:
There is no individual and complete hierarchial evaluation of each taxonomy/category keyword specified in the shortcode.

Solution that worked for me:
The issue is found in the WP-core file class-wp-tax-query.php. I’ve modified three functions to correct the issue. This includes changes to the SQL-statements generated.

Changes to file class-wp-tax-query.php:
class WP_Tax_Query

  • function get_sql_for_clause – code
  • function clean_query – input params and code
  • function transform_query – input params and code

You find my modified and running code/functions with my comments here (tagged with BF): https://gist.github.com/Nettsidespesialisten/5d4596e18dced3c7d97501f195ffe02e

This is my first ticket here so please notify me how to contribute the best way with this issue (providing code into SVN or other).

Kind regards

Brede

Attachments (2)

39140.patch (3.3 KB) - added by Toro_Unit 10 months ago.
Unit Test.
39140.2.patch (2.3 KB) - added by Toro_Unit 10 months ago.
Unit Test. (Fixed)

Download all attachments as: .zip

Change History (6)

#1 @bredefladen
3 years ago

  • Keywords has-patch added

#2 @sumon380
20 months ago

Hi, facing same problem. Is there any solution without touching core woocommerce functions?

#3 @Toro_Unit
10 months ago

  • Keywords needs-refresh has-unit-tests added

I have same problem. in WP 5.0.

Posts with parent cateogory not Selected.

bredefladen's change is Pass the following tests. But failed some other test. So need update patch.

<?php
        public function test_tax_query_single_query_multiple_hierarchical_terms_operator_and() {
                $europe = self::factory()->term->create(
                        array(
                                'taxonomy' => 'category',
                                'name'     => 'Europe',
                        )
                );
                $spain = self::factory()->term->create(
                        array(
                                'taxonomy' => 'category',
                                'name'     => 'Spain',
                                'parent'   => $europe,
                        )
                );
                $south_america = self::factory()->term->create(
                        array(
                                'taxonomy' => 'category',
                                'name'     => 'South America',
                        )
                );
                $argentina = self::factory()->term->create(
                        array(
                                'taxonomy' => 'category',
                                'name'     => 'Argentina',
                                'parent'   => $south_america,
                        )
                );
                $post_a = self::factory()->post->create( array( 'post_category' => array( $argentina ) ) );
                $post_b = self::factory()->post->create( array( 'post_category' => array( $spain ) ) );
                $post_c = self::factory()->post->create( array( 'post_category' => array( $argentina, $spain ) ) );
                $post_d = self::factory()->post->create( array( 'post_category' => array( $europe, $south_america ) ) );

                $posts = get_posts(
                        array(
                                'fields'                 => 'ids',
                                'update_post_meta_cache' => false,
                                'update_post_term_cache' => false,
                                'tax_query'              => array(
                                        array(
                                                'taxonomy' => 'category',
                                                'field'    => 'id',
                                                'terms'    => array( $argentina, $spain ),
                                                'operator' => 'AND'
                                        ),
                                ),
                        )
                );

                $this->assertEquals( 1, count( $posts ) );

                $posts = get_posts(
                        array(
                                'fields'                 => 'ids',
                                'update_post_meta_cache' => false,
                                'update_post_term_cache' => false,
                                'tax_query'              => array(
                                        array(
                                                'taxonomy' => 'category',
                                                'field'    => 'id',
                                                'terms'    => array( $europe, $south_america ),
                                                'operator' => 'AND'
                                        ),
                                ),
                        )
                );
                // failed !!! Actual: 0
                $this->assertEquals( 2, count( $posts ) );

        }
Last edited 10 months ago by Toro_Unit (previous) (diff)

@Toro_Unit
10 months ago

Unit Test.

@Toro_Unit
10 months ago

Unit Test. (Fixed)

#4 @Toro_Unit
10 months ago

  • Keywords needs-patch added; has-patch removed
Note: See TracTickets for help on using tickets.