Skip to:
Content

BuddyPress.org

Changeset 6314


Ignore:
Timestamp:
09/07/2012 02:14:42 AM (12 years ago)
Author:
boonebgorges
Message:

Introduces BP_User_Query for improved member query performance

  • Introduces BP_User_Query class
  • Deprecates use of BP_Core_User::get_users() in bp_core_get_users(), the main member query function in BuddyPress
  • Introduces bp_use_legacy_user_query filter, to allow plugins to use legacy query method during transition
  • Expands user query functionality to support 'user_ids' parameter, which can be used to skip the user_id query altogether, for maximum flexibility in plugins and themes

Props boonebgorges, johnjamesjacoby.

See #4060

Location:
trunk
Files:
1 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/bp-core/bp-core-classes.php

    r6313 r6314  
    11<?php
     2
    23// Exit if accessed directly
    34if ( !defined( 'ABSPATH' ) ) exit;
     5
     6/**
     7 * BuddyPress User Query class
     8 *
     9 * Used for querying users in a BuddyPress context, in situations where
     10 * WP_User_Query won't do the trick: Member directories, the Friends component,
     11 * etc.
     12 *
     13 * Accepted parameters:
     14 *   type        - Determines sort order. Select from 'newest', 'active',
     15 *                     'online', 'random', 'popular', 'alphabetical'
     16 *   per_page        - Number of results to return
     17 *   page            - Page offset (together with per_page)
     18 *   user_id         - Pass a single numeric user id to limit results to
     19 *                     friends of that user. Requires the Friends component
     20 *   search_terms    - Terms to search by. Search happens across xprofile
     21 *                     fields. Requires XProfile component
     22 *   include         - An array or comma-separated list of user ids. Results
     23 *                     will be limited to users in this list
     24 *   exclude         - An array or comma-separated list of user ids. Results
     25 *                     will not include any users in this list
     26 *   user_ids        - An array or comma-separated list of user ids. When
     27 *                     this parameter is passed, it will override all other
     28 *                     parameters; BP User objects will be constructed using
     29 *                     these IDs only
     30 *   meta_key        - Limit results to users that have usermeta associated
     31 *                     with this meta_key. Usually used with meta_value
     32 *   meta_value      - When used with meta_key, limits results to users whose
     33 *                     usermeta value associated with meta_key matches
     34 *                     meta_value
     35 *   populate_extras - Boolean. True if you want to fetch extra metadata about
     36 *                     returned users, such as total group and friend counts
     37 *   count_total     - Determines how BP_User_Query will do a count of total
     38 *                     users matching the other filter criteria. Default value
     39 *                     is 'count_query', which does a separate SELECT COUNT
     40 *                     query to determine the total. 'sql_count_found_rows'
     41 *                     uses SQL_COUNT_FOUND_ROWS and SELECT FOUND_ROWS(). Pass
     42 *                     an empty string to skip the total user count query.
     43 *
     44 * @since BuddyPress (1.7)
     45 */
     46class BP_User_Query {
     47
     48    /** Variables *************************************************************/
     49
     50    /**
     51     * Array of variables to query with
     52     *
     53     * @since BuddyPress (1.7)
     54     * @var array
     55     */
     56    public $query_vars = array();
     57
     58    /**
     59     * List of found users and their respective data
     60     *
     61     * @since BuddyPress (1.7)
     62     * @access public To allow components to manipulate them
     63     * @var array
     64     */
     65    public $results = array();
     66
     67    /**
     68     * Total number of found users for the current query
     69     *
     70     * @since BuddyPress (1.7)
     71     * @access public To allow components to manipulate it
     72     * @var int
     73     */
     74    public $total_users = 0;
     75
     76    /**
     77     * List of found user ID's
     78     *
     79     * @since BuddyPress (1.7)
     80     * @access public To allow components to manipulate it
     81     * @var array
     82     */
     83    public $user_ids = array();
     84
     85    /**
     86     * SQL clauses for the user ID query
     87     *
     88     * @since BuddyPress (1.7)
     89     * @access public To allow components to manipulate it
     90     * @var array()
     91     */
     92    public $uid_clauses = array();
     93
     94    /**
     95     * SQL database column name to order by
     96     *
     97     * @since BuddyPress (1.7)
     98     * @var string
     99     */
     100    public $uid_name = '';
     101
     102    /** Methods ***************************************************************/
     103
     104    /**
     105     * Constructor
     106     *
     107     * @since 1.7
     108     *
     109     * @param string|array $query The query variables
     110     */
     111    public function __construct( $query = null ) {
     112        if ( ! empty( $query ) ) {
     113            $this->query_vars = wp_parse_args( $query, array(
     114                'type'            => 'newest',
     115                'per_page'        => 0,
     116                'page'            => 1,
     117                'user_id'         => 0,
     118                'search_terms'    => false,
     119                'include'         => false,
     120                'exclude'         => false,
     121                'user_ids'        => false,
     122                'meta_key'        => false,
     123                'meta_value'      => false,
     124                'populate_extras' => true,
     125                'count_total'     => 'count_query'
     126            ) );
     127
     128            // Plugins can use this filter to modify query args
     129            // before the query is constructed
     130            do_action_ref_array( 'bp_pre_user_query_construct', array( &$this ) );
     131
     132            // Get user ids
     133            // If the user_ids param is present, we skip the query
     134            if ( false !== $this->query_vars['user_ids'] ) {
     135                $this->user_ids = wp_parse_id_list( $this->query_vars['user_ids'] );
     136            } else {
     137                $this->prepare_user_ids_query();
     138                $this->do_user_ids_query();
     139            }
     140        }
     141
     142        // Bail if no user IDs were found
     143        if ( empty( $this->user_ids ) ) {
     144            return;
     145        }
     146
     147        // Fetch additional data. First, using WP_User_Query
     148        $this->do_wp_user_query();
     149
     150        // Get BuddyPress specific user data
     151        $this->populate_extras();
     152    }
     153
     154    /**
     155     * Prepare the query for user_ids
     156     *
     157     * @since BuddyPress (1.7)
     158     */
     159    public function prepare_user_ids_query() {
     160        global $wpdb, $bp;
     161
     162        // Default query variables used here
     163        $type         = '';
     164        $per_page     = 0;
     165        $page         = 1;
     166        $user_id      = 0;
     167        $include      = false;
     168        $search_terms = false;
     169        $exclude      = false;
     170        $meta_key     = false;
     171        $meta_value   = false;
     172
     173        extract( $this->query_vars );
     174
     175        // Setup the main SQL query container
     176        $sql = array(
     177            'select'  => '',
     178            'where'   => array(),
     179            'orderby' => '',
     180            'order'   => '',
     181            'limit'   => ''
     182        );
     183
     184        /** TYPE **************************************************************/
     185
     186        // Determines the sort order, which means it also determines where the
     187        // user IDs are drawn from (the SELECT and WHERE statements)
     188        switch ( $type ) {
     189
     190            // 'active', 'online', 'newest', and 'random' queries
     191            // all happen against the last_activity usermeta key
     192            case 'active' :
     193            case 'online' :
     194            case 'newest' :
     195            case 'random' :
     196                $this->uid_name = 'user_id';
     197                $sql['select']  = "SELECT DISTINCT u.{$this->uid_name} as id FROM {$wpdb->usermeta} u";
     198                $sql['where'][] = $wpdb->prepare( "u.meta_key = %s", bp_get_user_meta_key( 'last_activity' ) );
     199
     200                if ( 'newest' == $type ) {
     201                    $sql['orderby'] = "ORDER BY u.user_id";
     202                    $sql['order'] = "DESC";
     203                } else if ( 'random' == $type ) {
     204                    $sql['orderby'] = "ORDER BY rand()";
     205                } else {
     206                    $sql['orderby'] = "ORDER BY u.meta_value";
     207                    $sql['order'] = "DESC";
     208                }
     209
     210                break;
     211
     212            // 'popular' sorts by the 'total_friend_count' usermeta
     213            case 'popular' :
     214                $this->uid_name = 'user_id';
     215                $sql['select']  = "SELECT DISTINCT u.{$this->uid_name} as id FROM {$wpdb->usermeta} u";
     216                $sql['where'][] = $wpdb->prepare( "u.meta_key = %s", bp_get_user_meta_key( 'total_friend_count' ) );
     217                $sql['orderby'] = "ORDER BY u.meta_value";
     218                $sql['order']   = "DESC";
     219
     220                break;
     221
     222            // 'alphabetical' sorts depend on the xprofile setup
     223            case 'alphabetical' :
     224
     225                // We prefer to do alphabetical sorts against the display_name field
     226                // of wp_users, because the table is smaller and better indexed. We
     227                // can do so if xprofile sync is enabled, or if xprofile is inactive.
     228                //
     229                // @todo remove need for bp_is_active() check
     230                if ( ! bp_disable_profile_sync() || ! bp_is_active( 'xprofile' ) ) {
     231                    $this->uid_name = 'ID';
     232                    $sql['select']  = "SELECT DISTINCT u.{$this->uid_name} as id FROM {$wpdb->users} u";
     233                    $sql['orderby'] = "ORDER BY u.display_name";
     234                    $sql['order']   = "ASC";
     235
     236                // When profile sync is disabled, alphabetical sorts must happen against
     237                // the xprofile table
     238                } else {
     239                    $fullname_field_id = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$bp->profile->table_name_fields} WHERE name = %s", bp_xprofile_fullname_field_name() ) );
     240
     241                    $this->uid_name = 'user_id';
     242                    $sql['select']  = "SELECT DISTINCT u.{$this->uid_name} as id FROM {$bp->profile->table_name_data} u";
     243                    $sql['where'][] = "u.field_id = {$fullname_field_id}";
     244                    $sql['orderby'] = "ORDER BY u.value";
     245                    $sql['order']   = "ASC";
     246                }
     247
     248                break;
     249
     250            // Any other 'type' falls through
     251            default :
     252                $this->uid_name = 'ID';
     253                $sql['select']  = "SELECT DISTINCT u.{$this->uid_name} as id FROM {$wpdb->users} u";
     254
     255                // In this case, we assume that a plugin is
     256                // handling order, so we leave those clauses
     257                // blank
     258
     259                break;
     260        }
     261
     262        /** WHERE *************************************************************/
     263
     264        // 'include' - User ids to include in the results
     265        if ( false !== $include ) {
     266            $include        = wp_parse_id_list( $include );
     267            $include_ids    = $wpdb->escape( implode( ',', (array) $include ) );
     268            $sql['where'][] = "u.{$this->uid_name} IN ({$include_ids})";
     269        }
     270
     271        // 'exclude' - User ids to exclude from the results
     272        if ( false !== $exclude ) {
     273            $exclude        = wp_parse_id_list( $exclude );
     274            $exclude_ids    = $wpdb->escape( implode( ',', (array) $exclude ) );
     275            $sql['where'][] = "u.{$this->uid_name} NOT IN ({$exclude_ids})";
     276        }
     277
     278        // 'user_id' - When a user id is passed, limit to the friends of the user
     279        // @todo remove need for bp_is_active() check
     280        if ( !empty( $user_id ) && bp_is_active( 'friends' ) ) {
     281            $friend_ids = friends_get_friend_user_ids( $user_id );
     282            $friend_ids = $wpdb->escape( implode( ',', (array) $friend_ids ) );
     283
     284            if ( !empty( $friend_ids ) ) {
     285                $sql['where'][] = "u.{$this->uid_name} NOT IN ({$friend_ids})";
     286            } else {
     287                // If the user has no friends, make sure the query returns null
     288                $sql['where'][] = "0 = 1";
     289            }
     290        }
     291
     292        /** Search Terms ******************************************************/
     293
     294        // 'search_terms' searches the xprofile fields
     295        // To avoid global joins, do a separate query
     296        // @todo remove need for bp_is_active() check
     297        if ( false !== $search_terms && bp_is_active( 'xprofile' ) ) {
     298            $found_user_ids = $wpdb->get_col( $wpdb->prepare( "SELECT user_id FROM {$bp->profile->table_name_data} WHERE value LIKE %s", '%%' . like_escape( $search_terms ) . '%%' ), ARRAY_N );
     299
     300            if ( ! empty( $found_user_ids ) ) {
     301                $sql['where'][] = "u.{$this->uid_name} IN (" . implode( ',', wp_parse_id_list( $found_user_ids ) ) . ")";
     302            }
     303        }
     304
     305        // 'meta_key', 'meta_value' allow usermeta search
     306        // To avoid global joins, do a separate query
     307        if ( false !== $meta_key ) {
     308            $meta_sql = $wpdb->prepare( "SELECT user_id FROM {$wpdb->usermeta} WHERE meta_key = %s", $meta_key );
     309
     310            if ( false !== $meta_value ) {
     311                $meta_sql .= $wpdb->prepare( " AND meta_value = %s", $meta_value );
     312            }
     313
     314            $found_user_ids = $wpdb->get_col( $meta_sql );
     315
     316            if ( ! empty( $found_user_ids ) ) {
     317                $sql['where'][] = "u.{$this->uid_name} IN (" . implode( ',', wp_parse_id_list( $found_user_ids ) ) . ")";
     318            }
     319        }
     320
     321        // 'per_page', 'page' - handles LIMIT
     322        if ( !empty( $per_page ) && !empty( $page ) ) {
     323            $sql['limit'] = $wpdb->prepare( "LIMIT %d, %d", intval( ( $page - 1 ) * $per_page ), intval( $per_page ) );
     324        } else {
     325            $sql['limit'] = '';
     326        }
     327
     328        // Assemble the query chunks
     329        $this->uid_clauses['select']  = $sql['select'];
     330        $this->uid_clauses['where']   = ! empty( $sql['where'] ) ? 'WHERE ' . implode( ' AND ', $sql['where'] ) : '';
     331        $this->uid_clauses['orderby'] = $sql['orderby'];
     332        $this->uid_clauses['order']   = $sql['order'];
     333        $this->uid_clauses['limit']   = $sql['limit'];
     334
     335        do_action_ref_array( 'bp_pre_user_query', array( &$this ) );
     336    }
     337
     338    /**
     339     * Perform a database query to specifically get only user IDs, using
     340     * existing query variables set previously in the constructor.
     341     *
     342     * Also used to quickly perform user total counts.
     343     *
     344     * @since BuddyPress (1.7)
     345     */
     346    public function do_user_ids_query() {
     347        global $wpdb;
     348
     349        // If counting using SQL_CALC_FOUND_ROWS, set it up here
     350        if ( 'sql_calc_found_rows' == $this->query_vars['count_total'] ) {
     351            $this->uid_clauses['select'] = str_replace( 'SELECT', 'SELECT SQL_CALC_FOUND_ROWS', $this->uid_clauses['select'] );
     352        }
     353
     354        // Get the specific user ids
     355        $this->user_ids = $wpdb->get_col( $wpdb->prepare( "{$this->uid_clauses['select']} {$this->uid_clauses['where']} {$this->uid_clauses['orderby']} {$this->uid_clauses['order']} {$this->uid_clauses['limit']}" ) );
     356
     357        // Get the total user count
     358        if ( 'sql_calc_found_rows' == $this->query_vars['count_total'] ) {
     359            $this->total_users = $wpdb->get_var( apply_filters( 'bp_found_user_query', "SELECT FOUND_ROWS()", $this ) );
     360        } elseif ( 'count_query' == $this->query_vars['count_total'] ) {
     361            $count_select      = preg_replace( '/^SELECT.*?FROM (\S+) u/', "SELECT COUNT(DISTINCT u.{$this->uid_name}) FROM $1 u", $this->uid_clauses['select'] );
     362            $this->total_users = $wpdb->get_var( apply_filters( 'bp_found_user_query', "{$count_select} {$this->uid_clauses['where']}", $this ) );
     363        }
     364    }
     365
     366    /**
     367     * Perform a database query using the WP_User_Query() object, using existing
     368     * fields, variables, and user ID's set previously in this class.
     369     *
     370     * @since BuddyPress (1.7)
     371     */
     372    public function do_wp_user_query() {
     373        $wp_user_query = new WP_User_Query( apply_filters( 'bp_wp_user_query_args', array(
     374
     375            // Relevant
     376            'fields'      => array( 'ID', 'user_registered', 'user_login', 'user_nicename', 'display_name', 'user_email' ),
     377            'include'     => $this->user_ids,
     378
     379            // Overrides
     380            'blog_id'     => 0,    // BP does not require blog roles
     381            'count_total' => false // We already have a count
     382
     383        ), $this ) );
     384
     385        // Reindex for easier matching
     386        $r = array();
     387        foreach ( $wp_user_query->results as $u ) {
     388            $r[ $u->ID ] = $u;
     389        }
     390
     391        // Match up to the user ids from the main query
     392        foreach ( $this->user_ids as $uid ) {
     393            if ( isset( $r[ $uid ] ) ) {
     394                $this->results[ $uid ] = $r[ $uid ];
     395
     396                // The BP template functions expect an 'id'
     397                // (as opposed to 'ID') property
     398                $this->results[ $uid ]->id = $uid;
     399            }
     400        }
     401    }
     402
     403    /**
     404     * Perform a database query to populate any extra metadata we might need.
     405     * Different components will hook into the 'bp_user_query_populate_extras'
     406     * action to loop in the things they want.
     407     *
     408     * @since BuddyPress (1.7)
     409     *
     410     * @global BuddyPress $bp
     411     * @global WPDB $wpdb
     412     * @return
     413     */
     414    public function populate_extras() {
     415        global $wpdb;
     416
     417        // Bail if no users
     418        if ( empty( $this->user_ids ) || empty( $this->results ) ) {
     419            return;
     420        }
     421
     422        // Bail if the populate_extras flag is set to false
     423        // In the case of the 'popular' sort type, we force
     424        // populate_extras to true, because we need the friend counts
     425        if ( 'popular' == $this->query_vars['type'] ) {
     426            $this->query_vars['populate_extras'] = 1;
     427        }
     428
     429        if ( ! (bool) $this->query_vars['populate_extras'] ) {
     430            return;
     431        }
     432
     433        // Turn user ID's into a query-usable, comma separated value
     434        $user_ids_sql = implode( ',', wp_parse_id_list( $this->user_ids ) );
     435
     436        /**
     437         * Use this action to independently populate your own custom extras.
     438         *
     439         * Note that anything you add here should query using $user_ids_sql, to
     440         * avoid running multiple queries per user in the loop.
     441         *
     442         * Two BuddyPress components currently do this:
     443         * - XProfile: To override display names
     444         * - Friends:  To set whether or not a user is the current users friend
     445         *
     446         * @see bp_xprofile_filter_user_query_populate_extras()
     447         * @see bp_friends_filter_user_query_populate_extras()
     448         */
     449        do_action_ref_array( 'bp_user_query_populate_extras', array( $this, $user_ids_sql ) );
     450
     451        // Fetch usermeta data
     452        // We want the three following pieces of info from usermeta:
     453        // - friend count
     454        // - last activity
     455        // - latest update
     456        $total_friend_count_key = bp_get_user_meta_key( 'total_friend_count' );
     457        $last_activity_key      = bp_get_user_meta_key( 'last_activity'      );
     458        $bp_latest_update_key   = bp_get_user_meta_key( 'bp_latest_update'   );
     459
     460        // total_friend_count must be set for each user, even if its
     461        // value is 0
     462        foreach ( $this->results as $uindex => $user ) {
     463            $this->results[$uindex]->total_friend_count = 0;
     464        }
     465
     466        // Create, prepare, and run the seperate usermeta query
     467        $user_metas = $wpdb->get_results( $wpdb->prepare( "SELECT user_id, meta_key, meta_value FROM {$wpdb->usermeta} WHERE meta_key IN (%s,%s,%s) AND user_id IN ({$user_ids_sql})", $total_friend_count_key, $last_activity_key, $bp_latest_update_key ) );
     468
     469        // The $members_template global expects the index key to be different
     470        // from the meta_key in some cases, so we rejig things here.
     471        foreach ( $user_metas as $user_meta ) {
     472            switch ( $user_meta->meta_key ) {
     473                case $total_friend_count_key :
     474                    $key = 'total_friend_count';
     475                    break;
     476
     477                case $last_activity_key :
     478                    $key = 'last_activity';
     479                    break;
     480
     481                case $bp_latest_update_key :
     482                    $key = 'latest_update';
     483                    break;
     484            }
     485
     486            if ( isset( $this->results[ $user_meta->user_id ] ) ) {
     487                $this->results[ $user_meta->user_id ]->{$key} = $user_meta->meta_value;
     488            }
     489        }
     490
     491        // When meta_key or meta_value have been passed to the query,
     492        // fetch the resulting values for use in the template functions
     493        if ( ! empty( $this->query_vars['meta_key'] ) ) {
     494            $meta_sql = array(
     495                'select' => "SELECT user_id, meta_key, meta_value",
     496                'from'   => "FROM $wpdb->usermeta",
     497                'where'  => $wpdb->prepare( "WHERE meta_key = %s", $this->query_vars['meta_key'] )
     498            );
     499
     500            if ( false !== $this->query_vars['meta_value'] ) {
     501                $meta_sql['where'] .= $wpdb->prepare( " AND meta_value = %s", $this->query_vars['meta_value'] );
     502            }
     503
     504            $metas = $wpdb->get_results( $wpdb->prepare( "{$meta_sql['select']} {$meta_sql['from']} {$meta_sql['where']}" ) );
     505
     506            if ( ! empty( $metas ) ) {
     507                foreach ( $metas as $meta ) {
     508                    if ( isset( $this->results[ $meta->user_id ] ) ) {
     509                        $this->results[ $meta->user_id ]->meta_key = $meta->meta_key;
     510
     511                        if ( ! empty( $meta->meta_value ) ) {
     512                            $this->results[ $meta->user_id ]->meta_value = $meta->meta_value;
     513                        }
     514                    }
     515                }
     516            }
     517        }
     518    }
     519}
    4520
    5521/**
     
    201717    function get_users( $type, $limit = 0, $page = 1, $user_id = 0, $include = false, $search_terms = false, $populate_extras = true, $exclude = false, $meta_key = false, $meta_value = false ) {
    202718        global $wpdb, $bp;
     719
     720        _deprecated_function( __METHOD__, '1.7', 'BP_User_Query' );
    203721
    204722        $sql = array();
  • trunk/bp-core/bp-core-widgets.php

    r6264 r6314  
    4040           . $after_title; ?>
    4141
    42         <?php if ( bp_has_members( 'user_id=0&type=' . $instance['member_default'] . '&max=' . $instance['max_members'] . '&populate_extras=0' ) ) : ?>
     42        <?php if ( bp_has_members( 'user_id=0&type=' . $instance['member_default'] . '&max=' . $instance['max_members'] . '&populate_extras=1' ) ) : ?>
    4343            <div class="item-options" id="members-list-options">
    4444                <a href="<?php echo site_url( bp_get_members_root_slug() ); ?>" id="newest-members" <?php if ( $instance['member_default'] == 'newest' ) : ?>class="selected"<?php endif; ?>><?php _e( 'Newest', 'buddypress' ) ?></a>
     
    157157           . $after_title; ?>
    158158
    159         <?php if ( bp_has_members( 'user_id=0&type=online&per_page=' . $instance['max_members'] . '&max=' . $instance['max_members'] . '&populate_extras=0' ) ) : ?>
     159        <?php if ( bp_has_members( 'user_id=0&type=online&per_page=' . $instance['max_members'] . '&max=' . $instance['max_members'] . '&populate_extras=1' ) ) : ?>
    160160            <div class="avatar-block">
    161161                <?php while ( bp_members() ) : bp_the_member(); ?>
     
    221221           . $after_title; ?>
    222222
    223         <?php if ( bp_has_members( 'user_id=0&type=active&per_page=' . $instance['max_members'] . '&max=' . $instance['max_members'] . '&populate_extras=0' ) ) : ?>
     223        <?php if ( bp_has_members( 'user_id=0&type=active&per_page=' . $instance['max_members'] . '&max=' . $instance['max_members'] . '&populate_extras=1' ) ) : ?>
    224224            <div class="avatar-block">
    225225                <?php while ( bp_members() ) : bp_the_member(); ?>
     
    291291    }
    292292
    293     if ( bp_has_members( 'user_id=0&type=' . $type . '&per_page=' . $_POST['max-members'] . '&max=' . $_POST['max-members'] . '&populate_extras=0' ) ) : ?>
     293    if ( bp_has_members( 'user_id=0&type=' . $type . '&per_page=' . $_POST['max-members'] . '&max=' . $_POST['max-members'] . '&populate_extras=1' ) ) : ?>
    294294        <?php echo '0[[SPLIT]]'; // return valid result. TODO: remove this. ?>
    295295        <div class="avatar-block">
  • trunk/bp-members/bp-members-functions.php

    r6269 r6314  
    7272 * Return an array of users IDs based on the parameters passed.
    7373 *
     74 * Since BuddyPress 1.7, bp_core_get_users() uses BP_User_Query. If you
     75 * need backward compatibility with BP_Core_User::get_users(), filter the
     76 * bp_use_legacy_user_query value, returning true.
     77 *
    7478 * @package BuddyPress Core
    7579 */
    7680function bp_core_get_users( $args = '' ) {
    7781
    78     $defaults = array(
    79         'type'            => 'active', // active, newest, alphabetical, random or popular
    80         'user_id'         => false,    // Pass a user_id to limit to only friend connections for this user
    81         'exclude'         => false,    // Users to exclude from results
    82         'search_terms'    => false,    // Limit to users that match these search terms
    83         'meta_key'        => false,    // Limit to users who have this piece of usermeta
    84         'meta_value'      => false,    // With meta_key, limit to users where usermeta matches this value
    85 
    86         'include'         => false,    // Pass comma separated list of user_ids to limit to only these users
    87         'per_page'        => 20,       // The number of results to return per page
    88         'page'            => 1,        // The page to return if limiting per page
    89         'populate_extras' => true,     // Fetch the last active, where the user is a friend, total friend count, latest update
    90     );
    91 
    92     $params = wp_parse_args( $args, $defaults );
    93     extract( $params, EXTR_SKIP );
    94 
    95     return apply_filters( 'bp_core_get_users', BP_Core_User::get_users( $type, $per_page, $page, $user_id, $include, $search_terms, $populate_extras, $exclude, $meta_key, $meta_value ), $params );
     82    // Parse the user query arguments
     83    $params = wp_parse_args( $args, array(
     84        'type'            => 'active',     // active, newest, alphabetical, random or popular
     85        'user_id'         => false,        // Pass a user_id to limit to only friend connections for this user
     86        'exclude'         => false,        // Users to exclude from results
     87        'search_terms'    => false,        // Limit to users that match these search terms
     88        'meta_key'        => false,        // Limit to users who have this piece of usermeta
     89        'meta_value'      => false,        // With meta_key, limit to users where usermeta matches this value
     90        'include'         => false,        // Pass comma separated list of user_ids to limit to only these users
     91        'per_page'        => 20,           // The number of results to return per page
     92        'page'            => 1,            // The page to return if limiting per page
     93        'populate_extras' => true,         // Fetch the last active, where the user is a friend, total friend count, latest update
     94        'count_total'     => 'count_query' // What kind of total user count to do, if any. 'count_query', 'sql_calc_found_rows', or false
     95    ) );
     96
     97    // For legacy users. Use of BP_Core_User::get_users() is deprecated.
     98    if ( apply_filters( 'bp_use_legacy_user_query', false, __FUNCTION__, $params ) ) {
     99        extract( $params, EXTR_SKIP );
     100        $retval = BP_Core_User::get_users( $type, $per_page, $page, $user_id, $include, $search_terms, $populate_extras, $exclude, $meta_key, $meta_value );
     101
     102    // Default behavior as of BuddyPress 1.7
     103    } else {       
     104
     105        // Get users like we were asked to do...
     106        $users = new BP_User_Query( $params );
     107
     108        // ...but reformat the results to match bp_core_get_users() behavior.
     109        $retval = array(
     110            'users' => array_values( $users->results ),
     111            'total' => $users->total_users
     112        );
     113    }
     114
     115    return apply_filters( 'bp_core_get_users', $retval, $params );
    96116}
    97117
  • trunk/bp-xprofile/bp-xprofile-filters.php

    r6224 r6314  
    220220add_filter( 'comments_array', 'xprofile_filter_comments', 10, 2 );
    221221
    222 
     222/**
     223 * Filter BP_User_Query::populate_extras to override each queries users fullname
     224 *
     225 * @since BuddyPress (1.7)
     226 *
     227 * @global BuddyPress $bp
     228 * @global WPDB $wpdb
     229 * @param BP_User_Query $user_query
     230 * @param string $user_ids_sql
     231 */
     232function bp_xprofile_filter_user_query_populate_extras( BP_User_Query $user_query, $user_ids_sql ) {
     233    global $bp, $wpdb;
     234
     235    if ( bp_is_active( 'xprofile' ) ) {
     236        $fullname_field_id = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$bp->profile->table_name_fields} WHERE name = %s", bp_xprofile_fullname_field_name() ) );
     237        $user_id_names     = $wpdb->get_results( $wpdb->prepare( "SELECT user_id, value as fullname FROM {$bp->profile->table_name_data} WHERE user_id IN ({$user_ids_sql}) AND field_id = {$fullname_field_id}" ) );
     238
     239        // Loop through names and override each user's fullname
     240        foreach ( $user_id_names as $user ) {
     241            if ( isset( $user_query->results[ $user->user_id ] ) ) {
     242                $user_query->results[ $user->user_id ]->fullname = $user->fullname;
     243            }
     244        }
     245    }
     246}
     247add_filter( 'bp_user_query_populate_extras', 'bp_xprofile_filter_user_query_populate_extras', 2, 2 );
    223248
    224249?>
Note: See TracChangeset for help on using the changeset viewer.