diff --git a/src/wp-includes/meta.php b/src/wp-includes/meta.php index e1d0652214..e9f7811c31 100644 --- a/src/wp-includes/meta.php +++ b/src/wp-includes/meta.php @@ -1057,18 +1057,38 @@ class WP_Meta_Query { public function parse_query_vars( $qv ) { $meta_query = array(); - // Simple query needs to be first for orderby=meta_value to work correctly. + /* + * For orderby=meta_value to work correctly, simple query needs to be + * first (so that its table join is against an unaliased meta table) and + * needs to be its own clause (so it doesn't interfere with the logic of + * the rest of the meta_query). + */ + $primary_meta_query = array(); foreach ( array( 'key', 'compare', 'type' ) as $key ) { - if ( !empty( $qv[ "meta_$key" ] ) ) - $meta_query[0][ $key ] = $qv[ "meta_$key" ]; + if ( ! empty( $qv[ "meta_$key" ] ) ) { + $primary_meta_query[ $key ] = $qv[ "meta_$key" ]; + } } // WP_Query sets 'meta_value' = '' by default. - if ( isset( $qv[ 'meta_value' ] ) && '' !== $qv[ 'meta_value' ] && ( ! is_array( $qv[ 'meta_value' ] ) || $qv[ 'meta_value' ] ) ) - $meta_query[0]['value'] = $qv[ 'meta_value' ]; + if ( isset( $qv['meta_value'] ) && '' !== $qv['meta_value'] && ( ! is_array( $qv['meta_value'] ) || $qv['meta_value'] ) ) { + $primary_meta_query['value'] = $qv['meta_value']; + } - if ( !empty( $qv['meta_query'] ) && is_array( $qv['meta_query'] ) ) { - $meta_query = array_merge( $meta_query, $qv['meta_query'] ); + $existing_meta_query = isset( $qv['meta_query'] ) && is_array( $qv['meta_query'] ) ? $qv['meta_query'] : array(); + + if ( ! empty( $primary_meta_query ) && ! empty( $existing_meta_query ) ) { + $meta_query = array( + 'relation' => 'AND', + $primary_meta_query, + $existing_meta_query, + ); + } else if ( ! empty( $primary_meta_query ) ) { + $meta_query = array( + $primary_meta_query, + ); + } else if ( ! empty( $existing_meta_query ) ) { + $meta_query = $existing_meta_query; } $this->__construct( $meta_query ); diff --git a/tests/phpunit/tests/meta/query.php b/tests/phpunit/tests/meta/query.php index ceee7cf931..47fe7a6d28 100644 --- a/tests/phpunit/tests/meta/query.php +++ b/tests/phpunit/tests/meta/query.php @@ -104,9 +104,12 @@ class Tests_Meta_Query extends WP_UnitTestCase { $this->assertEquals( $expected0, $query->queries[0] ); $expected1 = array( - 'key' => 'foo1', - 'compare' => 'baz1', - 'value' => 'bar1', + 'relation' => 'OR', + array( + 'key' => 'foo1', + 'compare' => 'baz1', + 'value' => 'bar1', + ), ); $this->assertEquals( $expected1, $query->queries[1] ); } diff --git a/tests/phpunit/tests/post/query.php b/tests/phpunit/tests/post/query.php index adf683c81e..d5d16a4e6f 100644 --- a/tests/phpunit/tests/post/query.php +++ b/tests/phpunit/tests/post/query.php @@ -1187,6 +1187,90 @@ class Tests_Post_Query extends WP_UnitTestCase { $this->assertEqualSets( array( $post_4, $post_3, $post_2, $post_1 ), $query->posts ); } + /** + * @group meta + * @ticket 29604 + */ + public function test_meta_query_with_orderby_meta_value_relation_or() { + $posts = $this->factory->post->create_many( 4 ); + update_post_meta( $posts[0], 'foo', 5 ); + update_post_meta( $posts[1], 'foo', 6 ); + update_post_meta( $posts[2], 'foo', 4 ); + update_post_meta( $posts[3], 'foo', 7 ); + + update_post_meta( $posts[0], 'bar1', 'baz' ); + update_post_meta( $posts[1], 'bar1', 'baz' ); + update_post_meta( $posts[2], 'bar2', 'baz' ); + + $query = new WP_Query( array( + 'orderby' => 'meta_value', + 'order' => 'ASC', + 'meta_key' => 'foo', + 'meta_query' => array( + 'relation' => 'OR', + array( + 'key' => 'bar1', + 'value' => 'baz', + 'compare' => '=', + ), + array( + 'key' => 'bar2', + 'value' => 'baz', + 'compare' => '=', + ), + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + + $this->assertEquals( array( $posts[2], $posts[0], $posts[1] ), $query->posts ); + } + + /** + * @group meta + * @ticket 29604 + */ + public function test_meta_query_with_orderby_meta_value_relation_and() { + $posts = $this->factory->post->create_many( 4 ); + update_post_meta( $posts[0], 'foo', 5 ); + update_post_meta( $posts[1], 'foo', 6 ); + update_post_meta( $posts[2], 'foo', 4 ); + update_post_meta( $posts[3], 'foo', 7 ); + + update_post_meta( $posts[0], 'bar1', 'baz' ); + update_post_meta( $posts[1], 'bar1', 'baz' ); + update_post_meta( $posts[2], 'bar1', 'baz' ); + update_post_meta( $posts[3], 'bar1', 'baz' ); + update_post_meta( $posts[0], 'bar2', 'baz' ); + update_post_meta( $posts[1], 'bar2', 'baz' ); + update_post_meta( $posts[2], 'bar2', 'baz' ); + + $query = new WP_Query( array( + 'orderby' => 'meta_value', + 'order' => 'ASC', + 'meta_key' => 'foo', + 'meta_query' => array( + 'relation' => 'AND', + array( + 'key' => 'bar1', + 'value' => 'baz', + 'compare' => '=', + ), + array( + 'key' => 'bar2', + 'value' => 'baz', + 'compare' => '=', + ), + ), + 'update_post_meta_cache' => false, + 'update_post_term_cache' => false, + 'fields' => 'ids', + ) ); + + $this->assertEquals( array( $posts[2], $posts[0], $posts[1] ), $query->posts ); + } + /** * @ticket 29642 * @group meta