Skip to:
Content

BuddyPress.org


Ignore:
Timestamp:
06/03/2013 05:12:54 PM (11 years ago)
Author:
boonebgorges
Message:

Introduces BP_Group_Member_Query and refactors bp_group_has_members() to use it

BP_Group_Member_Query extends BP_User_Query, which has a number of notable
benefits:

  • Group member queries no longer JOIN against global user tables
  • Less code duplication, since general logic like 'exclude' is handled by BP_User_Query
  • Future access to the additional parameters of BP_User_Query, such as 'type'

Using the new BP_Group_Member_Query, this changeset also changes the way that
group member queries filter by group roles (member, mod, admin). The new
group_role parameter in the bp_group_has_members() stack accepts an array of
group roles. The legacy argument 'exclude_admins_mods' is still accepted, and
translates to 'group_role' => array( 'member' ) when true. These group_role
enhancements will allow for future enhancements in the Groups Admin section of
the Dashboard, and other places where it might be useful to query for the
members of a group matching a specific role. See #4977.

Fixes #4482

Props trishasalas for early patches and feedback. Props johnjamesjacoby for
review.

File:
1 edited

Legend:

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

    r7140 r7141  
    948948}
    949949
     950/**
     951 * Query for the members of a group
     952 *
     953 * @since BuddyPress (1.8)
     954 */
     955class BP_Group_Member_Query extends BP_User_Query {
     956    /**
     957     * Set up action hooks
     958     *
     959     * @since BuddyPress (1.8)
     960     */
     961    public function setup_hooks() {
     962        // Take this early opportunity to set the default 'type' param
     963        // to 'last_modified', which will ensure that BP_User_Query
     964        // trusts our order and does not try to apply its own
     965        if ( empty( $this->query_vars_raw['type'] ) ) {
     966            $this->query_vars_raw['type'] = 'last_modified';
     967        }
     968
     969        // Set up our populate_extras method
     970        add_action( 'bp_user_query_populate_extras', array( $this, 'populate_group_member_extras' ), 10, 2 );
     971    }
     972
     973    /**
     974     * Get a list of user_ids to include in the IN clause of the main query
     975     *
     976     * Overrides BP_User_Query::get_include_ids(), adding our additional
     977     * group-member logic.
     978     *
     979     * @since BuddyPress (1.8)
     980     * @param array
     981     * @return array
     982     */
     983    public function get_include_ids( $include ) {
     984        // The following args are specific to group member queries, and
     985        // are not present in the query_vars of a normal BP_User_Query.
     986        // We loop through to make sure that defaults are set (though
     987        // values passed to the constructor will, as usual, override
     988        // these defaults).
     989        $this->query_vars = wp_parse_args( $this->query_vars, array(
     990            'group_id'       => 0,
     991            'group_role'     => array( 'member' ),
     992            'exclude_banned' => true,
     993        ) );
     994
     995        $group_member_ids = $this->get_group_member_ids();
     996
     997        if ( ! empty( $include ) ) {
     998            $group_member_ids = array_intersect( $include, $group_member_ids );
     999        }
     1000
     1001        return $group_member_ids;
     1002    }
     1003
     1004    /**
     1005     * Get the members of the queried group
     1006     *
     1007     * @since BuddyPress (1.8)
     1008     * @return array $ids User IDs of relevant group member ids
     1009     */
     1010    protected function get_group_member_ids() {
     1011        global $wpdb;
     1012
     1013        $bp  = buddypress();
     1014        $sql = array(
     1015            'select'  => "SELECT user_id FROM {$bp->groups->table_name_members}",
     1016            'where'   => array(),
     1017            'orderby' => '',
     1018            'order'   => '',
     1019            'limit'   => '',
     1020        );
     1021
     1022        /** WHERE clauses *****************************************************/
     1023
     1024        $sql['where'][] = $wpdb->prepare( "group_id = %d", $this->query_vars['group_id'] );
     1025
     1026        // Role information is stored as follows: admins have
     1027        // is_admin = 1, mods have is_mod = 1, and members have both
     1028        // set to 0.
     1029        $roles = !empty( $this->query_vars['group_role'] ) ? $this->query_vars['group_role'] : array();
     1030        if ( is_string( $roles ) ) {
     1031            $roles = explode( ',', $roles );
     1032        }
     1033
     1034        // Sanitize: Only 'admin', 'mod', and 'member' are valid
     1035        foreach ( $roles as $role_key => $role_value ) {
     1036            if ( ! in_array( $role_value, array( 'admin', 'mod', 'member' ) ) ) {
     1037                unset( $roles[ $role_key ] );
     1038            }
     1039        }
     1040
     1041        // Remove dupes to make the count accurate, and flip for faster
     1042        // isset() lookups
     1043        $roles = array_flip( array_unique( $roles ) );
     1044
     1045        switch ( count( $roles ) ) {
     1046
     1047            // All three roles means we don't limit results
     1048            case 3 :
     1049            default :
     1050                $roles_sql = '';
     1051                break;
     1052
     1053            case 2 :
     1054                // member + mod = no admins
     1055                // member + admin = no mods
     1056                if ( isset( $roles['member'] ) ) {
     1057                    $roles_sql = isset( $roles['admin'] ) ? "is_mod = 0" : "is_admin = 0";
     1058
     1059                // Two non-member roles are 'admin' and 'mod'
     1060                } else {
     1061                    $roles_sql = "(is_admin = 1 OR is_mod = 1)";
     1062                }
     1063                break;
     1064
     1065            case 1 :
     1066                // member only means no admins or mods
     1067                if ( isset( $roles['member'] ) ) {
     1068                    $roles_sql = "is_admin = 0 AND is_mod = 0";
     1069
     1070                // Filter by that role only
     1071                } else {
     1072                    $roles_sql = isset( $roles['admin'] ) ? "is_admin = 1" : "is_mod = 1";
     1073                }
     1074                break;
     1075
     1076            // No roles means no users should be returned
     1077            case 0 :
     1078                $roles_sql = $this->no_results['where'];
     1079                break;
     1080        }
     1081
     1082        if ( ! empty( $roles_sql ) ) {
     1083            $sql['where'][] = $roles_sql;
     1084        }
     1085
     1086        if ( ! empty( $this->query_vars['exclude_banned'] ) ) {
     1087            $sql['where'][] = "is_banned = 0";
     1088        }
     1089
     1090        $sql['where'] = ! empty( $sql['where'] ) ? 'WHERE ' . implode( ' AND ', $sql['where'] ) : '';
     1091
     1092        /** ORDER BY clause ***************************************************/
     1093
     1094        // @todo For now, mimicking legacy behavior of
     1095        // bp_group_has_members(), which has us order by date_modified
     1096        // only. Should abstract it in the future
     1097        $sql['orderby'] = "ORDER BY date_modified";
     1098        $sql['order']   = "DESC";
     1099
     1100        /** LIMIT clause ******************************************************/
     1101
     1102        // Technically, this is also handled by BP_User_Query, but
     1103        // repeating the limit here helps to make the query more
     1104        // efficient, by not fetching every single matching user
     1105        if ( ! empty( $this->query_vars['per_page'] ) && ! empty( $this->query_vars['page'] ) ) {
     1106            $sql['limit'] = $wpdb->prepare( "LIMIT %d, %d", absint( ( $this->query_vars['page'] - 1 ) * $this->query_vars['per_page'] ), absint( $this->query_vars['per_page'] ) );
     1107        }
     1108
     1109        $ids = $wpdb->get_col( "{$sql['select']} {$sql['where']} {$sql['orderby']} {$sql['order']} {$sql['limit']}" );
     1110
     1111        return $ids;
     1112    }
     1113
     1114    /**
     1115     * Fetch additional data required in bp_group_has_members() loops
     1116     *
     1117     * @since BuddyPress (1.8)
     1118     * @param object $query BP_User_Query object. Because we're filtering
     1119     *   the current object, we use $this inside of the method instead
     1120     * @param string $user_ids_sql Sanitized, comma-separated string of
     1121     *   the user ids returned by the main query
     1122     */
     1123    public function populate_group_member_extras( $query, $user_ids_sql ) {
     1124        global $wpdb;
     1125
     1126        $bp     = buddypress();
     1127        $extras = $wpdb->get_results( $wpdb->prepare( "SELECT user_id, date_modified, is_banned FROM {$bp->groups->table_name_members} WHERE user_id IN ({$user_ids_sql}) AND group_id = %d", $this->query_vars['group_id'] ) );
     1128
     1129        foreach ( (array) $extras as $extra ) {
     1130            if ( isset( $this->results[ $extra->user_id ] ) ) {
     1131                // user_id is provided for backward compatibility
     1132                $this->results[ $extra->user_id ]->user_id       = (int) $extra->user_id;
     1133                $this->results[ $extra->user_id ]->is_banned     = (int) $extra->is_banned;
     1134                $this->results[ $extra->user_id ]->date_modified = $extra->date_modified;
     1135            }
     1136        }
     1137
     1138        // Don't filter other BP_User_Query objects on the same page
     1139        remove_action( 'bp_user_query_populate_extras', array( $this, 'populate_group_member_extras' ), 10, 2 );
     1140    }
     1141}
     1142
    9501143class BP_Groups_Member {
    9511144    var $id;
     
    13991592    function get_all_for_group( $group_id, $limit = false, $page = false, $exclude_admins_mods = true, $exclude_banned = true, $exclude = false ) {
    14001593        global $bp, $wpdb;
     1594
     1595        _deprecated_function( __METHOD__, '1.8', 'BP_Group_Member_Query' );
    14011596
    14021597        $pag_sql = '';
Note: See TracChangeset for help on using the changeset viewer.