WordPress.org

Make WordPress Core

Changeset 29896


Ignore:
Timestamp:
10/15/2014 12:53:22 AM (5 years ago)
Author:
boonebgorges
Message:

Support 'EXISTS' and 'NOT EXISTS' in WP_Tax_Query.

These new values for the 'operator' parameter make it possible to filter items
that have no term from a given taxonomy, or any term from a given taxonomy.

Includes unit tests.

Fixes #29181.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/taxonomy.php

    r29891 r29896  
    692692     *
    693693     * @since 3.1.0
     694     * @since 4.1.0 Added support for $operator 'NOT EXISTS' and 'EXISTS'.
    694695     * @access public
    695696     *
    696697     * @param array $tax_query {
    697      *     Array of taxonoy query clauses.
     698     *     Array of taxonomy query clauses.
    698699     *
    699700     *     @type string $relation Optional. The MySQL keyword used to join
     
    707708     *                                                 'name', or 'term_taxonomy_id'. Default: 'term_id'.
    708709     *         @type string           $operator         MySQL operator to be used with $terms in the WHERE clause.
    709      *                                                  Accepts 'AND', 'IN', or 'OR. Default: 'IN'.
     710     *                                                  Accepts 'AND', 'IN', 'NOT IN', 'EXISTS', 'NOT EXISTS'.
     711     *                                                  Default: 'IN'.
    710712     *         @type bool             $include_children Optional. Whether to include child terms.
    711713     *                                                  Requires a $taxonomy. Default: true.
     
    10271029                AND object_id = $this->primary_table.$this->primary_id_column
    10281030            ) = $num_terms";
     1031
     1032        } elseif ( 'NOT EXISTS' === $operator || 'EXISTS' === $operator ) {
     1033
     1034            $where = $wpdb->prepare( "$operator (
     1035                SELECT 1
     1036                FROM $wpdb->term_relationships
     1037                INNER JOIN $wpdb->term_taxonomy
     1038                ON $wpdb->term_taxonomy.term_taxonomy_id = $wpdb->term_relationships.term_taxonomy_id
     1039                WHERE $wpdb->term_taxonomy.taxonomy = %s
     1040                AND $wpdb->term_relationships.object_id = $this->primary_table.$this->primary_id_column
     1041            )", $clause['taxonomy'] );
     1042
    10291043        }
    10301044
  • trunk/tests/phpunit/tests/post/query.php

    r29891 r29896  
    14141414
    14151415    /**
     1416     * @ticket 29181
     1417     */
     1418    public function test_tax_query_operator_not_exists() {
     1419        register_taxonomy( 'wptests_tax1', 'post' );
     1420        register_taxonomy( 'wptests_tax2', 'post' );
     1421
     1422        $t1 = $this->factory->term->create( array( 'taxonomy' => 'wptests_tax1' ) );
     1423        $t2 = $this->factory->term->create( array( 'taxonomy' => 'wptests_tax2' ) );
     1424
     1425        $p1 = $this->factory->post->create();
     1426        $p2 = $this->factory->post->create();
     1427        $p3 = $this->factory->post->create();
     1428
     1429        wp_set_object_terms( $p1, array( $t1 ), 'wptests_tax1' );
     1430        wp_set_object_terms( $p2, array( $t2 ), 'wptests_tax2' );
     1431
     1432        $q = new WP_Query( array(
     1433            'fields' => 'ids',
     1434            'orderby' => 'ID',
     1435            'order' => 'ASC',
     1436            'tax_query' => array(
     1437                array(
     1438                    'taxonomy' => 'wptests_tax2',
     1439                    'operator' => 'NOT EXISTS',
     1440                ),
     1441            ),
     1442        ) );
     1443
     1444        $this->assertEqualSets( array( $p1, $p3 ), $q->posts );
     1445    }
     1446
     1447    /**
     1448     * @ticket 29181
     1449     */
     1450    public function test_tax_query_operator_exists() {
     1451        register_taxonomy( 'wptests_tax1', 'post' );
     1452        register_taxonomy( 'wptests_tax2', 'post' );
     1453
     1454        $t1 = $this->factory->term->create( array( 'taxonomy' => 'wptests_tax1' ) );
     1455        $t2 = $this->factory->term->create( array( 'taxonomy' => 'wptests_tax2' ) );
     1456
     1457        $p1 = $this->factory->post->create();
     1458        $p2 = $this->factory->post->create();
     1459        $p3 = $this->factory->post->create();
     1460
     1461        wp_set_object_terms( $p1, array( $t1 ), 'wptests_tax1' );
     1462        wp_set_object_terms( $p2, array( $t2 ), 'wptests_tax2' );
     1463
     1464        $q = new WP_Query( array(
     1465            'fields' => 'ids',
     1466            'orderby' => 'ID',
     1467            'order' => 'ASC',
     1468            'tax_query' => array(
     1469                array(
     1470                    'taxonomy' => 'wptests_tax2',
     1471                    'operator' => 'EXISTS',
     1472                ),
     1473            ),
     1474        ) );
     1475
     1476        $this->assertEqualSets( array( $p2 ), $q->posts );
     1477    }
     1478
     1479    /**
     1480     * @ticket 29181
     1481     */
     1482    public function test_tax_query_operator_exists_should_ignore_terms() {
     1483        register_taxonomy( 'wptests_tax1', 'post' );
     1484        register_taxonomy( 'wptests_tax2', 'post' );
     1485
     1486        $t1 = $this->factory->term->create( array( 'taxonomy' => 'wptests_tax1' ) );
     1487        $t2 = $this->factory->term->create( array( 'taxonomy' => 'wptests_tax2' ) );
     1488
     1489        $p1 = $this->factory->post->create();
     1490        $p2 = $this->factory->post->create();
     1491        $p3 = $this->factory->post->create();
     1492
     1493        wp_set_object_terms( $p1, array( $t1 ), 'wptests_tax1' );
     1494        wp_set_object_terms( $p2, array( $t2 ), 'wptests_tax2' );
     1495
     1496        $q = new WP_Query( array(
     1497            'fields' => 'ids',
     1498            'orderby' => 'ID',
     1499            'order' => 'ASC',
     1500            'tax_query' => array(
     1501                array(
     1502                    'taxonomy' => 'wptests_tax2',
     1503                    'operator' => 'EXISTS',
     1504                    'terms' => array( 'foo', 'bar' ),
     1505                ),
     1506            ),
     1507        ) );
     1508
     1509        $this->assertEqualSets( array( $p2 ), $q->posts );
     1510    }
     1511
     1512    /**
     1513     * @ticket 29181
     1514     */
     1515    public function test_tax_query_operator_exists_with_no_taxonomy() {
     1516        register_taxonomy( 'wptests_tax1', 'post' );
     1517        register_taxonomy( 'wptests_tax2', 'post' );
     1518
     1519        $t1 = $this->factory->term->create( array( 'taxonomy' => 'wptests_tax1' ) );
     1520        $t2 = $this->factory->term->create( array( 'taxonomy' => 'wptests_tax2' ) );
     1521
     1522        $p1 = $this->factory->post->create();
     1523        $p2 = $this->factory->post->create();
     1524        $p3 = $this->factory->post->create();
     1525
     1526        wp_set_object_terms( $p1, array( $t1 ), 'wptests_tax1' );
     1527        wp_set_object_terms( $p2, array( $t2 ), 'wptests_tax2' );
     1528
     1529        $q = new WP_Query( array(
     1530            'fields' => 'ids',
     1531            'orderby' => 'ID',
     1532            'order' => 'ASC',
     1533            'tax_query' => array(
     1534                array(
     1535                    'operator' => 'EXISTS',
     1536                ),
     1537            ),
     1538        ) );
     1539
     1540        $this->assertEmpty( $q->posts );
     1541    }
     1542
     1543    /**
    14161544     * @group taxonomy
    14171545     */
Note: See TracChangeset for help on using the changeset viewer.