From d19002b239fa886f8c32885b1e1d489ea05a335e Mon Sep 17 00:00:00 2001 From: Kartik Suthar Date: Thu, 23 Jan 2025 20:44:33 +0530 Subject: [PATCH] WIP - group member query --- src/bp-core/classes/class-bp-invitation.php | 2 +- src/bp-core/classes/class-bp-user-query.php | 20 +- src/bp-groups/bp-groups-functions.php | 2 +- .../classes/class-bb-group-member-query.php | 476 ++++++++++++++++++ .../classes/class-bp-group-member-query.php | 253 ---------- .../class-bp-groups-invite-template.php | 2 +- src/class-buddypress.php | 1 + 7 files changed, 483 insertions(+), 273 deletions(-) create mode 100644 src/bp-groups/classes/class-bb-group-member-query.php diff --git a/src/bp-core/classes/class-bp-invitation.php b/src/bp-core/classes/class-bp-invitation.php index 99f5c5b1f9..32121769cc 100644 --- a/src/bp-core/classes/class-bp-invitation.php +++ b/src/bp-core/classes/class-bp-invitation.php @@ -843,7 +843,7 @@ public static function get( $args = array() ) { $paged_invites_sql = apply_filters( 'bp_invitations_get_paged_invitations_sql', $paged_invites_sql, $sql, $r ); if ( ! empty( $r['retval'] ) && 'sql' == $r['retval'] ) { - return str_replace( $sql['orderby'] . ' ' . $sql['pagination'], '', $paged_invites_sql ); + return $sql; } $cached = bp_core_get_incremented_cache( $paged_invites_sql, 'bp_invitations' ); diff --git a/src/bp-core/classes/class-bp-user-query.php b/src/bp-core/classes/class-bp-user-query.php index eba16f4980..6f32e7dd33 100644 --- a/src/bp-core/classes/class-bp-user-query.php +++ b/src/bp-core/classes/class-bp-user-query.php @@ -268,12 +268,7 @@ public function prepare_user_ids_query() { // 'include' - User ids to include in the results. $include = false !== $include ? wp_parse_id_list( $include ) : array(); - - $include_ids_sql = $this->get_include_ids_sql( $include ); - $include_ids = array(); - if ( empty( $include_ids_sql ) ) { - $include_ids = $this->get_include_ids( $include ); - } + $include_ids = $this->get_include_ids( $include ); /* TYPE **************************************************************/ @@ -387,10 +382,7 @@ public function prepare_user_ids_query() { $this->uid_name = 'ID'; $this->uid_table = $wpdb->users; $sql['select'] = "SELECT u.{$this->uid_name} as id FROM {$this->uid_table} u"; - if ( ! empty( $include_ids_sql ) ) { - $sql['where'][] = "u.{$this->uid_name} IN ({$include_ids_sql})"; - $sql['orderby'] = "ORDER BY FIELD(u.{$this->uid_name}, {$include_ids_sql})"; - } else if ( ! empty( $include_ids ) ) { + if ( ! empty( $include_ids ) ) { $include_ids = implode( ',', wp_parse_id_list( $include_ids ) ); $sql['where'][] = "u.{$this->uid_name} IN ({$include_ids})"; $sql['orderby'] = "ORDER BY FIELD(u.{$this->uid_name}, {$include_ids})"; @@ -422,9 +414,7 @@ public function prepare_user_ids_query() { /* WHERE *************************************************************/ // An array containing nothing but 0 should always fail. - if ( ! empty( $include_ids_sql ) ) { - $sql['where'][] = "u.{$this->uid_name} IN ({$include_ids_sql})"; - } else if ( is_array( $include_ids ) && 1 === count( $include_ids ) && 0 == reset( $include_ids ) ) { + if ( is_array( $include_ids ) && 1 === count( $include_ids ) && 0 == reset( $include_ids ) ) { $sql['where'][] = $this->no_results['where']; } elseif ( ! empty( $include_ids ) ) { $include_ids = implode( ',', wp_parse_id_list( $include_ids ) ); @@ -727,10 +717,6 @@ public function get_include_ids( $include = array() ) { return $include; } - public function get_include_ids_sql( $include = array() ) { - return ''; - } - /** * Perform a database query to populate any extra metadata we might need. * diff --git a/src/bp-groups/bp-groups-functions.php b/src/bp-groups/bp-groups-functions.php index 623b05f544..0ba632c1b1 100644 --- a/src/bp-groups/bp-groups-functions.php +++ b/src/bp-groups/bp-groups-functions.php @@ -921,7 +921,7 @@ function groups_get_group_members( $args = array() ) { $cache_key = 'bp_groups_get_group_members_' . md5( maybe_serialize( $group_member_args ) ); if ( ! isset( $cache[ $cache_key ] ) ) { // Perform the group member query (extends BP_User_Query). - $members = new BP_Group_Member_Query( $group_member_args ); + $members = new BB_Group_Member_Query( $group_member_args ); $cache[ $cache_key ] = $members; } else { diff --git a/src/bp-groups/classes/class-bb-group-member-query.php b/src/bp-groups/classes/class-bb-group-member-query.php new file mode 100644 index 0000000000..b59f17a193 --- /dev/null +++ b/src/bp-groups/classes/class-bb-group-member-query.php @@ -0,0 +1,476 @@ +query_vars_raw['type'] ) ) { + $this->query_vars_raw['type'] = 'last_joined'; + } + + // Set the sort order. + add_action( 'bp_pre_user_query', array( $this, 'set_orderby' ) ); + + add_filter( 'bp_user_query_join_sql', array( $this, 'group_user_query_join_sql' ), 10, 2 ); + add_filter( 'bp_user_query_where_sql', array( $this, 'group_user_query_where_sql' ), 10, 2 ); + + // Set up our populate_extras method. + add_action( 'bp_user_query_populate_extras', array( $this, 'populate_group_member_extras' ), 10, 2 ); + } + + public function group_user_query_join_sql( $sql_select, $uid_name ) { + global $wpdb, $bp; + + $this->query_vars = bp_parse_args( + $this->query_vars, + array( + 'group_id' => 0, + 'group_role' => array( 'member' ), + 'is_confirmed' => true, + 'invite_sent' => null, + 'inviter_id' => null, + 'type' => 'last_joined', + ), + 'bp_group_member_query_join_sql' + ); + + $u_field = 'u.' . $uid_name; + + // GROUP MEMBER JOIN LOGIC + // Add a JOIN clause to include group members. + $this->inviter_sql = $this->get_inviter_sql( $this ); + if ( ! empty( $this->inviter_sql ) ) { + $invites_table_name = BP_Invitation_Manager::get_table_name(); + $group_member_join = "LEFT JOIN {$bp->groups->table_name_members} gm ON {$u_field} = gm.user_id"; + $inviter_join = "LEFT JOIN {$invites_table_name} i ON {$u_field} = i.user_id "; + $group_member_join = $group_member_join . ' ' . $inviter_join; + remove_filter( 'bp_user_query_where_sql', array( $this, 'group_user_query_where_sql' ), 10, 2 ); + add_filter( 'bp_user_query_where_sql', array( $this, 'group_user_invite_query_where_sql' ), 10, 2 ); + + } else { + $group_member_join = "INNER JOIN {$bp->groups->table_name_members} gm ON {$u_field} = gm.user_id"; + } + + if ( ! empty( $this->query_vars['type'] ) && 'group_activity' == $this->query_vars['type'] && bp_is_active( 'activity' ) ) { + $activity_sql = $this->get_activity_order_sql( $this ); + $group_member_join = $group_member_join . ' INNER JOIN (' . $activity_sql . ' ) a'; + } + + remove_filter( 'bp_user_query_join_sql', array( $this, 'group_user_query_join_sql' ), 10, 2 ); + + return $sql_select . ' ' . $group_member_join; + } + + public function group_user_query_where_sql( $where, $uid_name ) { + global $wpdb; + + // Add group member conditions to the WHERE clause. + $group_ids = wp_parse_id_list( $this->query_vars['group_id'] ); + $group_ids = implode( ',', $group_ids ); + $where[] = "gm.group_id IN ({$group_ids})"; + + // If is_confirmed. + $is_confirmed = empty( $this->query_vars['is_confirmed'] ) ? 0 : 1; + $where[] = $wpdb->prepare( 'gm.is_confirmed = %d', $is_confirmed ); + + // If invite_sent. + if ( ! is_null( $this->query_vars['invite_sent'] ) ) { + $invite_sent = ! empty( $this->query_vars['invite_sent'] ) ? 1 : 0; + $where[] = $wpdb->prepare( 'gm.invite_sent = %d', $invite_sent ); + } + + // If inviter_id. + if ( ! is_null( $this->query_vars['inviter_id'] ) ) { + $inviter_id = $this->query_vars['inviter_id']; + + // Empty: inviter_id = 0. (pass false, 0, or empty array). + if ( empty( $inviter_id ) ) { + $where[] = 'gm.inviter_id = 0'; + + // The string 'any' matches any non-zero value (inviter_id != 0). + } elseif ( 'any' === $inviter_id ) { + $where[] = 'gm.inviter_id != 0'; + + // Assume that a list of inviter IDs has been passed. + } else { + // Parse and sanitize. + $inviter_ids = wp_parse_id_list( $inviter_id ); + if ( ! empty( $inviter_ids ) ) { + $inviter_ids_sql = implode( ',', $inviter_ids ); + $where[] = "gm.inviter_id IN ({$inviter_ids_sql})"; + } + } + } + + // Role information is stored as follows: admins have + // is_admin = 1, mods have is_mod = 1, banned have is_banned = + // 1, and members have all three set to 0. + $roles = ! empty( $this->query_vars['group_role'] ) ? $this->query_vars['group_role'] : array(); + if ( is_string( $roles ) ) { + $roles = explode( ',', $roles ); + } + + // Sanitize: Only 'admin', 'mod', 'member', and 'banned' are valid. + $allowed_roles = array( 'admin', 'mod', 'member', 'banned' ); + foreach ( $roles as $role_key => $role_value ) { + if ( ! in_array( $role_value, $allowed_roles ) ) { + unset( $roles[ $role_key ] ); + } + } + + $roles = array_unique( $roles ); + + // When querying for a set of roles containing 'member' (for + // which there is no dedicated is_ column), figure out a list + // of columns *not* to match. + $roles_sql = ''; + if ( in_array( 'member', $roles ) ) { + $role_columns = array(); + foreach ( array_diff( $allowed_roles, $roles ) as $excluded_role ) { + $role_columns[] = 'gm.is_' . $excluded_role . ' = 0'; + } + + if ( ! empty( $role_columns ) ) { + $roles_sql = '(' . implode( ' AND ', $role_columns ) . ')'; + } + + // When querying for a set of roles *not* containing 'member', + // simply construct a list of is_* = 1 clauses. + } else { + $role_columns = array(); + foreach ( $roles as $role ) { + $role_columns[] = 'gm.is_' . $role . ' = 1'; + } + + if ( ! empty( $role_columns ) ) { + $roles_sql = '(' . implode( ' OR ', $role_columns ) . ')'; + } + } + + if ( ! empty( $roles_sql ) ) { + $where[] = $roles_sql; + } + + remove_filter( 'bp_user_query_where_sql', array( $this, 'group_user_query_where_sql' ), 10, 2 ); + + return $where; + } + + public function group_user_invite_query_where_sql( $where, $uid_name ) { + if ( ! empty( $this->inviter_sql ) ) { + $group_where = implode( ' AND ', $this->group_user_query_where_sql( array(), $uid_name ) ); + $inviter_join = str_replace( 'WHERE i.class', 'i.class', $this->inviter_sql['where'] ); + $where[] = "(gm.user_id IS NOT NULL OR i.user_id IS NOT NULL) AND ( ({$group_where}) OR ({$inviter_join}) )"; + } + + remove_filter( 'bp_user_query_where_sql', array( $this, 'group_user_invite_query_where_sql' ), 10, 2 ); + + return $where; + } + + /** + * Get a list of user_ids to include in the IN clause of the main query. + * + * Overrides BP_User_Query::get_include_ids(), adding our additional + * group-member logic. + * + * @since BuddyPress 1.8.0 + * + * @param array $include Existing group IDs in the $include parameter, + * as calculated in BP_User_Query. + * @return array + */ + public function get_include_ids( $include = array() ) { + + return $include; + } + + /** + * Tell BP_User_Query to order by the order of our query results. + * + * We only override BP_User_Query's native ordering in case of the + * 'last_joined' and 'first_joined' $type parameters. + * + * @since BuddyPress 1.8.1 + * + * @param BP_User_Query $query BP_User_Query object. + */ + public function set_orderby( $query ) { + + if ( in_array( $query->query_vars['type'], array( 'last_joined', 'first_joined', 'group_activity', 'group_role' ) ) ) { + if ( ! empty( $query->query_vars['type'] ) && 'group_activity' == $query->query_vars['type'] && bp_is_active( 'activity' ) ) { + $query->uid_clauses['orderby'] = 'ORDER BY a.latest_date'; + } elseif ( $query->query_vars['type'] === 'group_role' ) { + $query->uid_clauses['orderby'] = 'ORDER BY gm.is_admin DESC, gm.is_mod DESC, gm.date_modified DESC, gm.user_id ASC'; + } else { + $query->uid_clauses['orderby'] = 'ORDER BY gm.date_modified'; + } + + $query->uid_clauses['order'] = 'first_joined' === $query->query_vars['type'] ? 'ASC' : $query->uid_clauses['order']; + } + + + // Prevent this filter from running on future BP_User_Query + // instances on the same page. + remove_action( 'bp_pre_user_query', array( $this, 'set_orderby' ) ); + } + + /** + * Fetch additional data required in bp_group_has_members() loops. + * + * Additional data fetched: + * - is_banned + * - date_modified + * + * @since BuddyPress 1.8.0 + * + * @param BP_User_Query $query BP_User_Query object. Because we're + * filtering the current object, we use + * $this inside of the method instead. + * @param string $user_ids_sql Sanitized, comma-separated string of + * the user ids returned by the main query. + */ + public function populate_group_member_extras( $query, $user_ids_sql ) { + global $wpdb; + static $cache = array(); + + $bp = buddypress(); + + if ( is_array( $this->query_vars['group_id'] ) ) { + $group_ids = wp_parse_id_list( $this->query_vars['group_id'] ); + } else { + $group_ids = wp_parse_id_list( explode( ',', $this->query_vars['group_id'] ) ); + } + + $cache_key = 'bb_populate_group_member_extras_' . str_replace( ',', '_', implode( ',', $group_ids ) ) . '_' . str_replace( ',', '_', $user_ids_sql ); + if ( ! isset( $cache[ $cache_key ] ) ) { + + $sql = "SELECT id, user_id, date_modified, is_admin, is_mod, comments, user_title, invite_sent, is_confirmed, inviter_id, is_banned FROM {$bp->groups->table_name_members} WHERE user_id IN ({$user_ids_sql}) AND group_id IN ( " . implode( ', ', array_fill( 0, count( $group_ids ), '%s' ) ) . ' )'; + + // Call $wpdb->prepare passing the values of the array as separate arguments. + $query = call_user_func_array( array( $wpdb, 'prepare' ), array_merge( array( $sql ), $group_ids ) ); + + $extras = $wpdb->get_results( $query ); + $cache[ $cache_key ] = $extras; + } else { + $extras = $cache[ $cache_key ]; + } + + foreach ( (array) $extras as $extra ) { + if ( isset( $this->results[ $extra->user_id ] ) ) { + // The user_id is provided for backward compatibility. + $this->results[ $extra->user_id ]->user_id = (int) $extra->user_id; + $this->results[ $extra->user_id ]->is_admin = (int) $extra->is_admin; + $this->results[ $extra->user_id ]->is_mod = (int) $extra->is_mod; + $this->results[ $extra->user_id ]->is_banned = (int) $extra->is_banned; + $this->results[ $extra->user_id ]->date_modified = $extra->date_modified; + $this->results[ $extra->user_id ]->user_title = $extra->user_title; + $this->results[ $extra->user_id ]->comments = $extra->comments; + $this->results[ $extra->user_id ]->invite_sent = (int) $extra->invite_sent; + $this->results[ $extra->user_id ]->inviter_id = (int) $extra->inviter_id; + $this->results[ $extra->user_id ]->is_confirmed = (int) $extra->is_confirmed; + $this->results[ $extra->user_id ]->membership_id = (int) $extra->id; + } + } + + // Add accurate invitation info from the invitations table. + $invites = groups_get_invites( + array( + 'user_id' => $user_ids_sql, + 'item_id' => $this->query_vars['group_id'], + 'type' => 'all', + ) + ); + foreach ( $invites as $invite ) { + if ( isset( $this->results[ $invite->user_id ] ) ) { + $this->results[ $invite->user_id ]->comments = $invite->content; + $this->results[ $invite->user_id ]->is_confirmed = 0; + $this->results[ $invite->user_id ]->invitation_id = $invite->id; + $this->results[ $invite->user_id ]->invite_sent = (int) $invite->invite_sent; + $this->results[ $invite->user_id ]->inviter_id = $invite->inviter_id; + + // Backfill properties that are not being set above. + if ( ! isset( $this->results[ $invite->user_id ]->user_id ) ) { + $this->results[ $invite->user_id ]->user_id = $invite->user_id; + } + if ( ! isset( $this->results[ $invite->user_id ]->is_admin ) ) { + $this->results[ $invite->user_id ]->is_admin = 0; + } + if ( ! isset( $this->results[ $invite->user_id ]->is_mod ) ) { + $this->results[ $invite->user_id ]->is_mod = 0; + } + if ( ! isset( $this->results[ $invite->user_id ]->is_banned ) ) { + $this->results[ $invite->user_id ]->is_banned = 0; + } + if ( ! isset( $this->results[ $invite->user_id ]->date_modified ) ) { + $this->results[ $invite->user_id ]->date_modified = $invite->date_modified; + } + if ( ! isset( $this->results[ $invite->user_id ]->user_title ) ) { + $this->results[ $invite->user_id ]->user_title = ''; + } + if ( ! isset( $this->results[ $invite->user_id ]->membership_id ) ) { + $this->results[ $invite->user_id ]->membership_id = 0; + } + } + } + + // Don't filter other BP_User_Query objects on the same page. + remove_action( 'bp_user_query_populate_extras', array( $this, 'populate_group_member_extras' ), 10 ); + } + + /** + * Sort user IDs by how recently they have generated activity within a given group. + * + * @since BuddyPress 2.1.0 + * + * @param BP_User_Query $query BP_User_Query object. + * @param array $gm_ids array of group member ids. + * + * @return string + */ + public function get_activity_order_sql( $query ) { + global $wpdb; + + $return_sql = ''; + + if ( ! bp_is_active( 'activity' ) ) { + return $return_sql; + } + + $activity_table = buddypress()->activity->table_name; + + $sql = array( + 'select' => "SELECT user_id, max( date_recorded ) as latest_date FROM {$activity_table}", + 'where' => array(), + 'groupby' => 'GROUP BY user_id', + 'orderby' => 'ORDER BY date_recorded', + 'order' => 'DESC', + ); + + $sql['where'] = array( + 'item_id = ' . absint( $query->query_vars['group_id'] ), + $wpdb->prepare( 'component = %s', buddypress()->groups->id ), + ); + + $sql['where'] = 'WHERE ' . implode( ' AND ', $sql['where'] ); + + return $wpdb->prepare( "{$sql['select']} {$sql['where']} {$sql['groupby']} {$sql['orderby']} {$sql['order']}" ); + } + + public function get_inviter_sql( $query ) { + global $wpdb; + + $invited_member_sql = array(); + + $is_confirmed = ! empty( $query->query_vars['is_confirmed'] ) ? 1 : 0; + + // If appropriate, fetch invitations and add them to the results. + if ( ! $is_confirmed || ! is_null( $query->query_vars['invite_sent'] ) || ! is_null( $query->query_vars['inviter_id'] ) ) { + $invite_args = array( + 'item_id' => $query->query_vars['group_id'], + 'fields' => 'user_ids', + 'type' => 'all', + ); + + if ( ! is_null( $query->query_vars['invite_sent'] ) ) { + $invite_args['invite_sent'] = ! empty( $query->query_vars['invite_sent'] ) ? 'sent' : 'draft'; + } + + // If inviter_id. + if ( ! is_null( $query->query_vars['inviter_id'] ) ) { + $inviter_id = $query->query_vars['inviter_id']; + + // Empty: inviter_id = 0. (pass false, 0, or empty array). + if ( empty( $inviter_id ) ) { + $invite_args['type'] = 'request'; + + /* + * The string 'any' matches any non-zero value (inviter_id != 0). + * These are invitations, not requests. + */ + } elseif ( 'any' === $inviter_id ) { + $invite_args['type'] = 'invite'; + + // Assume that a list of inviter IDs has been passed. + } else { + $invite_args['type'] = 'invite'; + // Parse and sanitize. + $inviter_ids = wp_parse_id_list( $inviter_id ); + if ( ! empty( $inviter_ids ) ) { + $invite_args['inviter_id'] = $inviter_ids; + } + } + } + + $invite_args['retval'] = 'sql'; + + $invited_member_sql = groups_get_invites( $invite_args ); + } + + return $invited_member_sql; + } +} diff --git a/src/bp-groups/classes/class-bp-group-member-query.php b/src/bp-groups/classes/class-bp-group-member-query.php index cf7809406d..b31986afd2 100644 --- a/src/bp-groups/classes/class-bp-group-member-query.php +++ b/src/bp-groups/classes/class-bp-group-member-query.php @@ -48,15 +48,6 @@ class BP_Group_Member_Query extends BP_User_Query { */ protected $group_member_ids; - /** - * Array of group member ids, cached to prevent redundant lookups SQL - * - * @since BuddyBoss [BBVERSION] - * - * @var null|array Null if not yet defined, otherwise an array of ints. - */ - protected $group_member_ids_sql; - /** * Set up action hooks. * @@ -508,248 +499,4 @@ public function get_gm_ids_ordered_by_activity( $query, $gm_ids = array() ) { return wp_list_pluck( $group_user_ids, 'user_id' ); } - - protected function get_group_member_ids_sql( $include = array() ) { - global $wpdb; - - if ( ! empty( $this->group_member_ids_sql ) ) { - return $this->group_member_ids_sql; - } - - $bp = buddypress(); - $sql = array( - 'select' => "SELECT user_id FROM {$bp->groups->table_name_members}", - 'where' => array(), - 'orderby' => '', - 'order' => '', - ); - - /* WHERE clauses *****************************************************/ - - // Group id. - $group_ids = wp_parse_id_list( $this->query_vars['group_id'] ); - $group_ids = implode( ',', $group_ids ); - $sql['where'][] = "group_id IN ({$group_ids})"; - - // If is_confirmed. - $is_confirmed = ! empty( $this->query_vars['is_confirmed'] ) ? 1 : 0; - $sql['where'][] = $wpdb->prepare( 'is_confirmed = %d', $is_confirmed ); - - // If invite_sent. - if ( ! is_null( $this->query_vars['invite_sent'] ) ) { - $invite_sent = ! empty( $this->query_vars['invite_sent'] ) ? 1 : 0; - $sql['where'][] = $wpdb->prepare( 'invite_sent = %d', $invite_sent ); - } - - if ( ! empty( $include ) ) { - $include_ids = wp_parse_id_list( $include ); - $include_ids = implode( ',', $include_ids ); - $sql['where'][] = "user_id IN ({$include_ids})"; - } - - // If inviter_id. - if ( ! is_null( $this->query_vars['inviter_id'] ) ) { - $inviter_id = $this->query_vars['inviter_id']; - - // Empty: inviter_id = 0. (pass false, 0, or empty array). - if ( empty( $inviter_id ) ) { - $sql['where'][] = 'inviter_id = 0'; - - // The string 'any' matches any non-zero value (inviter_id != 0). - } elseif ( 'any' === $inviter_id ) { - $sql['where'][] = 'inviter_id != 0'; - - // Assume that a list of inviter IDs has been passed. - } else { - // Parse and sanitize. - $inviter_ids = wp_parse_id_list( $inviter_id ); - if ( ! empty( $inviter_ids ) ) { - $inviter_ids_sql = implode( ',', $inviter_ids ); - $sql['where'][] = "inviter_id IN ({$inviter_ids_sql})"; - } - } - } - - // Role information is stored as follows: admins have - // is_admin = 1, mods have is_mod = 1, banned have is_banned = - // 1, and members have all three set to 0. - $roles = ! empty( $this->query_vars['group_role'] ) ? $this->query_vars['group_role'] : array(); - if ( is_string( $roles ) ) { - $roles = explode( ',', $roles ); - } - - // Sanitize: Only 'admin', 'mod', 'member', and 'banned' are valid. - $allowed_roles = array( 'admin', 'mod', 'member', 'banned' ); - foreach ( $roles as $role_key => $role_value ) { - if ( ! in_array( $role_value, $allowed_roles ) ) { - unset( $roles[ $role_key ] ); - } - } - - $roles = array_unique( $roles ); - - // When querying for a set of roles containing 'member' (for - // which there is no dedicated is_ column), figure out a list - // of columns *not* to match. - $roles_sql = ''; - if ( in_array( 'member', $roles ) ) { - $role_columns = array(); - foreach ( array_diff( $allowed_roles, $roles ) as $excluded_role ) { - $role_columns[] = 'is_' . $excluded_role . ' = 0'; - } - - if ( ! empty( $role_columns ) ) { - $roles_sql = '(' . implode( ' AND ', $role_columns ) . ')'; - } - - // When querying for a set of roles *not* containing 'member', - // simply construct a list of is_* = 1 clauses. - } else { - $role_columns = array(); - foreach ( $roles as $role ) { - $role_columns[] = 'is_' . $role . ' = 1'; - } - - if ( ! empty( $role_columns ) ) { - $roles_sql = '(' . implode( ' OR ', $role_columns ) . ')'; - } - } - - if ( ! empty( $roles_sql ) ) { - $sql['where'][] = $roles_sql; - } - - $sql['where'] = ! empty( $sql['where'] ) ? 'WHERE ' . implode( ' AND ', $sql['where'] ) : ''; - - // We fetch group members in order of last_joined, regardless - // of 'type'. If the 'type' value is not 'last_joined' or - // 'first_joined', the order will be overridden in - // BP_Group_Member_Query::set_orderby(). - if ( $this->query_vars['type'] === 'group_role' ) { - $sql['orderby'] = 'ORDER BY -is_admin, -is_mod, date_modified'; - } else { - $sql['orderby'] = 'ORDER BY date_modified'; - } - - $sql['order'] = 'first_joined' === $this->query_vars['type'] ? 'ASC' : 'DESC'; - if ( $this->query_vars['type'] === 'group_role' ) { - $sql['order'] = $sql['order'] . ', user_id'; - } - - $invited_member_ids_sql = ''; - - // If appropriate, fetch invitations and add them to the results. - if ( ! $is_confirmed || ! is_null( $this->query_vars['invite_sent'] ) || ! is_null( $this->query_vars['inviter_id'] ) ) { - $invite_args = array( - 'item_id' => $this->query_vars['group_id'], - 'fields' => 'user_ids', - 'type' => 'all', - ); - - if ( ! is_null( $this->query_vars['invite_sent'] ) ) { - $invite_args['invite_sent'] = ! empty( $this->query_vars['invite_sent'] ) ? 'sent' : 'draft'; - } - - if ( ! empty( $include ) ) { - $invite_args['user_id'] = $include; - } - - // If inviter_id. - if ( ! is_null( $this->query_vars['inviter_id'] ) ) { - $inviter_id = $this->query_vars['inviter_id']; - - // Empty: inviter_id = 0. (pass false, 0, or empty array). - if ( empty( $inviter_id ) ) { - $invite_args['type'] = 'request'; - - /* - * The string 'any' matches any non-zero value (inviter_id != 0). - * These are invitations, not requests. - */ - } elseif ( 'any' === $inviter_id ) { - $invite_args['type'] = 'invite'; - - // Assume that a list of inviter IDs has been passed. - } else { - $invite_args['type'] = 'invite'; - // Parse and sanitize. - $inviter_ids = wp_parse_id_list( $inviter_id ); - if ( ! empty( $inviter_ids ) ) { - $invite_args['inviter_id'] = $inviter_ids; - } - } - } - - /* - * If first_joined is the "type" of query, sort the oldest - * requests and invitations to the top. - */ - if ( 'first_joined' === $this->query_vars['type'] ) { - $invite_args['order_by'] = 'date_modified'; - $invite_args['sort_order'] = 'ASC'; - } - - $invite_args['retval'] = 'sql'; - - $invited_member_ids_sql = groups_get_invites( $invite_args ); - } - - if ( ! empty( $invited_member_ids_sql ) ) { - $group_member_ids_sql = "{$sql['select']} {$sql['where']}"; - $this->group_member_ids_sql = $group_member_ids_sql . ' UNION ' . $invited_member_ids_sql; - } else { - $group_member_ids_sql = "{$sql['select']} {$sql['where']} {$sql['orderby']} {$sql['order']}"; - $this->group_member_ids_sql = $group_member_ids_sql; - } - - /** - * Filters the member IDs for the current group member query. - * - * Use this filter to build a custom query (such as when you've - * defined a custom 'type'). - * - * @since BuddyBoss [BBVERSION] - * - * @param array $group_member_ids_sql Array of associated member IDs SQL. - * @param BP_Group_Member_Query $this Current BP_Group_Member_Query instance. - */ - $this->group_member_ids_sql = apply_filters( 'bp_group_member_query_group_member_ids_sql', $this->group_member_ids_sql, $this ); - - return $this->group_member_ids_sql; - } - - /** - * Get a list of user_ids to include in the IN clause of the main query. - * - * Overrides BP_User_Query::get_include_ids(), adding our additional - * group-member logic. - * - * @since BuddyPress 1.8.0 - * - * @param array $include Existing group IDs in the $include parameter, - * as calculated in BP_User_Query. - * @return array - */ - public function get_include_ids_sql( $include = array() ) { - // The following args are specific to group member queries, and - // are not present in the query_vars of a normal BP_User_Query. - // We loop through to make sure that defaults are set (though - // values passed to the constructor will, as usual, override - // these defaults). - $this->query_vars = bp_parse_args( - $this->query_vars, - array( - 'group_id' => 0, - 'group_role' => array( 'member' ), - 'is_confirmed' => true, - 'invite_sent' => null, - 'inviter_id' => null, - 'type' => 'last_joined', - ), - 'bp_group_member_query_get_include_ids' - ); - - - return $this->get_group_member_ids_sql( $include ); - } } diff --git a/src/bp-groups/classes/class-bp-groups-invite-template.php b/src/bp-groups/classes/class-bp-groups-invite-template.php index c94517c459..c9d6d6a66b 100644 --- a/src/bp-groups/classes/class-bp-groups-invite-template.php +++ b/src/bp-groups/classes/class-bp-groups-invite-template.php @@ -110,7 +110,7 @@ public function __construct( $args = array() ) { $this->pag_page = bp_sanitize_pagination_arg( $this->pag_arg, $r['page'] ); $this->pag_num = bp_sanitize_pagination_arg( 'num', $r['per_page'] ); - $iquery = new BP_Group_Member_Query( + $iquery = new BB_Group_Member_Query( array( 'group_id' => $r['group_id'], 'type' => 'first_joined', diff --git a/src/class-buddypress.php b/src/class-buddypress.php index beae16027e..f678797791 100644 --- a/src/class-buddypress.php +++ b/src/class-buddypress.php @@ -694,6 +694,7 @@ public function autoload( $class ) { 'BP_Core_Follow_Follower_Widget' => 'core', 'BP_Group_Extension' => 'groups', 'BP_Group_Member_Query' => 'groups', + 'BB_Group_Member_Query' => 'groups', 'BP_Core_Members_Template' => 'members', 'BP_Core_Members_Widget' => 'members', 'BP_Core_Recently_Active_Widget' => 'members',