From 27d0a177f730916c3117629486e9dfd330c6c605 Mon Sep 17 00:00:00 2001 From: scribu Date: Sun, 5 Sep 2010 13:31:33 +0000 Subject: [PATCH] introduce _wp_meta_sql(). Preparation for adding blog_id to WP_User_Query. See #14572 git-svn-id: http://svn.automattic.com/wordpress/trunk@15565 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/functions.php | 50 +++++++++++++++++++++++++++++++++++++++ wp-includes/user.php | 37 ++++++++++++++++------------- 2 files changed, 71 insertions(+), 16 deletions(-) diff --git a/wp-includes/functions.php b/wp-includes/functions.php index 28f501f038..51dc9ba951 100644 --- a/wp-includes/functions.php +++ b/wp-includes/functions.php @@ -4218,6 +4218,56 @@ function _wp_search_sql($string, $cols) { return ' AND (' . implode(' OR ', $searches) . ')'; } +/* + * Used internally to generate an SQL string for searching across multiple meta key = value pairs + * + * @access private + * @since 3.1.0 + * + * @param array $queries An array of queries + * @return string + */ +function _wp_meta_sql( $queries, $meta_id_column, $table ) { + global $wpdb; + + $clauses = array(); + + foreach ( $queries as $query ) { + $meta_key = trim( @$query['meta_key'] ); + $meta_value = trim( @$query['meta_value'] ); + $meta_compare = @$query['meta_compare']; + + if ( empty( $meta_compare ) || !in_array( $meta_compare, array( '=', '!=', '>', '>=', '<', '<=', 'like' ) ) ) + $meta_compare = '='; + + if ( empty( $meta_key ) ) + continue; + + $clause = $wpdb->prepare( "WHEN %s THEN meta_value ", $meta_key ); + + if ( empty( $meta_value ) ) { + $clauses[] = $clause . "IS NOT NULL"; + } elseif ( 'like' == $meta_compare ) { + $clauses[] = $clause . $wpdb->prepare( "LIKE %s", '%' . like_escape( $meta_value ) . '%' ); + } else { + $clauses[] = $clause . $wpdb->prepare( "$meta_compare %s", $meta_value ); + } + } + + if ( empty( $clauses ) ) + return ''; + + return " + SELECT $meta_id_column + FROM $table + WHERE CASE meta_key + " . implode( "\n", $clauses ) . " + END + GROUP BY $meta_id_column + HAVING COUNT(*) = " . count( $clauses ); +} + + /* * Used internally to tidy up the search terms * diff --git a/wp-includes/user.php b/wp-includes/user.php index 0a8355cf30..5f37bb644f 100644 --- a/wp-includes/user.php +++ b/wp-includes/user.php @@ -379,7 +379,7 @@ class WP_User_Query { 'orderby' => 'login', 'order' => 'ASC', 'meta_key' => '', 'meta_value' => '', 'include' => array(), 'exclude' => array(), - 'fields' => 'all' + 'fields' => 'all', ) ); $this->prepare_query(); @@ -445,26 +445,31 @@ class WP_User_Query { $role = trim( $qv['role'] ); - if ( $role || is_multisite() ) { - $this->query_from .= " INNER JOIN $wpdb->usermeta ON $wpdb->users.ID = $wpdb->usermeta.user_id"; - $this->query_where .= $wpdb->prepare( " AND $wpdb->usermeta.meta_key = %s", $wpdb->prefix . 'capabilities' ); - } + $meta_queries = array(); + + $cap_meta_query = array(); + $cap_meta_key = $wpdb->prefix . 'capabilities'; + + if ( $role || is_multisite() ) + $cap_meta_query['meta_key'] = $cap_meta_key; if ( $role ) { - $this->query_where .= $wpdb->prepare( " AND $wpdb->usermeta.meta_value LIKE %s", '%' . like_escape( $role ) . '%' ); + $cap_meta_query['meta_value'] = $role; + $cap_meta_query['meta_compare'] = 'like'; } - $meta_key = trim( $qv['meta_key'] ); - $meta_value = trim( $qv['meta_value'] ); - if ( $meta_key ) { - if ( empty( $meta_value ) ) { - $subquery = $wpdb->prepare( "SELECT user_id FROM {$wpdb->usermeta} WHERE meta_key = %s", $meta_key ); - } - else { - $subquery = $wpdb->prepare( "SELECT user_id FROM {$wpdb->usermeta} WHERE meta_key = %s AND meta_value = %s", $meta_key, $meta_value ); - } + $meta_queries[] = $cap_meta_query; - $this->query_where .= " AND $wpdb->users.ID IN ($subquery)"; + $meta_queries[] = array( + 'meta_key' => @$qv['meta_key'], + 'meta_value' => @$qv['meta_key'], + 'meta_compare' => @$qv['meta_key'], + ); + + $meta_query_sql = _wp_meta_sql( $meta_queries, 'user_id', $wpdb->usermeta ); + + if ( !empty( $meta_query_sql ) ) { + $this->query_where .= " AND $wpdb->users.ID IN ($meta_query_sql)"; } if ( !empty($qv['include']) ) {