From b13705965665420b8848a41709ecc2f1ef1b9434 Mon Sep 17 00:00:00 2001 From: Boone Gorges Date: Sun, 19 Oct 2014 18:54:19 +0000 Subject: [PATCH] Make orderby=meta_value compatible with meta_query when relation=OR. Passing orderby=meta_value and meta_key=foo to WP_Query should require that each matched post have a meta value with the key 'foo'. To make this requirement compatible with meta_query params that have the relation OR, we nest the meta_query param, and join it using AND to a meta_query clause generated from the meta_key/meta_compare/meta_type query vars. Fixes #25538. Built from https://develop.svn.wordpress.org/trunk@29964 git-svn-id: http://core.svn.wordpress.org/trunk@29711 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/meta.php | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/wp-includes/meta.php b/wp-includes/meta.php index e1d0652214..e9f7811c31 100644 --- a/wp-includes/meta.php +++ b/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 );