mirror of
https://github.com/gosticks/wordpress-develop.git
synced 2026-04-01 19:24:34 +00:00
Introduce support for nested queries in WP_Meta_Query.
Previously, meta query arguments could be joined by a single AND or OR relation. Now, these queries can be arbitrarily nested, allowing clauses to be linked together with multiple relations. Adds unit tests for the new nesting syntax. Modifies a few existing unit tests that were overly specific for the old SQL syntax. Backward compatibility with existing syntax is fully maintained. Props boonebgorges, DrewAPicture. See #29642. git-svn-id: https://develop.svn.wordpress.org/trunk@29887 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
@@ -40,7 +40,7 @@ class Tests_Meta_Query extends WP_UnitTestCase {
|
||||
array(),
|
||||
) );
|
||||
|
||||
$this->assertSame( array( array() ), $query->queries );
|
||||
$this->assertSame( array(), $query->queries );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,19 +153,44 @@ class Tests_Meta_Query extends WP_UnitTestCase {
|
||||
$query = new WP_Meta_Query();
|
||||
|
||||
// just meta_value
|
||||
$query->parse_query_vars( array( 'meta_key' => 'abc' ) );
|
||||
|
||||
$this->assertEquals( array( array( 'key' => 'abc' ) ), $query->queries );
|
||||
$expected = array(
|
||||
'relation' => 'OR',
|
||||
array(
|
||||
'key' => 'abc',
|
||||
),
|
||||
);
|
||||
$query->parse_query_vars( array(
|
||||
'meta_key' => 'abc',
|
||||
) );
|
||||
$this->assertEquals( $expected, $query->queries );
|
||||
|
||||
// meta_key & meta_value
|
||||
$query->parse_query_vars( array( 'meta_key' => 'abc', 'meta_value' => 'def' ) );
|
||||
|
||||
$this->assertEquals( array( array( 'key' => 'abc', 'value' => 'def' ) ), $query->queries );
|
||||
$expected = array(
|
||||
'relation' => 'OR',
|
||||
array(
|
||||
'key' => 'abc',
|
||||
'value' => 'def',
|
||||
),
|
||||
);
|
||||
$query->parse_query_vars( array(
|
||||
'meta_key' => 'abc',
|
||||
'meta_value' => 'def',
|
||||
) );
|
||||
$this->assertEquals( $expected, $query->queries );
|
||||
|
||||
// meta_compare
|
||||
$query->parse_query_vars( array( 'meta_key' => 'abc', 'meta_compare' => '=>' ) );
|
||||
|
||||
$this->assertEquals( array( array( 'key' => 'abc', 'compare' => '=>' ) ), $query->queries );
|
||||
$expected = array(
|
||||
'relation' => 'OR',
|
||||
array(
|
||||
'key' => 'abc',
|
||||
'compare' => '=>',
|
||||
),
|
||||
);
|
||||
$query->parse_query_vars( array(
|
||||
'meta_key' => 'abc',
|
||||
'meta_compare' => '=>',
|
||||
) );
|
||||
$this->assertEquals( $expected, $query->queries );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -202,6 +227,229 @@ class Tests_Meta_Query extends WP_UnitTestCase {
|
||||
$this->assertEquals( 'CHAR', $query->get_cast_for_type( 'ANYTHING ELSE' ) );
|
||||
}
|
||||
|
||||
public function test_sanitize_query_single_query() {
|
||||
$expected = array(
|
||||
'relation' => 'OR',
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'value' => 'bar',
|
||||
),
|
||||
);
|
||||
|
||||
$q = new WP_Meta_Query();
|
||||
$found = $q->sanitize_query( array(
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'value' => 'bar',
|
||||
),
|
||||
) );
|
||||
|
||||
$this->assertEquals( $expected, $found );
|
||||
}
|
||||
|
||||
public function test_sanitize_query_multiple_first_order_queries_relation_default() {
|
||||
$expected = array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'value' => 'bar',
|
||||
),
|
||||
array(
|
||||
'key' => 'foo2',
|
||||
'value' => 'bar2',
|
||||
),
|
||||
);
|
||||
|
||||
$q = new WP_Meta_Query();
|
||||
$found = $q->sanitize_query( array(
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'value' => 'bar',
|
||||
),
|
||||
array(
|
||||
'key' => 'foo2',
|
||||
'value' => 'bar2',
|
||||
),
|
||||
) );
|
||||
|
||||
$this->assertEquals( $expected, $found );
|
||||
}
|
||||
|
||||
public function test_sanitize_query_multiple_first_order_queries_relation_or() {
|
||||
$expected = array(
|
||||
'relation' => 'OR',
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'value' => 'bar',
|
||||
),
|
||||
array(
|
||||
'key' => 'foo2',
|
||||
'value' => 'bar2',
|
||||
),
|
||||
);
|
||||
|
||||
$q = new WP_Meta_Query();
|
||||
$found = $q->sanitize_query( array(
|
||||
'relation' => 'OR',
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'value' => 'bar',
|
||||
),
|
||||
array(
|
||||
'key' => 'foo2',
|
||||
'value' => 'bar2',
|
||||
),
|
||||
) );
|
||||
|
||||
$this->assertEquals( $expected, $found );
|
||||
}
|
||||
|
||||
public function test_sanitize_query_multiple_first_order_queries_relation_or_lowercase() {
|
||||
$expected = array(
|
||||
'relation' => 'OR',
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'value' => 'bar',
|
||||
),
|
||||
array(
|
||||
'key' => 'foo2',
|
||||
'value' => 'bar2',
|
||||
),
|
||||
);
|
||||
|
||||
$q = new WP_Meta_Query();
|
||||
$found = $q->sanitize_query( array(
|
||||
'relation' => 'or',
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'value' => 'bar',
|
||||
),
|
||||
array(
|
||||
'key' => 'foo2',
|
||||
'value' => 'bar2',
|
||||
),
|
||||
) );
|
||||
|
||||
$this->assertEquals( $expected, $found );
|
||||
}
|
||||
|
||||
public function test_sanitize_query_multiple_first_order_queries_invalid_relation() {
|
||||
$expected = array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'value' => 'bar',
|
||||
),
|
||||
array(
|
||||
'key' => 'foo2',
|
||||
'value' => 'bar2',
|
||||
),
|
||||
);
|
||||
|
||||
$q = new WP_Meta_Query();
|
||||
$found = $q->sanitize_query( array(
|
||||
'relation' => 'FOO',
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'value' => 'bar',
|
||||
),
|
||||
array(
|
||||
'key' => 'foo2',
|
||||
'value' => 'bar2',
|
||||
),
|
||||
) );
|
||||
|
||||
$this->assertEquals( $expected, $found );
|
||||
}
|
||||
|
||||
public function test_sanitize_query_single_query_which_is_a_nested_query() {
|
||||
$expected = array(
|
||||
'relation' => 'OR',
|
||||
array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'value' => 'bar',
|
||||
),
|
||||
array(
|
||||
'key' => 'foo2',
|
||||
'value' => 'bar2',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$q = new WP_Meta_Query();
|
||||
$found = $q->sanitize_query( array(
|
||||
array(
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'value' => 'bar',
|
||||
),
|
||||
array(
|
||||
'key' => 'foo2',
|
||||
'value' => 'bar2',
|
||||
),
|
||||
),
|
||||
) );
|
||||
|
||||
$this->assertEquals( $expected, $found );
|
||||
}
|
||||
|
||||
public function test_sanitize_query_multiple_nested_queries() {
|
||||
$expected = array(
|
||||
'relation' => 'OR',
|
||||
array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'value' => 'bar',
|
||||
),
|
||||
array(
|
||||
'key' => 'foo2',
|
||||
'value' => 'bar2',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'key' => 'foo3',
|
||||
'value' => 'bar3',
|
||||
),
|
||||
array(
|
||||
'key' => 'foo4',
|
||||
'value' => 'bar4',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$q = new WP_Meta_Query();
|
||||
$found = $q->sanitize_query( array(
|
||||
'relation' => 'OR',
|
||||
array(
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'value' => 'bar',
|
||||
),
|
||||
array(
|
||||
'key' => 'foo2',
|
||||
'value' => 'bar2',
|
||||
),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'key' => 'foo3',
|
||||
'value' => 'bar3',
|
||||
),
|
||||
array(
|
||||
'key' => 'foo4',
|
||||
'value' => 'bar4',
|
||||
),
|
||||
),
|
||||
) );
|
||||
|
||||
$this->assertEquals( $expected, $found );
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalid $type will fail to get a table from _get_meta_table()
|
||||
*/
|
||||
@@ -229,7 +477,7 @@ class Tests_Meta_Query extends WP_UnitTestCase {
|
||||
$sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
|
||||
|
||||
// We should have 2 joins - one for my_first_key and one for my_second_key
|
||||
$this->assertEquals( 2, substr_count( $sql['join'], 'INNER JOIN' ) );
|
||||
$this->assertEquals( 2, substr_count( $sql['join'], 'JOIN' ) );
|
||||
|
||||
// The WHERE should check my_third_key against an unaliased table
|
||||
$this->assertEquals( 1, substr_count( $sql['where'], "$wpdb->postmeta.meta_key = 'my_third_key'" ) );
|
||||
@@ -247,7 +495,7 @@ class Tests_Meta_Query extends WP_UnitTestCase {
|
||||
) );
|
||||
$sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
|
||||
|
||||
$this->assertEquals( 1, substr_count( $sql['where'], "CAST($wpdb->postmeta.meta_value AS CHAR) = '')" ) );
|
||||
$this->assertEquals( 1, substr_count( $sql['where'], "CAST($wpdb->postmeta.meta_value AS CHAR) = ''" ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -558,7 +806,9 @@ class Tests_Meta_Query extends WP_UnitTestCase {
|
||||
) );
|
||||
|
||||
$sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
|
||||
$this->assertContains( "{$wpdb->postmeta}.meta_key = 'exclude'\nOR", $sql['where'] );
|
||||
|
||||
// Use regex because we don't care about the whitespace before OR.
|
||||
$this->assertRegExp( "/{$wpdb->postmeta}\.meta_key = \'exclude\'\s+OR/", $sql['where'] );
|
||||
$this->assertNotContains( "{$wpdb->postmeta}.post_id IS NULL", $sql['where'] );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -772,6 +772,100 @@ class Tests_Post_Query extends WP_UnitTestCase {
|
||||
$this->assertEqualSets( array( $post_4, $post_3, $post_2, $post_1 ), $query->posts );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 29642
|
||||
* @group meta
|
||||
*/
|
||||
public function test_meta_query_nested() {
|
||||
$p1 = $this->factory->post->create();
|
||||
$p2 = $this->factory->post->create();
|
||||
$p3 = $this->factory->post->create();
|
||||
|
||||
add_post_meta( $p1, 'foo', 'bar' );
|
||||
add_post_meta( $p2, 'foo2', 'bar' );
|
||||
add_post_meta( $p3, 'foo2', 'bar' );
|
||||
add_post_meta( $p3, 'foo3', 'bar' );
|
||||
|
||||
$query = new WP_Query( array(
|
||||
'update_post_meta_cache' => false,
|
||||
'update_term_meta_cache' => false,
|
||||
'fields' => 'ids',
|
||||
'meta_query' => array(
|
||||
'relation' => 'OR',
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'value' => 'bar',
|
||||
),
|
||||
array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'key' => 'foo2',
|
||||
'value' => 'bar',
|
||||
),
|
||||
array(
|
||||
'key' => 'foo3',
|
||||
'value' => 'bar',
|
||||
),
|
||||
),
|
||||
),
|
||||
) );
|
||||
|
||||
$expected = array( $p1, $p3 );
|
||||
$this->assertEqualSets( $expected, $query->posts );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 29642
|
||||
* @group meta
|
||||
*/
|
||||
public function test_meta_query_nested_two_levels_deep() {
|
||||
$p1 = $this->factory->post->create();
|
||||
$p2 = $this->factory->post->create();
|
||||
$p3 = $this->factory->post->create();
|
||||
|
||||
add_post_meta( $p1, 'foo', 'bar' );
|
||||
add_post_meta( $p3, 'foo2', 'bar' );
|
||||
add_post_meta( $p3, 'foo3', 'bar' );
|
||||
add_post_meta( $p3, 'foo4', 'bar' );
|
||||
|
||||
$query = new WP_Query( array(
|
||||
'update_post_meta_cache' => false,
|
||||
'update_term_meta_cache' => false,
|
||||
'fields' => 'ids',
|
||||
'meta_query' => array(
|
||||
'relation' => 'OR',
|
||||
array(
|
||||
'key' => 'foo',
|
||||
'value' => 'bar',
|
||||
),
|
||||
array(
|
||||
'relation' => 'OR',
|
||||
array(
|
||||
'key' => 'foo2',
|
||||
'value' => 'bar',
|
||||
),
|
||||
array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'key' => 'foo3',
|
||||
'value' => 'bar',
|
||||
),
|
||||
array(
|
||||
'key' => 'foo4',
|
||||
'value' => 'bar',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
) );
|
||||
|
||||
$expected = array( $p1, $p3 );
|
||||
$this->assertEqualSets( $expected, $query->posts );
|
||||
}
|
||||
|
||||
/**
|
||||
* @group meta
|
||||
*/
|
||||
function test_meta_between_not_between() {
|
||||
$post_id = $this->factory->post->create();
|
||||
add_post_meta( $post_id, 'time', 500 );
|
||||
@@ -819,6 +913,7 @@ class Tests_Post_Query extends WP_UnitTestCase {
|
||||
|
||||
/**
|
||||
* @ticket 16829
|
||||
* @group meta
|
||||
*/
|
||||
function test_meta_default_compare() {
|
||||
// compare should default to IN when meta_value is an array
|
||||
@@ -859,6 +954,7 @@ class Tests_Post_Query extends WP_UnitTestCase {
|
||||
|
||||
/**
|
||||
* @ticket 17264
|
||||
* @group meta
|
||||
*/
|
||||
function test_duplicate_posts_when_no_key() {
|
||||
$post_id = $this->factory->post->create();
|
||||
@@ -890,6 +986,7 @@ class Tests_Post_Query extends WP_UnitTestCase {
|
||||
|
||||
/**
|
||||
* @ticket 15292
|
||||
* @group meta
|
||||
*/
|
||||
function test_empty_meta_value() {
|
||||
$post_id = $this->factory->post->create();
|
||||
|
||||
Reference in New Issue
Block a user