From 5dfd6a02a7c633127ce0207bb2d237614a24111a Mon Sep 17 00:00:00 2001 From: Boone Gorges Date: Tue, 9 Jun 2015 17:42:28 +0000 Subject: [PATCH] Avoid returning duplicate matches when using a meta query in `WP_User_Query`. A meta_query containing an `OR` relation can result in the same record matching multiple clauses, leading to duplicate results. The previous prevention against duplicates [18178] #17582 became unreliable in 4.1 when `WP_Meta_Query` introduced support for nested clauses. The current changeset adds a new method `WP_Meta_Query::has_or_relation()` for checking whether an `OR` relation appears anywhere in the query, and uses the new method in `WP_User_Query` to enforce distinct results as necessary. Props maxxsnake. Fixes #32592. Built from https://develop.svn.wordpress.org/trunk@32713 git-svn-id: http://core.svn.wordpress.org/trunk@32683 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/meta.php | 25 +++++++++++++++++++++++++ wp-includes/user.php | 2 +- wp-includes/version.php | 2 +- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/wp-includes/meta.php b/wp-includes/meta.php index ead200455f..d1b74d904a 100644 --- a/wp-includes/meta.php +++ b/wp-includes/meta.php @@ -953,6 +953,15 @@ class WP_Meta_Query { */ protected $clauses = array(); + /** + * Whether the query contains any OR relations. + * + * @since 4.3.0 + * @access protected + * @var bool + */ + protected $has_or_relation = false; + /** * Constructor. * @@ -1046,6 +1055,7 @@ class WP_Meta_Query { // Sanitize the 'relation' key provided in the query. if ( isset( $relation ) && 'OR' === strtoupper( $relation ) ) { $clean_queries['relation'] = 'OR'; + $this->has_or_relation = true; /* * If there is only a single clause, call the relation 'OR'. @@ -1578,6 +1588,21 @@ class WP_Meta_Query { */ return apply_filters( 'meta_query_find_compatible_table_alias', $alias, $clause, $parent_query, $this ) ; } + + /** + * Check whether the current query has any OR relations. + * + * In some cases, the presence of an OR relation somewhere in the query will require the use of a DISTINCT or + * GROUP BY keyword in the SELECT clause. The current method can be used in these cases to determine whether + * such a clause is necessary. + * + * @since 4.3.0 + * + * @return bool True if the query contains any OR relations, otherwise false. + */ + public function has_or_relation() { + return $this->has_or_relation; + } } /** diff --git a/wp-includes/user.php b/wp-includes/user.php index 2599ce01a9..cb9695cf7b 100644 --- a/wp-includes/user.php +++ b/wp-includes/user.php @@ -709,7 +709,7 @@ class WP_User_Query { $this->query_from .= $clauses['join']; $this->query_where .= $clauses['where']; - if ( 'OR' == $this->meta_query->relation ) { + if ( $this->meta_query->has_or_relation() ) { $this->query_fields = 'DISTINCT ' . $this->query_fields; } } diff --git a/wp-includes/version.php b/wp-includes/version.php index e3a0247f95..533fdb63ff 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -4,7 +4,7 @@ * * @global string $wp_version */ -$wp_version = '4.3-alpha-32712'; +$wp_version = '4.3-alpha-32713'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.